diff --git a/DEPS b/DEPS index 5419b025..6ad5773 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': '750261f41af6fc636d64d4431cee2eae67d49d84', + 'skia_revision': 'e61500059aa7471a65631da81aae70bd1111e5be', # 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': '69b996bd9bcec21debfa319c5111697c03f8c77d', + 'v8_revision': '8c06327064717567a0723117ea9e45ad0e0e98e5', # 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. @@ -211,7 +211,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': 'b3c1e71eb1cb55ba78a3f884ab4e68ef1bd396da', + 'swiftshader_revision': '6d93a63356e12fc9945ba0cd40a2125cc8802416', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. @@ -258,7 +258,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '74f8dbb9578277e945548fa2e3378ec426dc2c69', + 'catapult_revision': '83c2cb1060772ddd0e096c49918785afb11148b4', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -266,7 +266,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling devtools-frontend # and whatever else without interference from each other. - 'devtools_frontend_revision': '0afca615a816673ed828161238d98c5d8483b635', + 'devtools_frontend_revision': '256b2c2587679c74a8fbdaeb9d0b1601c22e889f', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libprotobuf-mutator # and whatever else without interference from each other. @@ -881,7 +881,7 @@ # Tools used when building Chrome for Chrome OS. This affects both the Simple # Chrome workflow, as well as the chromeos-chrome ebuild. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'af5911446cd05354464bc60274f91c6a304d6ade', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'e6a8f4ed40bbe1622f7b3356655175cb69171ea0', 'condition': 'checkout_chromeos', }, @@ -901,7 +901,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '1407cfd9e5f4de4cf9bd04ecc435ee5b760675c1', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '422c039e8e1b95402a10734e1c1e376084fbd15e', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), @@ -1237,7 +1237,7 @@ Var('chromium_git') + '/external/github.com/cisco/openh264' + '@' + '3dd5b80bc4f172dd82925bb259cb7c82348409c5', 'src/third_party/openscreen/src': - Var('chromium_git') + '/openscreen' + '@' + '25493aef9427e1a0d93d993b441dec9e64266725', + Var('chromium_git') + '/openscreen' + '@' + 'dee4a03873a1ee6e09a5c4c43faa653470eba795', 'src/third_party/openxr/src': { 'url': Var('chromium_git') + '/external/github.com/KhronosGroup/OpenXR-SDK' + '@' + '9e97b73e7dd2bfc07745489d728f6a36665c648f', @@ -1486,7 +1486,7 @@ }, 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'c401923f3ee3b4ec5423a3ede7e91550e2acd52d', + Var('webrtc_git') + '/src.git' + '@' + '04482985b2041a91f4282ce4a3e7bb3716a621f1', 'src/third_party/libgifcodec': Var('skia_git') + '/libgifcodec' + '@'+ Var('libgifcodec_revision'), @@ -1577,7 +1577,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/media_app/app', - 'version': 't7oX_wB80ik282fRV1dJNehd9v-uldOkRpj9yVV25WwC', + 'version': 'F5O08dsIWdHTa7NozxSJmHAyJsTLlm6Zxo9jTQjw1qEC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/android_webview/browser/aw_browser_terminator.cc b/android_webview/browser/aw_browser_terminator.cc index 5d54028b..4d6a61c 100644 --- a/android_webview/browser/aw_browser_terminator.cc +++ b/android_webview/browser/aw_browser_terminator.cc
@@ -10,7 +10,10 @@ #include "android_webview/browser/aw_browser_process.h" #include "android_webview/browser/aw_render_process_gone_delegate.h" #include "android_webview/common/aw_descriptors.h" +#include "android_webview/common/crash_reporter/crash_keys.h" #include "base/android/scoped_java_ref.h" +#include "base/debug/crash_logging.h" +#include "base/debug/dump_without_crashing.h" #include "base/logging.h" #include "base/stl_util.h" #include "base/strings/stringprintf.h" @@ -123,6 +126,20 @@ LOG(ERROR) << "Renderer process (" << info.pid << ") crash detected (code " << info.crash_signo << ")."; + if (info.crash_signo == + crash_reporter::ChildExitObserver::TerminationInfo::kInvalidSigno) { + static auto* termination_info_key = base::debug::AllocateCrashKeyString( + crash_keys::kTerminationInfo, base::debug::CrashKeySize::Size32); + std::ostringstream stream; + stream << info.was_killed_intentionally_by_browser << " " + << info.renderer_shutdown_requested << " " + << info.threw_exception_during_init << " " + << info.renderer_has_visible_clients; + base::debug::SetCrashKeyString(termination_info_key, stream.str()); + base::debug::DumpWithoutCrashing(); + base::debug::ClearCrashKeyString(termination_info_key); + } + std::vector<ScopedJavaGlobalRef<jobject>> java_web_contents; GetJavaWebContentsForRenderProcess(rph, &java_web_contents);
diff --git a/android_webview/common/crash_reporter/crash_keys.cc b/android_webview/common/crash_reporter/crash_keys.cc index 83c5512..07d647e 100644 --- a/android_webview/common/crash_reporter/crash_keys.cc +++ b/android_webview/common/crash_reporter/crash_keys.cc
@@ -15,6 +15,7 @@ const char kAppProcessName[] = "app-process-name"; const char kAndroidSdkInt[] = "android-sdk-int"; +const char kTerminationInfo[] = "termination-info"; const char kSupportLibraryWebkitVersion[] = "androidx-webkit-version"; @@ -28,6 +29,7 @@ kAppProcessName, kAndroidSdkInt, kSupportLibraryWebkitVersion, + kTerminationInfo, // process type "ptype",
diff --git a/android_webview/common/crash_reporter/crash_keys.h b/android_webview/common/crash_reporter/crash_keys.h index fbf1d0d..22320d5 100644 --- a/android_webview/common/crash_reporter/crash_keys.h +++ b/android_webview/common/crash_reporter/crash_keys.h
@@ -22,6 +22,7 @@ extern const char kAppProcessName[]; extern const char kAndroidSdkInt[]; +extern const char kTerminationInfo[]; extern const char kSupportLibraryWebkitVersion[];
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/services/CrashReceiverServiceTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/services/CrashReceiverServiceTest.java index e4be9301..8940b07f 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/services/CrashReceiverServiceTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/services/CrashReceiverServiceTest.java
@@ -22,6 +22,7 @@ import org.chromium.android_webview.services.CrashReceiverService; import org.chromium.android_webview.test.AwJUnit4ClassRunner; import org.chromium.android_webview.test.OnlyRunIn; +import org.chromium.base.test.util.Batch; import java.io.File; import java.io.FileInputStream; @@ -30,10 +31,12 @@ import java.util.Map; /** - * Instrumentation tests for CrashReceiverService. + * Instrumentation tests for CrashReceiverService. These tests are batched as UNIT_TESTS because + * they don't actually launch any services or other components. */ @RunWith(AwJUnit4ClassRunner.class) @OnlyRunIn(SINGLE_PROCESS) +@Batch(Batch.UNIT_TESTS) public class CrashReceiverServiceTest { private static final String TEST_CRASH_LOCAL_ID = "abc1234"; private static final String TEST_CRASH_FILE_NAME =
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/services/MetricsBridgeServiceTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/services/MetricsBridgeServiceTest.java index 7ec7556..d67b83f 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/services/MetricsBridgeServiceTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/services/MetricsBridgeServiceTest.java
@@ -5,16 +5,14 @@ package org.chromium.android_webview.test.services; import static org.chromium.android_webview.test.OnlyRunIn.ProcessMode.SINGLE_PROCESS; +import static org.chromium.android_webview.test.services.MetricsBridgeServiceUnitTest.RETRIEVE_METRICS_TASK_STATUS_SUCCESS_RECORD; import android.content.Context; import android.content.Intent; -import android.os.IBinder; import androidx.test.filters.MediumTest; -import org.junit.After; import org.junit.Assert; -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -22,152 +20,19 @@ import org.chromium.android_webview.proto.MetricsBridgeRecords.HistogramRecord; import org.chromium.android_webview.proto.MetricsBridgeRecords.HistogramRecord.RecordType; import org.chromium.android_webview.services.MetricsBridgeService; -import org.chromium.android_webview.test.AwActivityTestRule; import org.chromium.android_webview.test.AwJUnit4ClassRunner; import org.chromium.android_webview.test.OnlyRunIn; import org.chromium.base.ContextUtils; -import org.chromium.base.FileUtils; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; import java.util.List; -import java.util.concurrent.FutureTask; /** - * Test MetricsBridgeService. + * Instrumentation tests MetricsBridgeService. These tests are not batched to make sure all unbinded + * services are properly killed between tests. */ @RunWith(AwJUnit4ClassRunner.class) @OnlyRunIn(SINGLE_PROCESS) public class MetricsBridgeServiceTest { - private static final byte[] PARSING_LOG_RESULT_SUCCESS_RECORD = - HistogramRecord.newBuilder() - .setRecordType(RecordType.HISTOGRAM_LINEAR) - .setHistogramName("Android.WebView.NonEmbeddedMetrics.ParsingLogResult") - .setSample(MetricsBridgeService.ParsingLogResult.SUCCESS) - .setMin(1) - .setMax(MetricsBridgeService.ParsingLogResult.COUNT) - .setNumBuckets(MetricsBridgeService.ParsingLogResult.COUNT + 1) - .build() - .toByteArray(); - - private static final byte[] RETRIEVE_METRICS_TASK_STATUS_SUCCESS_RECORD = - HistogramRecord.newBuilder() - .setRecordType(RecordType.HISTOGRAM_LINEAR) - .setHistogramName( - "Android.WebView.NonEmbeddedMetrics.RetrieveMetricsTaskStatus") - .setSample(MetricsBridgeService.RetrieveMetricsTaskStatus.SUCCESS) - .setMin(1) - .setMax(MetricsBridgeService.RetrieveMetricsTaskStatus.COUNT) - .setNumBuckets(MetricsBridgeService.RetrieveMetricsTaskStatus.COUNT + 1) - .build() - .toByteArray(); - - private File mTempFile; - - @Before - public void setUp() throws IOException { - mTempFile = File.createTempFile("test_webview_metrics_bridge_logs", null); - } - - @After - public void tearDown() { - if (mTempFile.exists()) { - Assert.assertTrue("Failed to delete \"" + mTempFile + "\"", mTempFile.delete()); - } - } - - @Test - @MediumTest - // Test that the service saves metrics records to file - public void testSaveToFile() throws Throwable { - HistogramRecord recordBooleanProto = HistogramRecord.newBuilder() - .setRecordType(RecordType.HISTOGRAM_BOOLEAN) - .setHistogramName("testSaveToFile.boolean") - .setSample(1) - .build(); - HistogramRecord recordLinearProto = HistogramRecord.newBuilder() - .setRecordType(RecordType.HISTOGRAM_LINEAR) - .setHistogramName("testSaveToFile.linear") - .setSample(123) - .setMin(1) - .setMax(1000) - .setNumBuckets(50) - .build(); - ByteArrayOutputStream out = new ByteArrayOutputStream(); - writeRecordsToStream(out, recordBooleanProto, recordLinearProto, recordBooleanProto); - byte[] expectedData = out.toByteArray(); - - // Cannot bind to service using real connection since we need to inject test file name. - MetricsBridgeService service = new MetricsBridgeService(mTempFile); - // Simulate starting the service by calling onCreate() - service.onCreate(); - - IBinder binder = service.onBind(null); - IMetricsBridgeService stub = IMetricsBridgeService.Stub.asInterface(binder); - stub.recordMetrics(recordBooleanProto.toByteArray()); - stub.recordMetrics(recordLinearProto.toByteArray()); - stub.recordMetrics(recordBooleanProto.toByteArray()); - - // Block until all tasks are finished to make sure all records are written to file. - FutureTask<Object> blockTask = service.addTaskToBlock(); - AwActivityTestRule.waitForFuture(blockTask); - - byte[] resultData = FileUtils.readStream(new FileInputStream(mTempFile)); - Assert.assertArrayEquals( - "byte data from file is different from the expected proto byte data", expectedData, - resultData); - } - - @Test - @MediumTest - // Test that service recovers saved data from file, appends new records to it and - // clears the file after a retrieve call. - public void testRetrieveFromFile() throws Throwable { - HistogramRecord recordBooleanProto = - HistogramRecord.newBuilder() - .setRecordType(RecordType.HISTOGRAM_BOOLEAN) - .setHistogramName("testRecoverFromFile.boolean") - .setSample(1) - .build(); - HistogramRecord recordLinearProto = HistogramRecord.newBuilder() - .setRecordType(RecordType.HISTOGRAM_LINEAR) - .setHistogramName("testRecoverFromFile.linear") - .setSample(123) - .setMin(1) - .setMax(1000) - .setNumBuckets(50) - .build(); - // write Initial proto data To File - writeRecordsToStream(new FileOutputStream(mTempFile), recordBooleanProto, recordLinearProto, - recordBooleanProto); - - // Cannot bind to service using real connection since we need to inject test file name. - MetricsBridgeService service = new MetricsBridgeService(mTempFile); - // Simulate starting the service by calling onCreate() - service.onCreate(); - - IBinder binder = service.onBind(null); - IMetricsBridgeService stub = IMetricsBridgeService.Stub.asInterface(binder); - stub.recordMetrics(recordBooleanProto.toByteArray()); - List<byte[]> retrievedDataList = stub.retrieveNonembeddedMetrics(); - - byte[][] expectedData = new byte[][] {recordBooleanProto.toByteArray(), - recordLinearProto.toByteArray(), recordBooleanProto.toByteArray(), - PARSING_LOG_RESULT_SUCCESS_RECORD, recordBooleanProto.toByteArray(), - RETRIEVE_METRICS_TASK_STATUS_SUCCESS_RECORD}; - - // Assert file is deleted after the retrieve call - Assert.assertFalse( - "file should be deleted after retrieve metrics call", mTempFile.exists()); - Assert.assertNotNull("retrieved byte data from the service is null", retrievedDataList); - Assert.assertArrayEquals("retrieved byte data is different from the expected data", - expectedData, retrievedDataList.toArray()); - } - @Test @MediumTest // Test sending data to the service and retrieving it back. @@ -229,12 +94,4 @@ retrievedDataList.toArray()); } } - - private static void writeRecordsToStream(OutputStream os, HistogramRecord... records) - throws IOException { - for (HistogramRecord record : records) { - record.writeDelimitedTo(os); - } - os.close(); - } } \ No newline at end of file
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/services/MetricsBridgeServiceUnitTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/services/MetricsBridgeServiceUnitTest.java new file mode 100644 index 0000000..d73916a --- /dev/null +++ b/android_webview/javatests/src/org/chromium/android_webview/test/services/MetricsBridgeServiceUnitTest.java
@@ -0,0 +1,178 @@ +// 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. + +package org.chromium.android_webview.test.services; + +import static org.chromium.android_webview.test.OnlyRunIn.ProcessMode.SINGLE_PROCESS; + +import android.os.IBinder; + +import androidx.test.filters.MediumTest; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.android_webview.common.services.IMetricsBridgeService; +import org.chromium.android_webview.proto.MetricsBridgeRecords.HistogramRecord; +import org.chromium.android_webview.proto.MetricsBridgeRecords.HistogramRecord.RecordType; +import org.chromium.android_webview.services.MetricsBridgeService; +import org.chromium.android_webview.test.AwActivityTestRule; +import org.chromium.android_webview.test.AwJUnit4ClassRunner; +import org.chromium.android_webview.test.OnlyRunIn; +import org.chromium.base.FileUtils; +import org.chromium.base.test.util.Batch; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; +import java.util.concurrent.FutureTask; + +/** + * Instrumentation tests for MetricsBridgeService. These tests are batched as UNIT_TESTS because + * they don't actually launch any services or other components. + */ +@RunWith(AwJUnit4ClassRunner.class) +@OnlyRunIn(SINGLE_PROCESS) +@Batch(Batch.UNIT_TESTS) +public class MetricsBridgeServiceUnitTest { + public static final byte[] PARSING_LOG_RESULT_SUCCESS_RECORD = + HistogramRecord.newBuilder() + .setRecordType(RecordType.HISTOGRAM_LINEAR) + .setHistogramName("Android.WebView.NonEmbeddedMetrics.ParsingLogResult") + .setSample(MetricsBridgeService.ParsingLogResult.SUCCESS) + .setMin(1) + .setMax(MetricsBridgeService.ParsingLogResult.COUNT) + .setNumBuckets(MetricsBridgeService.ParsingLogResult.COUNT + 1) + .build() + .toByteArray(); + + public static final byte[] RETRIEVE_METRICS_TASK_STATUS_SUCCESS_RECORD = + HistogramRecord.newBuilder() + .setRecordType(RecordType.HISTOGRAM_LINEAR) + .setHistogramName( + "Android.WebView.NonEmbeddedMetrics.RetrieveMetricsTaskStatus") + .setSample(MetricsBridgeService.RetrieveMetricsTaskStatus.SUCCESS) + .setMin(1) + .setMax(MetricsBridgeService.RetrieveMetricsTaskStatus.COUNT) + .setNumBuckets(MetricsBridgeService.RetrieveMetricsTaskStatus.COUNT + 1) + .build() + .toByteArray(); + + private File mTempFile; + + @Before + public void setUp() throws IOException { + mTempFile = File.createTempFile("test_webview_metrics_bridge_logs", null); + } + + @After + public void tearDown() { + if (mTempFile.exists()) { + Assert.assertTrue("Failed to delete \"" + mTempFile + "\"", mTempFile.delete()); + } + } + + @Test + @MediumTest + // Test that the service saves metrics records to file + public void testSaveToFile() throws Throwable { + HistogramRecord recordBooleanProto = HistogramRecord.newBuilder() + .setRecordType(RecordType.HISTOGRAM_BOOLEAN) + .setHistogramName("testSaveToFile.boolean") + .setSample(1) + .build(); + HistogramRecord recordLinearProto = HistogramRecord.newBuilder() + .setRecordType(RecordType.HISTOGRAM_LINEAR) + .setHistogramName("testSaveToFile.linear") + .setSample(123) + .setMin(1) + .setMax(1000) + .setNumBuckets(50) + .build(); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + writeRecordsToStream(out, recordBooleanProto, recordLinearProto, recordBooleanProto); + byte[] expectedData = out.toByteArray(); + + // Cannot bind to service using real connection since we need to inject test file name. + MetricsBridgeService service = new MetricsBridgeService(mTempFile); + // Simulate starting the service by calling onCreate() + service.onCreate(); + + IBinder binder = service.onBind(null); + IMetricsBridgeService stub = IMetricsBridgeService.Stub.asInterface(binder); + stub.recordMetrics(recordBooleanProto.toByteArray()); + stub.recordMetrics(recordLinearProto.toByteArray()); + stub.recordMetrics(recordBooleanProto.toByteArray()); + + // Block until all tasks are finished to make sure all records are written to file. + FutureTask<Object> blockTask = service.addTaskToBlock(); + AwActivityTestRule.waitForFuture(blockTask); + + byte[] resultData = FileUtils.readStream(new FileInputStream(mTempFile)); + Assert.assertArrayEquals( + "byte data from file is different from the expected proto byte data", expectedData, + resultData); + } + + @Test + @MediumTest + // Test that service recovers saved data from file, appends new records to it and + // clears the file after a retrieve call. + public void testRetrieveFromFile() throws Throwable { + HistogramRecord recordBooleanProto = + HistogramRecord.newBuilder() + .setRecordType(RecordType.HISTOGRAM_BOOLEAN) + .setHistogramName("testRecoverFromFile.boolean") + .setSample(1) + .build(); + HistogramRecord recordLinearProto = HistogramRecord.newBuilder() + .setRecordType(RecordType.HISTOGRAM_LINEAR) + .setHistogramName("testRecoverFromFile.linear") + .setSample(123) + .setMin(1) + .setMax(1000) + .setNumBuckets(50) + .build(); + // write Initial proto data To File + writeRecordsToStream(new FileOutputStream(mTempFile), recordBooleanProto, recordLinearProto, + recordBooleanProto); + + // Cannot bind to service using real connection since we need to inject test file name. + MetricsBridgeService service = new MetricsBridgeService(mTempFile); + // Simulate starting the service by calling onCreate() + service.onCreate(); + + IBinder binder = service.onBind(null); + IMetricsBridgeService stub = IMetricsBridgeService.Stub.asInterface(binder); + stub.recordMetrics(recordBooleanProto.toByteArray()); + List<byte[]> retrievedDataList = stub.retrieveNonembeddedMetrics(); + + byte[][] expectedData = new byte[][] {recordBooleanProto.toByteArray(), + recordLinearProto.toByteArray(), recordBooleanProto.toByteArray(), + PARSING_LOG_RESULT_SUCCESS_RECORD, recordBooleanProto.toByteArray(), + RETRIEVE_METRICS_TASK_STATUS_SUCCESS_RECORD}; + + // Assert file is deleted after the retrieve call + Assert.assertFalse( + "file should be deleted after retrieve metrics call", mTempFile.exists()); + Assert.assertNotNull("retrieved byte data from the service is null", retrievedDataList); + Assert.assertArrayEquals("retrieved byte data is different from the expected data", + expectedData, retrievedDataList.toArray()); + } + + private static void writeRecordsToStream(OutputStream os, HistogramRecord... records) + throws IOException { + for (HistogramRecord record : records) { + record.writeDelimitedTo(os); + } + os.close(); + } +} \ No newline at end of file
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/services/MinidumpUploadJobTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/services/MinidumpUploadJobTest.java index 925d83b..f24ffba5 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/services/MinidumpUploadJobTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/services/MinidumpUploadJobTest.java
@@ -44,6 +44,9 @@ /** * Instrumentation tests for WebView's implementation of MinidumpUploaderDelegate, and the * interoperability of WebView's minidump-copying and minidump-uploading logic. + * + * These tests loads native library and mark the process as a browser process, it's safer to + * leave them unbatched to avoid possible state leaking between tests. */ @RunWith(AwJUnit4ClassRunner.class) @OnlyRunIn(SINGLE_PROCESS)
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/services/VariationsSeedServerTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/services/VariationsSeedServerTest.java index 0a4a761..040a529 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/services/VariationsSeedServerTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/services/VariationsSeedServerTest.java
@@ -37,7 +37,8 @@ import java.util.concurrent.TimeoutException; /** - * Test VariationsSeedServer. + * Test VariationsSeedServer. These tests are not batched to make sure all unbinded services are + * properly killed between tests. */ @RunWith(AwJUnit4ClassRunner.class) @OnlyRunIn(SINGLE_PROCESS)
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/services/VisualStateCallbackTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/services/VisualStateCallbackTest.java index a6303e0..1360f87 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/services/VisualStateCallbackTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/services/VisualStateCallbackTest.java
@@ -38,7 +38,8 @@ import org.chromium.content_public.browser.UiThreadTaskTraits; /** - * Test VisualStateCallback when render process is gone. + * Test VisualStateCallback when render process is gone. Test is not batched because it tests + * behaviour in multiprocesses. */ @RunWith(AwJUnit4ClassRunner.class) public class VisualStateCallbackTest {
diff --git a/android_webview/test/BUILD.gn b/android_webview/test/BUILD.gn index e7f9fd2..335a8f8 100644 --- a/android_webview/test/BUILD.gn +++ b/android_webview/test/BUILD.gn
@@ -330,6 +330,7 @@ "../javatests/src/org/chromium/android_webview/test/devui/util/WebViewCrashLogParserTest.java", "../javatests/src/org/chromium/android_webview/test/services/CrashReceiverServiceTest.java", "../javatests/src/org/chromium/android_webview/test/services/MetricsBridgeServiceTest.java", + "../javatests/src/org/chromium/android_webview/test/services/MetricsBridgeServiceUnitTest.java", "../javatests/src/org/chromium/android_webview/test/services/MinidumpUploadJobTest.java", "../javatests/src/org/chromium/android_webview/test/services/MockMetricsBridgeService.java", "../javatests/src/org/chromium/android_webview/test/services/MockVariationsSeedServer.java",
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 8cd6d77..8bebcd5 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -935,6 +935,8 @@ "system/enterprise/enterprise_domain_observer.h", "system/gesture_education/gesture_education_notification_controller.cc", "system/gesture_education/gesture_education_notification_controller.h", + "system/holding_space/holding_space_color_provider_impl.cc", + "system/holding_space/holding_space_color_provider_impl.h", "system/holding_space/holding_space_item_chip_view.cc", "system/holding_space/holding_space_item_chip_view.h", "system/holding_space/holding_space_item_chips_container.cc",
diff --git a/ash/in_session_auth/in_session_auth_dialog.cc b/ash/in_session_auth/in_session_auth_dialog.cc index fc691996..6ccb033 100644 --- a/ash/in_session_auth/in_session_auth_dialog.cc +++ b/ash/in_session_auth/in_session_auth_dialog.cc
@@ -18,55 +18,37 @@ // The initial height does nothing except determining the vertical position of // the dialog, since the dialog is centered with the initial height. -constexpr gfx::Size kDefaultSize(340, 490); constexpr int kCornerRadius = 12; -class AuthDialogWidgetDelegate : public views::WidgetDelegate { - public: - AuthDialogWidgetDelegate() { - SetOwnedByWidget(true); - SetModalType(ui::MODAL_TYPE_SYSTEM); - } - AuthDialogWidgetDelegate(const AuthDialogWidgetDelegate&) = delete; - AuthDialogWidgetDelegate& operator=(const AuthDialogWidgetDelegate&) = delete; - ~AuthDialogWidgetDelegate() override = default; - - // views::WidgetDelegate: - views::View* GetInitiallyFocusedView() override { - return GetWidget()->GetContentsView(); - } -}; - -std::unique_ptr<views::Widget> CreateAuthDialogWidget(aura::Window* parent) { +std::unique_ptr<views::Widget> CreateAuthDialogWidget( + std::unique_ptr<views::View> contents_view) { views::Widget::InitParams params( views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params.delegate = new AuthDialogWidgetDelegate(); + params.delegate = new views::WidgetDelegate(); params.show_state = ui::SHOW_STATE_NORMAL; - params.parent = parent; + params.parent = nullptr; params.name = "AuthDialogWidget"; params.shadow_type = views::Widget::InitParams::ShadowType::kDrop; params.shadow_elevation = 3; - gfx::Rect bounds = display::Screen::GetScreen()->GetPrimaryDisplay().bounds(); - bounds.ClampToCenteredSize(kDefaultSize); - params.bounds = bounds; + + params.delegate->SetInitiallyFocusedView(contents_view.get()); + params.delegate->SetModalType(ui::MODAL_TYPE_SYSTEM); + params.delegate->SetOwnedByWidget(true); std::unique_ptr<views::Widget> widget = std::make_unique<views::Widget>(); widget->Init(std::move(params)); widget->SetVisibilityAnimationTransition(views::Widget::ANIMATE_NONE); + widget->SetContentsView(std::move(contents_view)); return widget; } } // namespace -InSessionAuthDialog::InSessionAuthDialog(uint32_t auth_methods) { - widget_ = CreateAuthDialogWidget(nullptr); - contents_view_ = widget_->SetContentsView( +InSessionAuthDialog::InSessionAuthDialog(uint32_t auth_methods) + : auth_methods_(auth_methods) { + widget_ = CreateAuthDialogWidget( std::make_unique<AuthDialogContentsView>(auth_methods)); - gfx::Rect bound = widget_->GetWindowBoundsInScreen(); - // Calculate initial height based on which child views are shown. - bound.set_height(contents_view_->GetPreferredSize().height()); - widget_->SetBounds(bound); aura::Window* window = widget_->GetNativeWindow(); rounded_corner_decorator_ = std::make_unique<RoundedCornerDecorator>( @@ -78,8 +60,7 @@ InSessionAuthDialog::~InSessionAuthDialog() = default; uint32_t InSessionAuthDialog::GetAuthMethods() const { - DCHECK(contents_view_); - return contents_view_->auth_methods(); + return auth_methods_; } } // namespace ash
diff --git a/ash/in_session_auth/in_session_auth_dialog.h b/ash/in_session_auth/in_session_auth_dialog.h index c56b06b..26a3cbd 100644 --- a/ash/in_session_auth/in_session_auth_dialog.h +++ b/ash/in_session_auth/in_session_auth_dialog.h
@@ -15,7 +15,6 @@ namespace ash { -class AuthDialogContentsView; class RoundedCornerDecorator; // InSessionAuthDialog gets instantiated on every request to show @@ -41,7 +40,7 @@ // Pointer to the contents view. Used to query and update the set of available // auth methods. - AuthDialogContentsView* contents_view_ = nullptr; + const uint32_t auth_methods_; std::unique_ptr<RoundedCornerDecorator> rounded_corner_decorator_; };
diff --git a/ash/login/ui/login_test_base.cc b/ash/login/ui/login_test_base.cc index a773f832..ee7688be 100644 --- a/ash/login/ui/login_test_base.cc +++ b/ash/login/ui/login_test_base.cc
@@ -20,27 +20,6 @@ namespace ash { -// A WidgetDelegate which ensures that |initially_focused| gets focus. -class LoginTestBase::WidgetDelegate : public views::WidgetDelegate { - public: - explicit WidgetDelegate(views::View* content) : content_(content) { - SetOwnedByWidget(true); - } - ~WidgetDelegate() override = default; - - // views::WidgetDelegate: - views::View* GetInitiallyFocusedView() override { return content_; } - views::Widget* GetWidget() override { return content_->GetWidget(); } - const views::Widget* GetWidget() const override { - return content_->GetWidget(); - } - - private: - views::View* content_; - - DISALLOW_COPY_AND_ASSIGN(WidgetDelegate); -}; - LoginTestBase::LoginTestBase() = default; LoginTestBase::~LoginTestBase() = default; @@ -76,7 +55,10 @@ views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; params.bounds = gfx::Rect(0, 0, 800, 800); - params.delegate = new WidgetDelegate(content); + + params.delegate = new views::WidgetDelegate(); + params.delegate->SetInitiallyFocusedView(content); + params.delegate->SetOwnedByWidget(true); // Set the widget to the lock screen container, since a test may change the // session state to locked, which will hide all widgets not associated with
diff --git a/ash/login/ui/login_test_base.h b/ash/login/ui/login_test_base.h index 0588165..901518b 100644 --- a/ash/login/ui/login_test_base.h +++ b/ash/login/ui/login_test_base.h
@@ -80,8 +80,6 @@ void TearDown() override; private: - class WidgetDelegate; - // The widget created using |ShowWidgetWithContent|. std::unique_ptr<views::Widget> widget_;
diff --git a/ash/public/cpp/BUILD.gn b/ash/public/cpp/BUILD.gn index 17029703..4ac05b3 100644 --- a/ash/public/cpp/BUILD.gn +++ b/ash/public/cpp/BUILD.gn
@@ -140,6 +140,8 @@ "frame_utils.h", "gesture_action_type.h", "holding_space/holding_space_client.h", + "holding_space/holding_space_color_provider.cc", + "holding_space/holding_space_color_provider.h", "holding_space/holding_space_constants.h", "holding_space/holding_space_controller.cc", "holding_space/holding_space_controller.h",
diff --git a/ash/public/cpp/ash_features.cc b/ash/public/cpp/ash_features.cc index 42021d8..9dac15b3 100644 --- a/ash/public/cpp/ash_features.cc +++ b/ash/public/cpp/ash_features.cc
@@ -86,7 +86,7 @@ "NotificationExpansionAnimation", base::FEATURE_DISABLED_BY_DEFAULT}; const base::Feature kNotificationExperimentalShortTimeouts{ - "NotificationExperimentalShortTimeouts", base::FEATURE_DISABLED_BY_DEFAULT}; + "NotificationExperimentalShortTimeouts", base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature kNotificationScrollBar{"NotificationScrollBar", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/ash/public/cpp/caption_buttons/frame_caption_button_container_view.cc b/ash/public/cpp/caption_buttons/frame_caption_button_container_view.cc index dbe2f50..782fc16 100644 --- a/ash/public/cpp/caption_buttons/frame_caption_button_container_view.cc +++ b/ash/public/cpp/caption_buttons/frame_caption_button_container_view.cc
@@ -10,10 +10,10 @@ #include "ash/public/cpp/caption_buttons/caption_button_model.h" #include "ash/public/cpp/caption_buttons/frame_size_button.h" #include "ash/public/cpp/caption_buttons/snap_controller.h" -#include "ash/public/cpp/tablet_mode.h" #include "base/metrics/histogram_macros.h" #include "base/metrics/user_metrics.h" #include "base/numerics/ranges.h" +#include "chromeos/ui/tablet_state.h" #include "ui/aura/window_tree_host.h" #include "ui/base/hit_test.h" #include "ui/base/l10n/l10n_util.h" @@ -420,7 +420,7 @@ } } else if (sender == close_button_) { frame_->Close(); - if (TabletMode::Get()->InTabletMode()) + if (chromeos::TabletState::Get()->InTabletMode()) RecordAction(UserMetricsAction("Tablet_WindowCloseFromCaptionButton")); else RecordAction(UserMetricsAction("CloseButton_Clk"));
diff --git a/ash/public/cpp/holding_space/holding_space_color_provider.cc b/ash/public/cpp/holding_space/holding_space_color_provider.cc new file mode 100644 index 0000000..346abc7 --- /dev/null +++ b/ash/public/cpp/holding_space/holding_space_color_provider.cc
@@ -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. + +#include "ash/public/cpp/holding_space/holding_space_color_provider.h" + +#include "base/check_op.h" + +namespace ash { + +namespace { + +// The singleton instance. +HoldingSpaceColorProvider* g_instance = nullptr; + +} // namespace + +HoldingSpaceColorProvider::~HoldingSpaceColorProvider() { + DCHECK_EQ(g_instance, this); + g_instance = nullptr; +} + +// static +HoldingSpaceColorProvider* HoldingSpaceColorProvider::Get() { + return g_instance; +} + +HoldingSpaceColorProvider::HoldingSpaceColorProvider() { + DCHECK_EQ(g_instance, nullptr); + g_instance = this; +} + +} // namespace ash
diff --git a/ash/public/cpp/holding_space/holding_space_color_provider.h b/ash/public/cpp/holding_space/holding_space_color_provider.h new file mode 100644 index 0000000..0a78d82 --- /dev/null +++ b/ash/public/cpp/holding_space/holding_space_color_provider.h
@@ -0,0 +1,30 @@ +// 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_PUBLIC_CPP_HOLDING_SPACE_HOLDING_SPACE_COLOR_PROVIDER_H_ +#define ASH_PUBLIC_CPP_HOLDING_SPACE_HOLDING_SPACE_COLOR_PROVIDER_H_ + +#include "ash/public/cpp/ash_public_export.h" +#include "third_party/skia/include/core/SkColor.h" + +namespace ash { + +// The interface for the singleton which provides colors to holding space. +class ASH_PUBLIC_EXPORT HoldingSpaceColorProvider { + public: + virtual ~HoldingSpaceColorProvider(); + + // Returns the singleton instance. + static HoldingSpaceColorProvider* Get(); + + // Returns the color to be used for file icons. + virtual SkColor GetFileIconColor() const = 0; + + protected: + HoldingSpaceColorProvider(); +}; + +} // namespace ash + +#endif // ASH_PUBLIC_CPP_HOLDING_SPACE_HOLDING_SPACE_COLOR_PROVIDER_H_
diff --git a/ash/public/cpp/holding_space/holding_space_controller.cc b/ash/public/cpp/holding_space/holding_space_controller.cc index 7f4a828..b444a565 100644 --- a/ash/public/cpp/holding_space/holding_space_controller.cc +++ b/ash/public/cpp/holding_space/holding_space_controller.cc
@@ -4,6 +4,7 @@ #include "ash/public/cpp/holding_space/holding_space_controller.h" +#include "ash/public/cpp/holding_space/holding_space_color_provider.h" #include "ash/public/cpp/holding_space/holding_space_controller_observer.h" #include "ash/public/cpp/session/session_controller.h" #include "base/check.h" @@ -16,7 +17,9 @@ } // namespace -HoldingSpaceController::HoldingSpaceController() { +HoldingSpaceController::HoldingSpaceController( + std::unique_ptr<HoldingSpaceColorProvider> color_provider) + : color_provider_(std::move(color_provider)) { CHECK(!g_instance); g_instance = this;
diff --git a/ash/public/cpp/holding_space/holding_space_controller.h b/ash/public/cpp/holding_space/holding_space_controller.h index 14ce07af..66430a7012 100644 --- a/ash/public/cpp/holding_space/holding_space_controller.h +++ b/ash/public/cpp/holding_space/holding_space_controller.h
@@ -5,6 +5,8 @@ #ifndef ASH_PUBLIC_CPP_HOLDING_SPACE_HOLDING_SPACE_CONTROLLER_H_ #define ASH_PUBLIC_CPP_HOLDING_SPACE_HOLDING_SPACE_CONTROLLER_H_ +#include <memory> + #include "ash/public/cpp/ash_public_export.h" #include "ash/public/cpp/session/session_observer.h" #include "base/observer_list.h" @@ -13,6 +15,7 @@ namespace ash { class HoldingSpaceClient; +class HoldingSpaceColorProvider; class HoldingSpaceControllerObserver; class HoldingSpaceModel; @@ -23,7 +26,7 @@ // using HoldingSpaceController::Get(). class ASH_PUBLIC_EXPORT HoldingSpaceController : public SessionObserver { public: - HoldingSpaceController(); + explicit HoldingSpaceController(std::unique_ptr<HoldingSpaceColorProvider>); HoldingSpaceController(const HoldingSpaceController& other) = delete; HoldingSpaceController& operator=(const HoldingSpaceController& other) = delete; @@ -53,6 +56,9 @@ void SetClient(HoldingSpaceClient* client); void SetModel(HoldingSpaceModel* model); + // The singleton provider for colors used by holding space. + std::unique_ptr<HoldingSpaceColorProvider> color_provider_; + // The currently active holding space client, set by `SetClient()`. HoldingSpaceClient* client_ = nullptr;
diff --git a/ash/shell.cc b/ash/shell.cc index 2ab1aa69..83fc1dc 100644 --- a/ash/shell.cc +++ b/ash/shell.cc
@@ -109,6 +109,7 @@ #include "ash/system/brightness/brightness_controller_chromeos.h" #include "ash/system/brightness_control_delegate.h" #include "ash/system/caps_lock_notification_controller.h" +#include "ash/system/holding_space/holding_space_color_provider_impl.h" #include "ash/system/keyboard_brightness/keyboard_brightness_controller.h" #include "ash/system/keyboard_brightness_control_delegate.h" #include "ash/system/locale/locale_update_controller_impl.h" @@ -1250,8 +1251,10 @@ std::make_unique<DisplayAlignmentController>(); } - if (features::IsTemporaryHoldingSpaceEnabled()) - holding_space_controller_ = std::make_unique<HoldingSpaceController>(); + if (features::IsTemporaryHoldingSpaceEnabled()) { + holding_space_controller_ = std::make_unique<HoldingSpaceController>( + std::make_unique<HoldingSpaceColorProviderImpl>()); + } for (auto& observer : shell_observers_) observer.OnShellInitialized();
diff --git a/ash/system/holding_space/holding_space_color_provider_impl.cc b/ash/system/holding_space/holding_space_color_provider_impl.cc new file mode 100644 index 0000000..a881e31 --- /dev/null +++ b/ash/system/holding_space/holding_space_color_provider_impl.cc
@@ -0,0 +1,20 @@ +// 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_color_provider_impl.h" + +#include "ash/style/ash_color_provider.h" + +namespace ash { + +HoldingSpaceColorProviderImpl::HoldingSpaceColorProviderImpl() = default; + +HoldingSpaceColorProviderImpl::~HoldingSpaceColorProviderImpl() = default; + +SkColor HoldingSpaceColorProviderImpl::GetFileIconColor() const { + return AshColorProvider::Get()->GetContentLayerColor( + AshColorProvider::ContentLayerType::kIconColorPrimary); +} + +} // namespace ash
diff --git a/ash/system/holding_space/holding_space_color_provider_impl.h b/ash/system/holding_space/holding_space_color_provider_impl.h new file mode 100644 index 0000000..282e4d3 --- /dev/null +++ b/ash/system/holding_space/holding_space_color_provider_impl.h
@@ -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. + +#ifndef ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_COLOR_PROVIDER_IMPL_H_ +#define ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_COLOR_PROVIDER_IMPL_H_ + +#include "ash/public/cpp/holding_space/holding_space_color_provider.h" + +namespace ash { + +// The implementation of the singleton which provides colors to holding space. +class HoldingSpaceColorProviderImpl : public HoldingSpaceColorProvider { + public: + HoldingSpaceColorProviderImpl(); + HoldingSpaceColorProviderImpl(const HoldingSpaceColorProviderImpl&) = delete; + HoldingSpaceColorProviderImpl& operator=( + const HoldingSpaceColorProviderImpl&) = delete; + ~HoldingSpaceColorProviderImpl() override; + + private: + // HoldingSpaceColorProvider: + SkColor GetFileIconColor() const override; +}; + +} // namespace ash + +#endif // ASH_PUBLIC_CPP_HOLDING_SPACE_HOLDING_SPACE_COLOR_PROVIDER_H_
diff --git a/ash/system/phonehub/quick_action_item.h b/ash/system/phonehub/quick_action_item.h index bc5304a9..910abb6 100644 --- a/ash/system/phonehub/quick_action_item.h +++ b/ash/system/phonehub/quick_action_item.h
@@ -16,7 +16,8 @@ namespace ash { // A toggle button with labels used in the quick action view. -class QuickActionItem : public views::View, public views::ButtonListener { +class ASH_EXPORT QuickActionItem : public views::View, + public views::ButtonListener { public: class Delegate { public:
diff --git a/ash/system/phonehub/quick_actions_view_unittest.cc b/ash/system/phonehub/quick_actions_view_unittest.cc index 99a8e553..ed8f022 100644 --- a/ash/system/phonehub/quick_actions_view_unittest.cc +++ b/ash/system/phonehub/quick_actions_view_unittest.cc
@@ -22,11 +22,15 @@ DummyEvent() : Event(ui::ET_UNKNOWN, base::TimeTicks(), 0) {} }; +constexpr base::TimeDelta kWaitForRequestTimeout = + base::TimeDelta::FromSeconds(10); + } // namespace class QuickActionsViewTest : public AshTestBase { public: - QuickActionsViewTest() = default; + QuickActionsViewTest() + : AshTestBase(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {} ~QuickActionsViewTest() override = default; // AshTestBase: @@ -105,6 +109,22 @@ actions_view()->silence_phone_for_testing()->ButtonPressed(nullptr, DummyEvent()); EXPECT_FALSE(dnd_controller()->IsDndEnabled()); + + // Test the error state. + dnd_controller()->SetShouldRequestFail(true); + actions_view()->silence_phone_for_testing()->ButtonPressed(nullptr, + DummyEvent()); + + // In error state, do not disturb is disabled but the button should still be + // on after being pressed. + EXPECT_FALSE(dnd_controller()->IsDndEnabled()); + EXPECT_TRUE(actions_view()->silence_phone_for_testing()->IsToggled()); + + // After a certain time, the button should be corrected to be off. + task_environment()->FastForwardBy(kWaitForRequestTimeout); + EXPECT_FALSE(actions_view()->silence_phone_for_testing()->IsToggled()); + + dnd_controller()->SetShouldRequestFail(false); } TEST_F(QuickActionsViewTest, LocatePhoneToggle) {
diff --git a/ash/system/phonehub/silence_phone_quick_action_controller.cc b/ash/system/phonehub/silence_phone_quick_action_controller.cc index 90d9987..6b7701f 100644 --- a/ash/system/phonehub/silence_phone_quick_action_controller.cc +++ b/ash/system/phonehub/silence_phone_quick_action_controller.cc
@@ -7,10 +7,20 @@ #include "ash/resources/vector_icons/vector_icons.h" #include "ash/strings/grit/ash_strings.h" #include "ash/system/phonehub/quick_action_item.h" +#include "base/timer/timer.h" #include "ui/base/l10n/l10n_util.h" namespace ash { +namespace { + +// Time to wait until we check the state of the phone to prevent showing wrong +// state +constexpr base::TimeDelta kWaitForRequestTimeout = + base::TimeDelta::FromSeconds(10); + +} // namespace + SilencePhoneQuickActionController::SilencePhoneQuickActionController( chromeos::phonehub::DoNotDisturbController* dnd_controller) : dnd_controller_(dnd_controller) { @@ -31,18 +41,32 @@ } void SilencePhoneQuickActionController::OnButtonPressed(bool is_now_enabled) { - SetState(ActionState::kConnecting); + requested_state_ = is_now_enabled ? ActionState::kOff : ActionState::kOn; + SetItemState(requested_state_.value()); + + check_requested_state_timer_ = std::make_unique<base::OneShotTimer>(); + check_requested_state_timer_->Start( + FROM_HERE, kWaitForRequestTimeout, + base::BindOnce(&SilencePhoneQuickActionController::CheckRequestedState, + base::Unretained(this))); + dnd_controller_->RequestNewDoNotDisturbState(!is_now_enabled); - // TODO(leandre): Add a timer to switch back to off state after connecting - // failed. } void SilencePhoneQuickActionController::OnDndStateChanged() { - dnd_controller_->IsDndEnabled() ? SetState(ActionState::kOn) - : SetState(ActionState::kOff); + state_ = + dnd_controller_->IsDndEnabled() ? ActionState::kOn : ActionState::kOff; + SetItemState(state_); + + // If |requested_state_| correctly resembles the current state, reset it and + // the timer. + if (state_ == requested_state_) { + check_requested_state_timer_.reset(); + requested_state_.reset(); + } } -void SilencePhoneQuickActionController::SetState(ActionState state) { +void SilencePhoneQuickActionController::SetItemState(ActionState state) { bool icon_enabled; int state_text_id; int sub_label_text; @@ -52,11 +76,6 @@ state_text_id = IDS_ASH_PHONE_HUB_QUICK_ACTIONS_DISABLED_STATE_TOOLTIP; sub_label_text = IDS_ASH_PHONE_HUB_QUICK_ACTIONS_OFF_STATE; break; - case ActionState::kConnecting: - icon_enabled = true; - state_text_id = IDS_ASH_PHONE_HUB_QUICK_ACTIONS_CONNECTING_STATE_TOOLTIP; - sub_label_text = IDS_ASH_PHONE_HUB_QUICK_ACTIONS_CONNECTING_STATE; - break; case ActionState::kOn: icon_enabled = true; state_text_id = IDS_ASH_PHONE_HUB_QUICK_ACTIONS_ENABLED_STATE_TOOLTIP; @@ -73,4 +92,14 @@ item_->GetItemLabel(), tooltip_state)); } +void SilencePhoneQuickActionController::CheckRequestedState() { + // If the current state is different from the requested state, it means that + // we fail to change the state, so switch back to the original one. + if (state_ != requested_state_) + SetItemState(state_); + + check_requested_state_timer_.reset(); + requested_state_.reset(); +} + } // namespace ash
diff --git a/ash/system/phonehub/silence_phone_quick_action_controller.h b/ash/system/phonehub/silence_phone_quick_action_controller.h index bd8c3bcb..38c2b8c 100644 --- a/ash/system/phonehub/silence_phone_quick_action_controller.h +++ b/ash/system/phonehub/silence_phone_quick_action_controller.h
@@ -8,6 +8,10 @@ #include "ash/system/phonehub/quick_action_controller_base.h" #include "chromeos/components/phonehub/do_not_disturb_controller.h" +namespace base { +class OneShotTimer; +} // namespace base + namespace ash { // Controller of a quick action item that toggles silence phone mode. @@ -33,13 +37,28 @@ private: // All the possible states that the silence phone button can be viewed. Each // state has a corresponding icon, labels and tooltip view. - enum class ActionState { kOff, kConnecting, kOn }; + enum class ActionState { kOff, kOn }; // Set the item (including icon, label and tooltips) to a certain state. - void SetState(ActionState state); + void SetItemState(ActionState state); + + // Check to see if the requested state is similar to current state of the + // phone. Make changes to item's state if necessary. + void CheckRequestedState(); chromeos::phonehub::DoNotDisturbController* dnd_controller_ = nullptr; QuickActionItem* item_ = nullptr; + + // Keep track the current state of the item. + ActionState state_; + + // State that user requests when clicking the button. + base::Optional<ActionState> requested_state_; + + // Timer that fires to prevent showing wrong state in the item. It will check + // if the requested state is similar to the current state after the button is + // pressed for a certain time. + std::unique_ptr<base::OneShotTimer> check_requested_state_timer_; }; } // namespace ash
diff --git a/ash/touch/touch_devices_controller.cc b/ash/touch/touch_devices_controller.cc index 8c4e314..0b34ab4 100644 --- a/ash/touch/touch_devices_controller.cc +++ b/ash/touch/touch_devices_controller.cc
@@ -21,7 +21,6 @@ #include "components/prefs/pref_service.h" #include "ui/ozone/public/input_controller.h" #include "ui/ozone/public/ozone_platform.h" -#include "ui/wm/core/cursor_manager.h" namespace ash { @@ -173,23 +172,11 @@ } void TouchDevicesController::UpdateTouchpadEnabled() { - bool enabled = GetTouchpadEnabled(TouchDeviceEnabledSource::GLOBAL) && - GetTouchpadEnabled(TouchDeviceEnabledSource::USER_PREF); - ui::InputController* input_controller = - ui::OzonePlatform::GetInstance()->GetInputController(); - const bool old_value = input_controller->IsInternalTouchpadEnabled(); - input_controller->SetInternalTouchpadEnabled(enabled); - if (old_value == input_controller->IsInternalTouchpadEnabled()) - return; // Value didn't actually change. - - ::wm::CursorManager* cursor_manager = Shell::Get()->cursor_manager(); - if (!cursor_manager) - return; - - if (enabled) - cursor_manager->ShowCursor(); - else - cursor_manager->HideCursor(); + ui::OzonePlatform::GetInstance() + ->GetInputController() + ->SetInternalTouchpadEnabled( + GetTouchpadEnabled(TouchDeviceEnabledSource::GLOBAL) && + GetTouchpadEnabled(TouchDeviceEnabledSource::USER_PREF)); } void TouchDevicesController::UpdateTouchscreenEnabled() {
diff --git a/ash/wm/tablet_mode/tablet_mode_controller.cc b/ash/wm/tablet_mode/tablet_mode_controller.cc index b26da6f..ad1597d 100644 --- a/ash/wm/tablet_mode/tablet_mode_controller.cc +++ b/ash/wm/tablet_mode/tablet_mode_controller.cc
@@ -54,6 +54,7 @@ #include "ui/events/keycodes/keyboard_codes.h" #include "ui/gfx/geometry/vector3d_f.h" #include "ui/views/widget/widget.h" +#include "ui/wm/core/cursor_manager.h" #include "ui/wm/core/window_util.h" namespace ash { @@ -888,6 +889,7 @@ VLOG(1) << "Exit tablet mode."; UpdateInternalInputDevicesEventBlocker(); + Shell::Get()->cursor_manager()->ShowCursor(); } } @@ -1152,6 +1154,7 @@ } UpdateInternalInputDevicesEventBlocker(); + Shell::Get()->cursor_manager()->HideCursor(); VLOG(1) << "Enter tablet mode."; }
diff --git a/ash/wm/tablet_mode/tablet_mode_controller_unittest.cc b/ash/wm/tablet_mode/tablet_mode_controller_unittest.cc index 903a1bfc..172c1382 100644 --- a/ash/wm/tablet_mode/tablet_mode_controller_unittest.cc +++ b/ash/wm/tablet_mode/tablet_mode_controller_unittest.cc
@@ -65,6 +65,7 @@ #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/vector3d_f.h" #include "ui/message_center/message_center.h" +#include "ui/wm/core/cursor_manager.h" #include "ui/wm/core/window_util.h" namespace ash { @@ -1069,6 +1070,19 @@ EXPECT_TRUE(AreEventsBlocked()); } +// Test that the mouse cursor is hidden when entering tablet mode, and shown +// when exiting tablet mode. +TEST_P(TabletModeControllerTest, ShowAndHideMouseCursorTest) { + wm::CursorManager* cursor_manager = Shell::Get()->cursor_manager(); + EXPECT_TRUE(cursor_manager->IsCursorVisible()); + + tablet_mode_controller()->SetEnabledForTest(true); + EXPECT_FALSE(cursor_manager->IsCursorVisible()); + + tablet_mode_controller()->SetEnabledForTest(false); + EXPECT_TRUE(cursor_manager->IsCursorVisible()); +} + class TabletModeControllerForceTabletModeTest : public TabletModeControllerTest { public:
diff --git a/base/allocator/partition_allocator/partition_lock.h b/base/allocator/partition_allocator/partition_lock.h index f28acefe..263f48d 100644 --- a/base/allocator/partition_allocator/partition_lock.h +++ b/base/allocator/partition_allocator/partition_lock.h
@@ -14,7 +14,7 @@ #include "base/threading/platform_thread.h" #include "build/build_config.h" -#if defined(OS_LINUX) || defined(OS_ANDROID) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) #include "base/allocator/partition_allocator/spinning_futex_linux.h" #endif @@ -142,7 +142,7 @@ } private: -#if defined(OS_LINUX) || defined(OS_ANDROID) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) base::NoDestructor<SpinningFutex> lock_; #else // base::Lock is slower on the fast path than SpinLock, hence we still use it
diff --git a/base/allocator/partition_allocator/spinning_futex_linux.cc b/base/allocator/partition_allocator/spinning_futex_linux.cc index 4944ff6..fa620d8 100644 --- a/base/allocator/partition_allocator/spinning_futex_linux.cc +++ b/base/allocator/partition_allocator/spinning_futex_linux.cc
@@ -7,7 +7,7 @@ #include "base/allocator/partition_allocator/partition_alloc_check.h" #include "build/build_config.h" -#if defined(OS_LINUX) || defined(OS_ANDROID) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) #include <errno.h> #include <linux/futex.h> @@ -70,4 +70,4 @@ } // namespace internal } // namespace base -#endif // defined(OS_LINUX) || defined(OS_ANDROID) +#endif // defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID)
diff --git a/base/allocator/partition_allocator/spinning_futex_linux.h b/base/allocator/partition_allocator/spinning_futex_linux.h index b7fd6df..795040dd 100644 --- a/base/allocator/partition_allocator/spinning_futex_linux.h +++ b/base/allocator/partition_allocator/spinning_futex_linux.h
@@ -12,7 +12,7 @@ #include "base/compiler_specific.h" #include "build/build_config.h" -#if !(defined(OS_LINUX) || defined(OS_ANDROID)) +#if !(defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID)) #error "Not supported" #endif
diff --git a/base/allocator/partition_allocator/thread_cache_unittest.cc b/base/allocator/partition_allocator/thread_cache_unittest.cc index 70c7ee0..a6716af 100644 --- a/base/allocator/partition_allocator/thread_cache_unittest.cc +++ b/base/allocator/partition_allocator/thread_cache_unittest.cc
@@ -27,7 +27,8 @@ // on Windows 7 (at least). As long as it doesn't use something else on Windows, // disable the cache (and tests) #if !BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && \ - !defined(MEMORY_TOOL_REPLACES_ALLOCATOR) && defined(OS_LINUX) + !defined(MEMORY_TOOL_REPLACES_ALLOCATOR) && \ + (defined(OS_LINUX) || defined(OS_CHROMEOS)) namespace base { namespace internal { @@ -402,4 +403,5 @@ } // namespace base #endif // !BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && - // !defined(MEMORY_TOOL_REPLACES_ALLOCATOR) && defined(OS_LINUX) + // !defined(MEMORY_TOOL_REPLACES_ALLOCATOR) && + // (defined(OS_LINUX) || defined(OS_CHROMEOS))
diff --git a/base/android/jni_generator/jni_generator.py b/base/android/jni_generator/jni_generator.py index 0fa50eb..6de4ea7 100755 --- a/base/android/jni_generator/jni_generator.py +++ b/base/android/jni_generator/jni_generator.py
@@ -27,7 +27,9 @@ _CHROMIUM_SRC = os.path.join(_FILE_DIR, os.pardir, os.pardir, os.pardir) _BUILD_ANDROID_GYP = os.path.join(_CHROMIUM_SRC, 'build', 'android', 'gyp') -sys.path.append(_BUILD_ANDROID_GYP) +# Item 0 of sys.path is the directory of the main file; item 1 is PYTHONPATH +# (if set); item 2 is system libraries. +sys.path.insert(1, _BUILD_ANDROID_GYP) from util import build_utils
diff --git a/base/debug/stack_trace.h b/base/debug/stack_trace.h index b8d6487..618e1e37 100644 --- a/base/debug/stack_trace.h +++ b/base/debug/stack_trace.h
@@ -152,7 +152,7 @@ // scanning area at the origin of the stack, wasting time and not finding any // frames (since Android libraries don't have frame pointers). Scanning is not // enabled on other posix platforms due to legacy reasons. -#if defined(OS_LINUX) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) constexpr bool kEnableScanningByDefault = true; #else constexpr bool kEnableScanningByDefault = false;
diff --git a/base/win/windows_version.cc b/base/win/windows_version.cc index 5010309..750cd731 100644 --- a/base/win/windows_version.cc +++ b/base/win/windows_version.cc
@@ -13,6 +13,7 @@ #include "base/check_op.h" #include "base/file_version_info_win.h" #include "base/files/file_path.h" +#include "base/logging.h" #include "base/no_destructor.h" #include "base/notreached.h" #include "base/strings/string_util.h" @@ -199,6 +200,16 @@ return kernel32_version; } +OSInfo::VersionNumber OSInfo::Kernel32VersionNumber() const { + DCHECK(Kernel32BaseVersion().components().size() == 4); + static const VersionNumber version = { + .major = Kernel32BaseVersion().components()[0], + .minor = Kernel32BaseVersion().components()[1], + .build = Kernel32BaseVersion().components()[2], + .patch = Kernel32BaseVersion().components()[3]}; + return version; +} + // Retrieve a version from kernel32. This is useful because when running in // compatibility mode for a down-level version of the OS, the file version of // kernel32 will still be the "real" version.
diff --git a/base/win/windows_version.h b/base/win/windows_version.h index 95bd9fc..872f8ae7 100644 --- a/base/win/windows_version.h +++ b/base/win/windows_version.h
@@ -120,20 +120,42 @@ // process. This doesn't touch member state, so you can bypass the singleton. static WOW64Status GetWOW64StatusForProcess(HANDLE process_handle); + // Returns the OS Version as returned from a call to GetVersionEx(). const Version& version() const { return version_; } - Version Kernel32Version() const; - base::Version Kernel32BaseVersion() const; - // The next two functions return arrays of values, [major, minor(, build)]. + + // Returns detailed version info containing major, minor, build and patch. const VersionNumber& version_number() const { return version_number_; } + + // The Kernel32* set of functions return the OS version as determined by a + // call to VerQueryValue() on kernel32.dll. This avoids any running App Compat + // shims from manipulating the version reported. + Version Kernel32Version() const; + VersionNumber Kernel32VersionNumber() const; + base::Version Kernel32BaseVersion() const; + + // Functions to determine Version Type (e.g. Enterprise/Home) and Service Pack + // value. See above for definitions of these values. const VersionType& version_type() const { return version_type_; } const ServicePack& service_pack() const { return service_pack_; } const std::string& service_pack_str() const { return service_pack_str_; } + + // Returns the number of processors on the system. const int& processors() const { return processors_; } + + // Returns the allocation granularity. See + // https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/ns-sysinfoapi-system_info. const size_t& allocation_granularity() const { return allocation_granularity_; } + + // Returns the WOW64 status of the running process. See above for definitions + // of the values. const WOW64Status& wow64_status() const { return wow64_status_; } + + // Processor name as read from registry. std::string processor_model_name(); + + // Returns the "ReleaseId" (Windows 10 release number) from the registry. const std::string& release_id() const { return release_id_; } private:
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index 193d518..a979b5e 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -0.20201005.1.1 +0.20201005.2.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 193d518..a979b5e 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -0.20201005.1.1 +0.20201005.2.1
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 0e3616c..47688e1 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -352,6 +352,7 @@ "//chrome/browser/ui/android/favicon:java", "//chrome/browser/ui/android/native_page:java", "//chrome/browser/ui/messages/android:java", + "//chrome/browser/uid/android:java", "//chrome/browser/user_education:java", "//chrome/browser/util:java", "//chrome/browser/version:java", @@ -828,6 +829,7 @@ "//chrome/browser/ui/messages/android:junit", "//chrome/browser/user_education:java", "//chrome/browser/util:java", + "//chrome/browser/version:java", "//chrome/browser/video_tutorials:java", "//chrome/browser/video_tutorials/internal:junit", "//chrome/browser/xsurface:java", @@ -843,6 +845,7 @@ "//components/browser_ui/site_settings/android:java", "//components/browser_ui/util/android:java", "//components/browser_ui/widget/android:java", + "//components/content_capture/android:java", "//components/content_settings/android:content_settings_enums_java", "//components/dom_distiller/core/android:dom_distiller_core_java", "//components/embedder_support/android:browser_context_java", @@ -962,6 +965,7 @@ sources = chrome_test_java_sources deps = [ + ":base_module_java", ":browser_java_test_support", ":chrome_app_java_resources", ":chrome_test_util_java", @@ -1032,7 +1036,10 @@ "//chrome/browser/ui/android/favicon:java", "//chrome/browser/ui/android/native_page:java", "//chrome/browser/ui/messages/android:java", + "//chrome/browser/uid/android:java", + "//chrome/browser/uid/android:javatests", "//chrome/browser/util:java", + "//chrome/browser/version:java", "//chrome/test:sync_integration_test_support_java", "//chrome/test/android:chrome_java_test_pagecontroller", "//chrome/test/android:chrome_java_test_support", @@ -2031,6 +2038,7 @@ "//android_webview:android_webview_java", "//base:base_java", "//chrome/android:chrome_java", + "//chrome/browser/version:java", "//content/public/android:content_java", ] sources = @@ -2057,6 +2065,13 @@ sources = [ "java/src/org/chromium/chrome/browser/base/SplitChromeApplication.java", "java/src/org/chromium/chrome/browser/base/SplitCompatApplication.java", + "java/src/org/chromium/chrome/browser/base/SplitCompatIntentService.java", + "java/src/org/chromium/chrome/browser/base/SplitCompatJobService.java", + "java/src/org/chromium/chrome/browser/base/SplitCompatService.java", + "java/src/org/chromium/chrome/browser/base/SplitCompatUtils.java", + "java/src/org/chromium/chrome/browser/download/DownloadForegroundService.java", + "java/src/org/chromium/chrome/browser/notifications/NotificationJobService.java", + "java/src/org/chromium/chrome/browser/notifications/NotificationService.java", ] deps = [ ":chrome_base_module_resources",
diff --git a/chrome/android/DEPS b/chrome/android/DEPS index 177aa58..945413da 100644 --- a/chrome/android/DEPS +++ b/chrome/android/DEPS
@@ -22,6 +22,7 @@ "+chrome/browser/ui/android/favicon/java", "+chrome/browser/ui/android/native_page", "+chrome/browser/ui/messages/android", + "+chrome/browser/uid/android", "+chrome/browser/user_education", "+chrome/browser/util/android/java", "+chrome/browser/version",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni index 5084fadc..8d234c6 100644 --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni
@@ -27,7 +27,6 @@ "java/src/org/chromium/chrome/browser/ChromeStringConstants.java", "java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java", "java/src/org/chromium/chrome/browser/ChromeTabbedActivity2.java", - "java/src/org/chromium/chrome/browser/ChromeVersionInfo.java", "java/src/org/chromium/chrome/browser/ChromeWindow.java", "java/src/org/chromium/chrome/browser/DefaultBrowserInfo.java", "java/src/org/chromium/chrome/browser/DefaultBrowserInfo2.java", @@ -526,7 +525,7 @@ "java/src/org/chromium/chrome/browser/download/DownloadActivity.java", "java/src/org/chromium/chrome/browser/download/DownloadBroadcastManager.java", "java/src/org/chromium/chrome/browser/download/DownloadController.java", - "java/src/org/chromium/chrome/browser/download/DownloadForegroundService.java", + "java/src/org/chromium/chrome/browser/download/DownloadForegroundServiceImpl.java", "java/src/org/chromium/chrome/browser/download/DownloadForegroundServiceManager.java", "java/src/org/chromium/chrome/browser/download/DownloadForegroundServiceObservers.java", "java/src/org/chromium/chrome/browser/download/DownloadInfoBarController.java", @@ -798,10 +797,8 @@ "java/src/org/chromium/chrome/browser/homepage/settings/HomepageMetricsEnums.java", "java/src/org/chromium/chrome/browser/homepage/settings/HomepageSettings.java", "java/src/org/chromium/chrome/browser/homepage/settings/RadioButtonGroupHomepagePreference.java", - "java/src/org/chromium/chrome/browser/identity/SettingsSecureBasedIdentificationGenerator.java", "java/src/org/chromium/chrome/browser/identity/UniqueIdentificationGenerator.java", "java/src/org/chromium/chrome/browser/identity/UniqueIdentificationGeneratorFactory.java", - "java/src/org/chromium/chrome/browser/identity/UuidBasedUniqueIdentificationGenerator.java", "java/src/org/chromium/chrome/browser/identity_disc/IdentityDiscController.java", "java/src/org/chromium/chrome/browser/incognito/IncognitoNotificationManager.java", "java/src/org/chromium/chrome/browser/incognito/IncognitoNotificationPresenceController.java", @@ -960,9 +957,9 @@ "java/src/org/chromium/chrome/browser/notifications/NotificationBuilderBase.java", "java/src/org/chromium/chrome/browser/notifications/NotificationConstants.java", "java/src/org/chromium/chrome/browser/notifications/NotificationIntentInterceptor.java", - "java/src/org/chromium/chrome/browser/notifications/NotificationJobService.java", + "java/src/org/chromium/chrome/browser/notifications/NotificationJobServiceImpl.java", "java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java", - "java/src/org/chromium/chrome/browser/notifications/NotificationService.java", + "java/src/org/chromium/chrome/browser/notifications/NotificationServiceImpl.java", "java/src/org/chromium/chrome/browser/notifications/NotificationSettingsBridge.java", "java/src/org/chromium/chrome/browser/notifications/NotificationSystemStatusUtil.java", "java/src/org/chromium/chrome/browser/notifications/NotificationTriggerBackgroundTask.java",
diff --git a/chrome/android/chrome_junit_test_java_sources.gni b/chrome/android/chrome_junit_test_java_sources.gni index 468658f4..e29ec44f 100644 --- a/chrome/android/chrome_junit_test_java_sources.gni +++ b/chrome/android/chrome_junit_test_java_sources.gni
@@ -48,6 +48,7 @@ "junit/src/org/chromium/chrome/browser/compositor/layouts/StaticLayoutUnitTest.java", "junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java", "junit/src/org/chromium/chrome/browser/compositor/overlays/toolbar/TopToolbarOverlayMediatorTest.java", + "junit/src/org/chromium/chrome/browser/content_capture/ContentCaptureHistoryDeletionObserverTest.java", "junit/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuCoordinatorTest.java", "junit/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuHeaderMediatorTest.java", "junit/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchContextTest.java",
diff --git a/chrome/android/chrome_test_java_sources.gni b/chrome/android/chrome_test_java_sources.gni index 0a87b36e..bf18b5a 100644 --- a/chrome/android/chrome_test_java_sources.gni +++ b/chrome/android/chrome_test_java_sources.gni
@@ -225,9 +225,6 @@ "javatests/src/org/chromium/chrome/browser/homepage/HomepageTestRule.java", "javatests/src/org/chromium/chrome/browser/homepage/settings/HomepageSettingsFragmentTest.java", "javatests/src/org/chromium/chrome/browser/homepage/settings/HomepageSettingsFragmentWithEditorTest.java", - "javatests/src/org/chromium/chrome/browser/identity/SettingsSecureBasedIdentificationGeneratorTest.java", - "javatests/src/org/chromium/chrome/browser/identity/UniqueIdentificationGeneratorFactoryTest.java", - "javatests/src/org/chromium/chrome/browser/identity/UuidBasedUniqueIdentificationGeneratorTest.java", "javatests/src/org/chromium/chrome/browser/identity_disc/IdentityDiscControllerTest.java", "javatests/src/org/chromium/chrome/browser/incognito/IncognitoCookieLeakageTest.java", "javatests/src/org/chromium/chrome/browser/incognito/IncognitoDataTestUtils.java",
diff --git a/chrome/android/expectations/monochrome_public_bundle.AndroidManifest.expected b/chrome/android/expectations/monochrome_public_bundle.AndroidManifest.expected index 8525b27..cc102ae8 100644 --- a/chrome/android/expectations/monochrome_public_bundle.AndroidManifest.expected +++ b/chrome/android/expectations/monochrome_public_bundle.AndroidManifest.expected
@@ -926,11 +926,15 @@ <receiver # DIFF-ANCHOR: de24469c android:exported="false" android:name="org.chromium.chrome.browser.notifications.NotificationService$Receiver"> + </receiver> # DIFF-ANCHOR: de24469c + <receiver # DIFF-ANCHOR: 2934478c + android:exported="false" + android:name="org.chromium.chrome.browser.notifications.NotificationServiceImpl$Receiver"> <intent-filter> # DIFF-ANCHOR: 1c1c5ed8 <action android:name="org.chromium.chrome.browser.notifications.CLICK_NOTIFICATION"/> <action android:name="org.chromium.chrome.browser.notifications.CLOSE_NOTIFICATION"/> </intent-filter> # DIFF-ANCHOR: 1c1c5ed8 - </receiver> # DIFF-ANCHOR: de24469c + </receiver> # DIFF-ANCHOR: 2934478c <receiver # DIFF-ANCHOR: e1c4d394 android:exported="false" android:name="org.chromium.chrome.browser.notifications.scheduler.DisplayAgent$Receiver">
diff --git a/chrome/android/expectations/trichrome_chrome_bundle.AndroidManifest.expected b/chrome/android/expectations/trichrome_chrome_bundle.AndroidManifest.expected index 886f0cc2a..a9f3572 100644 --- a/chrome/android/expectations/trichrome_chrome_bundle.AndroidManifest.expected +++ b/chrome/android/expectations/trichrome_chrome_bundle.AndroidManifest.expected
@@ -866,11 +866,15 @@ <receiver # DIFF-ANCHOR: de24469c android:exported="false" android:name="org.chromium.chrome.browser.notifications.NotificationService$Receiver"> + </receiver> # DIFF-ANCHOR: de24469c + <receiver # DIFF-ANCHOR: 2934478c + android:exported="false" + android:name="org.chromium.chrome.browser.notifications.NotificationServiceImpl$Receiver"> <intent-filter> # DIFF-ANCHOR: 1c1c5ed8 <action android:name="org.chromium.chrome.browser.notifications.CLICK_NOTIFICATION"/> <action android:name="org.chromium.chrome.browser.notifications.CLOSE_NOTIFICATION"/> </intent-filter> # DIFF-ANCHOR: 1c1c5ed8 - </receiver> # DIFF-ANCHOR: de24469c + </receiver> # DIFF-ANCHOR: 2934478c <receiver # DIFF-ANCHOR: e1c4d394 android:exported="false" android:name="org.chromium.chrome.browser.notifications.scheduler.DisplayAgent$Receiver">
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataBinder.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataBinder.java index 05b5e35..3366291e 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataBinder.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataBinder.java
@@ -11,7 +11,6 @@ import androidx.annotation.Nullable; import org.chromium.base.task.PostTask; -import org.chromium.chrome.browser.ChromeVersionInfo; import org.chromium.chrome.browser.autofill.prefeditor.EditorDialog; import org.chromium.chrome.browser.autofill_assistant.generic_ui.AssistantValue; import org.chromium.chrome.browser.autofill_assistant.user_data.additional_sections.AssistantAdditionalSection.Delegate; @@ -23,6 +22,7 @@ import org.chromium.chrome.browser.payments.CardEditor; import org.chromium.chrome.browser.payments.ContactEditor; import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.version.ChromeVersionInfo; import org.chromium.components.payments.BasicCardUtils; import org.chromium.components.payments.MethodStrings; import org.chromium.content_public.browser.UiThreadTaskTraits;
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceLayout.java b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceLayout.java index 9804b8e..c8dceaa 100644 --- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceLayout.java +++ b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceLayout.java
@@ -20,7 +20,6 @@ import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordUserAction; import org.chromium.base.supplier.Supplier; -import org.chromium.chrome.browser.ChromeVersionInfo; import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider; import org.chromium.chrome.browser.compositor.LayerTitleCache; import org.chromium.chrome.browser.compositor.animation.CompositorAnimationHandler; @@ -38,6 +37,7 @@ import org.chromium.chrome.browser.tasks.tab_management.TabSwitcher; import org.chromium.chrome.browser.tasks.tab_management.TabUiFeatureUtilities; import org.chromium.chrome.browser.util.ChromeAccessibilityUtil; +import org.chromium.chrome.browser.version.ChromeVersionInfo; import org.chromium.components.browser_ui.widget.animation.Interpolators; import org.chromium.ui.resources.ResourceManager;
diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml index 4fb1cd15..9f77221 100644 --- a/chrome/android/java/AndroidManifest.xml +++ b/chrome/android/java/AndroidManifest.xml
@@ -1038,6 +1038,8 @@ <service android:name="org.chromium.chrome.browser.notifications.NotificationService" android:exported="false"/> <receiver android:name="org.chromium.chrome.browser.notifications.NotificationService$Receiver" + android:exported="false"/> + <receiver android:name="org.chromium.chrome.browser.notifications.NotificationServiceImpl$Receiver" android:exported="false"> <intent-filter> <action android:name="org.chromium.chrome.browser.notifications.CLICK_NOTIFICATION" />
diff --git a/chrome/android/java/DEPS b/chrome/android/java/DEPS index 6200d927..e95500a 100644 --- a/chrome/android/java/DEPS +++ b/chrome/android/java/DEPS
@@ -2,6 +2,7 @@ "-chrome/android/features/keyboard_accessory/internal", "+chrome/browser/android/lifecycle", + "+chrome/browser/device", "+chrome/browser/privacy", "+chrome/browser/profiles/android/java", "+chrome/browser/share/android",
diff --git a/chrome/android/java/res/layout/fre_tosanduma.xml b/chrome/android/java/res/layout/fre_tosanduma.xml index d6e0224..6fa5e53 100644 --- a/chrome/android/java/res/layout/fre_tosanduma.xml +++ b/chrome/android/java/res/layout/fre_tosanduma.xml
@@ -91,6 +91,7 @@ android:layout_height="wrap_content" android:lineSpacingMultiplier="1.4" android:text="@string/fre_send_report_check" + android:paddingStart="@dimen/fre_tos_checkbox_padding" android:textAppearance="@style/TextAppearance.TextMedium.Primary" /> </LinearLayout> </LinearLayout>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeStrictMode.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeStrictMode.java index c964f54..dc9bedb 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeStrictMode.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeStrictMode.java
@@ -18,6 +18,7 @@ import org.chromium.base.ThreadUtils; import org.chromium.base.library_loader.LibraryLoader; import org.chromium.chrome.browser.flags.ChromeSwitches; +import org.chromium.chrome.browser.version.ChromeVersionInfo; import org.chromium.components.strictmode.KnownViolations; import org.chromium.components.strictmode.StrictModePolicyViolation; import org.chromium.components.strictmode.ThreadStrictModeInterceptor;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeVersionInfo.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeVersionInfo.java deleted file mode 100644 index bc796d8..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeVersionInfo.java +++ /dev/null
@@ -1,12 +0,0 @@ -// Copyright 2014 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. - -package org.chromium.chrome.browser; - -/** - * Temporary class left until references are moved to the new package and build target. - * - * TODO(crbug.com/1131982): Remove this. - */ -public class ChromeVersionInfo extends org.chromium.chrome.browser.version.ChromeVersionInfo {}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/MonochromeApplication.java b/chrome/android/java/src/org/chromium/chrome/browser/MonochromeApplication.java index 7d233a4..657b2ca 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/MonochromeApplication.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/MonochromeApplication.java
@@ -12,6 +12,7 @@ import org.chromium.base.annotations.UsedByReflection; import org.chromium.base.library_loader.LibraryProcessType; import org.chromium.chrome.browser.base.SplitMonochromeApplication; +import org.chromium.chrome.browser.version.ChromeVersionInfo; import org.chromium.content_public.browser.ChildProcessCreationParams; /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/about_settings/AboutChromeSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/about_settings/AboutChromeSettings.java index c12b88f..e984d4f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/about_settings/AboutChromeSettings.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/about_settings/AboutChromeSettings.java
@@ -14,8 +14,8 @@ import androidx.preference.PreferenceFragmentCompat; import org.chromium.chrome.R; -import org.chromium.chrome.browser.ChromeVersionInfo; import org.chromium.chrome.browser.tracing.settings.DeveloperSettings; +import org.chromium.chrome.browser.version.ChromeVersionInfo; import org.chromium.components.browser_ui.settings.SettingsUtils; import org.chromium.ui.widget.Toast;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java index e451fd73e..fe4cf431 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
@@ -1739,7 +1739,7 @@ mCompositorViewHolder.setUrlBar(urlBar); mCompositorViewHolder.setInsetObserverView(getInsetObserverView()); mCompositorViewHolder.onFinishNativeInitialization( - getTabModelSelector(), this, mContextualSearchManager, mActivityTabProvider); + getTabModelSelector(), this, mContextualSearchManager); if (controlContainer != null && DeviceClassManager.enableToolbarSwipe() && getCompositorViewHolder().getLayoutManager().getToolbarSwipeHandler() != null) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillLocalCardEditor.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillLocalCardEditor.java index ed82127..f014d03 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillLocalCardEditor.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillLocalCardEditor.java
@@ -23,12 +23,12 @@ import org.chromium.base.annotations.UsedByReflection; import org.chromium.base.metrics.RecordUserAction; import org.chromium.chrome.R; -import org.chromium.chrome.browser.ChromeVersionInfo; import org.chromium.chrome.browser.autofill.PersonalDataManager; import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile; import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.payments.SettingsAutofillAndPaymentsObserver; +import org.chromium.chrome.browser.version.ChromeVersionInfo; import java.text.SimpleDateFormat; import java.util.Calendar;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/base/SplitChromeApplication.java b/chrome/android/java/src/org/chromium/chrome/browser/base/SplitChromeApplication.java index cb326b6..6858380 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/base/SplitChromeApplication.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/base/SplitChromeApplication.java
@@ -5,10 +5,6 @@ package org.chromium.chrome.browser.base; import android.content.Context; -import android.content.pm.PackageManager; -import android.os.Build; - -import org.chromium.base.compat.ApiHelperForO; /** * Application class to use for Chrome when //chrome code is in an isolated split. This class will @@ -30,8 +26,8 @@ @Override protected void attachBaseContext(Context context) { if (isBrowserProcess()) { - context = createChromeContext(context); - setImpl(createChromeApplication(context)); + context = SplitCompatUtils.createChromeContext(context); + setImpl((Impl) SplitCompatUtils.newInstance(context, mChromeApplicationClassName)); } else { setImpl(createNonBrowserApplication()); } @@ -41,29 +37,4 @@ protected Impl createNonBrowserApplication() { return new Impl(); } - - private Impl createChromeApplication(Context context) { - try { - return (Impl) context.getClassLoader() - .loadClass(mChromeApplicationClassName) - .newInstance(); - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e); - } - } - - private Context createChromeContext(Context base) { - assert isBrowserProcess(); - // Isolated splits are only supported in O+, so just return the base context on other - // versions, since this will have access to all splits. - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { - return base; - } - try { - return ApiHelperForO.createContextForSplit(base, "chrome"); - } catch (PackageManager.NameNotFoundException e) { - // This application class should not be used if the chrome split does not exist. - throw new RuntimeException(e); - } - } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatIntentService.java b/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatIntentService.java new file mode 100644 index 0000000..91b22513c --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatIntentService.java
@@ -0,0 +1,63 @@ +// 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. + +package org.chromium.chrome.browser.base; + +import android.app.IntentService; +import android.content.Context; +import android.content.Intent; +import android.os.IBinder; + +/** + * IntentService base class which will call through to the given {@link Impl}. This class must be + * present in the base module, while the Impl can be in the chrome module. + */ +public class SplitCompatIntentService extends IntentService { + private String mServiceClassName; + private Impl mImpl; + + public SplitCompatIntentService(String serviceClassName, String name) { + super(name); + mServiceClassName = serviceClassName; + } + + @Override + protected void attachBaseContext(Context context) { + context = SplitCompatUtils.createChromeContext(context); + mImpl = (Impl) SplitCompatUtils.newInstance(context, mServiceClassName); + mImpl.setService(this); + super.attachBaseContext(context); + } + + private IBinder superOnBind(Intent intent) { + return super.onBind(intent); + } + + @Override + protected void onHandleIntent(Intent intent) { + mImpl.onHandleIntent(intent); + } + + /** + * Holds the implementation of service logic. Will be called by {@link + * SplitCompatIntentService}. + */ + public abstract static class Impl { + private SplitCompatIntentService mService; + + private void setService(SplitCompatIntentService service) { + mService = service; + } + + protected final IntentService getService() { + return mService; + } + + public IBinder onBind(Intent intent) { + return mService.superOnBind(intent); + } + + protected abstract void onHandleIntent(Intent intent); + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatJobService.java b/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatJobService.java new file mode 100644 index 0000000..15ccc74 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatJobService.java
@@ -0,0 +1,58 @@ +// 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. + +package org.chromium.chrome.browser.base; + +import android.app.job.JobParameters; +import android.app.job.JobService; +import android.content.Context; + +/** + * JobService base class which will call through to the given {@link Impl}. This class must be + * present in the base module, while the Impl can be in the chrome module. + */ +public class SplitCompatJobService extends JobService { + private String mServiceClassName; + private Impl mImpl; + + public SplitCompatJobService(String serviceClassName) { + mServiceClassName = serviceClassName; + } + + @Override + protected void attachBaseContext(Context context) { + context = SplitCompatUtils.createChromeContext(context); + mImpl = (Impl) SplitCompatUtils.newInstance(context, mServiceClassName); + mImpl.setService(this); + super.attachBaseContext(context); + } + + @Override + public boolean onStartJob(JobParameters params) { + return mImpl.onStartJob(params); + } + + @Override + public boolean onStopJob(JobParameters params) { + return mImpl.onStopJob(params); + } + + /** + * Holds the implementation of service logic. Will be called by {@link SplitCompatJobService}. + */ + public abstract static class Impl { + private SplitCompatJobService mService; + + private void setService(SplitCompatJobService service) { + mService = service; + } + + protected final JobService getService() { + return mService; + } + + public abstract boolean onStartJob(JobParameters params); + public abstract boolean onStopJob(JobParameters params); + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatService.java b/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatService.java new file mode 100644 index 0000000..6a5b422 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatService.java
@@ -0,0 +1,98 @@ +// 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. + +package org.chromium.chrome.browser.base; + +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.os.IBinder; + +/** + * Service base class which will call through to the given {@link Impl}. This class must be present + * in the base module, while the Impl can be in the chrome module. + */ +public class SplitCompatService extends Service { + private String mServiceClassName; + private Impl mImpl; + + public SplitCompatService(String serviceClassName) { + mServiceClassName = serviceClassName; + } + + @Override + protected void attachBaseContext(Context context) { + context = SplitCompatUtils.createChromeContext(context); + mImpl = (Impl) SplitCompatUtils.newInstance(context, mServiceClassName); + mImpl.setService(this); + super.attachBaseContext(context); + } + + @Override + public void onCreate() { + super.onCreate(); + mImpl.onCreate(); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + return mImpl.onStartCommand(intent, flags, startId); + } + + @Override + public void onDestroy() { + super.onDestroy(); + mImpl.onDestroy(); + } + + @Override + public void onTaskRemoved(Intent rootIntent) { + super.onTaskRemoved(rootIntent); + mImpl.onTaskRemoved(rootIntent); + } + + @Override + public void onLowMemory() { + super.onLowMemory(); + mImpl.onLowMemory(); + } + + @Override + public IBinder onBind(Intent intent) { + return mImpl.onBind(intent); + } + + private int superOnStartCommand(Intent intent, int flags, int startId) { + return super.onStartCommand(intent, flags, startId); + } + + /** + * Holds the implementation of service logic. Will be called by {@link SplitCompatService}. + */ + public abstract static class Impl { + private SplitCompatService mService; + + protected void setService(SplitCompatService service) { + mService = service; + } + + protected final Service getService() { + return mService; + } + + public void onCreate() {} + + public int onStartCommand(Intent intent, int flags, int startId) { + return mService.superOnStartCommand(intent, flags, startId); + } + + public void onDestroy() {} + + public void onTaskRemoved(Intent rootIntent) {} + + public void onLowMemory() {} + + public abstract IBinder onBind(Intent intent); + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatUtils.java new file mode 100644 index 0000000..207cd06 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatUtils.java
@@ -0,0 +1,42 @@ +// 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. + +package org.chromium.chrome.browser.base; + +import android.content.Context; +import android.content.pm.PackageManager; +import android.os.Build; + +import org.chromium.base.compat.ApiHelperForO; + +/** Utils for compatibility with isolated splits. */ +public class SplitCompatUtils { + private SplitCompatUtils() {} + + /** Creates a context which can be used to load code and resources in the chrome split. */ + public static Context createChromeContext(Context base) { + // Isolated splits are only supported in O+, so just return the base context on other + // versions, since this will have access to all splits. + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { + return base; + } + try { + return ApiHelperForO.createContextForSplit(base, "chrome"); + } catch (PackageManager.NameNotFoundException e) { + // This application class should not be used if the chrome split does not exist. + throw new RuntimeException(e); + } + } + + /** + * Constructs a new instance of the given class name using the class loader from the context. + */ + public static Object newInstance(Context context, String className) { + try { + return context.getClassLoader().loadClass(className).newInstance(); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClientAppBroadcastReceiver.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClientAppBroadcastReceiver.java index ae024e9..bf498a6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClientAppBroadcastReceiver.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClientAppBroadcastReceiver.java
@@ -10,9 +10,9 @@ import org.chromium.base.Log; import org.chromium.chrome.browser.ChromeApplication; -import org.chromium.chrome.browser.ChromeVersionInfo; import org.chromium.chrome.browser.browserservices.permissiondelegation.PermissionUpdater; import org.chromium.chrome.browser.metrics.WebApkUma; +import org.chromium.chrome.browser.version.ChromeVersionInfo; import org.chromium.components.embedder_support.util.Origin; import org.chromium.components.webapk.lib.common.WebApkConstants;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java index 7a9562f..8fd5697 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
@@ -43,7 +43,6 @@ import org.chromium.base.supplier.ObservableSupplier; import org.chromium.base.supplier.ObservableSupplierImpl; import org.chromium.chrome.R; -import org.chromium.chrome.browser.ActivityTabProvider; import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider; import org.chromium.chrome.browser.browser_controls.BrowserControlsUtils; import org.chromium.chrome.browser.compositor.layouts.LayoutManager; @@ -1241,16 +1240,14 @@ * represent. * @param tabCreatorManager The {@link TabCreatorManager} for this view. * @param contextualSearchManager A {@link ContextualSearchManagementDelegate} instance. - * @param tabProvider A means of acquiring the active tab. */ public void onFinishNativeInitialization(TabModelSelector tabModelSelector, TabCreatorManager tabCreatorManager, - ContextualSearchManagementDelegate contextualSearchManager, - ActivityTabProvider tabProvider) { + ContextualSearchManagementDelegate contextualSearchManager) { assert mLayoutManager != null; mLayoutManager.init(tabModelSelector, tabCreatorManager, mControlContainer, contextualSearchManager, - mCompositorView.getResourceManager().getDynamicResourceLoader(), tabProvider); + mCompositorView.getResourceManager().getDynamicResourceLoader()); mTabModelSelector = tabModelSelector; tabModelSelector.addObserver(new EmptyTabModelSelectorObserver() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelContent.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelContent.java index af0c27c0..602916c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelContent.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelContent.java
@@ -14,13 +14,13 @@ import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.NativeMethods; -import org.chromium.chrome.browser.ChromeVersionInfo; import org.chromium.chrome.browser.WebContentsFactory; import org.chromium.chrome.browser.app.ChromeActivity; import org.chromium.chrome.browser.content.ContentUtils; import org.chromium.chrome.browser.contextualsearch.ContextualSearchManager; import org.chromium.chrome.browser.externalnav.ExternalNavigationDelegateImpl; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.version.ChromeVersionInfo; import org.chromium.components.embedder_support.delegate.WebContentsDelegateAndroid; import org.chromium.components.embedder_support.view.ContentView; import org.chromium.components.external_intents.ExternalNavigationHandler;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabCoordinator.java index fec85cff..7142f40 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabCoordinator.java
@@ -17,7 +17,6 @@ import org.chromium.base.supplier.Supplier; import org.chromium.chrome.R; import org.chromium.chrome.browser.ActivityTabProvider; -import org.chromium.chrome.browser.ChromeVersionInfo; import org.chromium.chrome.browser.WebContentsFactory; import org.chromium.chrome.browser.content.ContentUtils; import org.chromium.chrome.browser.dependency_injection.ActivityScope; @@ -29,6 +28,7 @@ import org.chromium.chrome.browser.tabmodel.TabCreator; import org.chromium.chrome.browser.ui.favicon.FaviconHelper; import org.chromium.chrome.browser.ui.favicon.FaviconUtils; +import org.chromium.chrome.browser.version.ChromeVersionInfo; import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController.SheetState;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManager.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManager.java index 8d9550c..215d728 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManager.java
@@ -16,12 +16,10 @@ import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; -import org.chromium.base.Callback; import org.chromium.base.ObserverList; import org.chromium.base.TraceEvent; import org.chromium.base.supplier.ObservableSupplier; import org.chromium.base.supplier.ObservableSupplierImpl; -import org.chromium.chrome.browser.ActivityTabProvider; import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider; import org.chromium.chrome.browser.browser_controls.BrowserControlsUtils; import org.chromium.chrome.browser.browser_controls.BrowserControlsVisibilityManager; @@ -43,7 +41,6 @@ import org.chromium.chrome.browser.compositor.scene_layer.SceneOverlayLayer; import org.chromium.chrome.browser.compositor.scene_layer.ScrollingBottomViewSceneLayer; import org.chromium.chrome.browser.contextualsearch.ContextualSearchManagementDelegate; -import org.chromium.chrome.browser.device.DeviceClassManager; import org.chromium.chrome.browser.fullscreen.BrowserControlsManager; import org.chromium.chrome.browser.gesturenav.HistoryNavigationCoordinator; import org.chromium.chrome.browser.native_page.NativePageFactory; @@ -66,10 +63,12 @@ import org.chromium.chrome.browser.tabmodel.TabModelUtils; import org.chromium.chrome.browser.toolbar.ControlContainer; import org.chromium.chrome.browser.toolbar.ToolbarColors; -import org.chromium.components.browser_ui.widget.ClipDrawableProgressBar; import org.chromium.components.embedder_support.util.UrlConstants; import org.chromium.ui.base.LocalizationUtils; import org.chromium.ui.base.SPenSupport; +import org.chromium.ui.modelutil.PropertyKey; +import org.chromium.ui.modelutil.PropertyModel; +import org.chromium.ui.modelutil.PropertyModelChangeProcessor; import org.chromium.ui.resources.ResourceManager; import org.chromium.ui.resources.dynamics.DynamicResourceLoader; import org.chromium.ui.util.TokenHolder; @@ -139,7 +138,6 @@ private boolean mUpdateRequested; private ContextualSearchPanel mContextualSearchPanel; private final OverlayPanelManager mOverlayPanelManager; - private TopToolbarOverlayCoordinator mToolbarOverlay; private SceneOverlay mGestureNavigationOverscrollGlow; /** A delegate for interacting with the Contextual Search manager. */ @@ -454,7 +452,7 @@ public void init(TabModelSelector selector, TabCreatorManager creator, @Nullable ControlContainer controlContainer, ContextualSearchManagementDelegate contextualSearchDelegate, - DynamicResourceLoader dynamicResourceLoader, ActivityTabProvider tabProvider) { + DynamicResourceLoader dynamicResourceLoader) { LayoutRenderHost renderHost = mHost.getLayoutRenderHost(); // Build Layouts @@ -466,19 +464,6 @@ setNextLayout(null); - // If fullscreen is disabled, don't bother creating this overlay; only the android view will - // ever be shown. - if (DeviceClassManager.enableFullscreen()) { - Callback<ClipDrawableProgressBar.DrawingInfo> progressInfoCallback = (info) -> { - if (controlContainer == null) return; - controlContainer.getProgressBarDrawingInfo(info); - }; - mToolbarOverlay = new TopToolbarOverlayCoordinator(mContext, mFrameRequestSupplier, - this, progressInfoCallback, tabProvider, getBrowserControlsManager(), - mAndroidViewShownSupplier, () -> renderHost.getResourceManager()); - addSceneOverlay(mToolbarOverlay); - } - // Initialize Layouts mStaticLayout.onFinishNativeInitialization(); @@ -563,7 +548,6 @@ * Cleans up and destroys this object. It should not be used after this. */ public void destroy() { - if (mToolbarOverlay != null) mToolbarOverlay.destroy(); mAnimationHandler.destroy(); mSceneChangeObservers.clear(); if (mStaticLayout != null) mStaticLayout.destroy(); @@ -578,6 +562,27 @@ } } + /** @return A resource manager to pull textures from. */ + public ResourceManager getResourceManager() { + if (mHost.getLayoutRenderHost() == null) return null; + return mHost.getLayoutRenderHost().getResourceManager(); + } + + /** + * Creates a CompositorModelChangeProcessor observing the given {@code model} that will operate + * on this {@link LayoutManager}'s frame cycle. The model will be bound to the view initially + * and request a new frame. + * @param model The model containing the data to be bound to the view. + * @param view The view which the model will be bound to. + * @param viewBinder This is used to bind the model to the view. + */ + public <V extends SceneLayer> CompositorModelChangeProcessor<V> createCompositorMCP( + PropertyModel model, V view, + PropertyModelChangeProcessor.ViewBinder<PropertyModel, V, PropertyKey> viewBinder) { + return CompositorModelChangeProcessor.create( + model, view, viewBinder, mFrameRequestSupplier, true); + } + /** * @param observer Adds {@code observer} to be notified when the active {@code Layout} changes. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java index 706cf73..22cc928 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java
@@ -15,7 +15,6 @@ import org.chromium.base.metrics.RecordUserAction; import org.chromium.base.supplier.ObservableSupplier; import org.chromium.base.supplier.OneshotSupplierImpl; -import org.chromium.chrome.browser.ActivityTabProvider; import org.chromium.chrome.browser.accessibility_tab_switcher.OverviewListLayout; import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider; import org.chromium.chrome.browser.compositor.TitleCache; @@ -169,7 +168,7 @@ public void init(TabModelSelector selector, TabCreatorManager creator, ControlContainer controlContainer, ContextualSearchManagementDelegate contextualSearchDelegate, - DynamicResourceLoader dynamicResourceLoader, ActivityTabProvider tabProvider) { + DynamicResourceLoader dynamicResourceLoader) { Context context = mHost.getContext(); LayoutRenderHost renderHost = mHost.getLayoutRenderHost(); BrowserControlsStateProvider browserControlsStateProvider = @@ -188,7 +187,7 @@ } super.init(selector, creator, controlContainer, contextualSearchDelegate, - dynamicResourceLoader, tabProvider); + dynamicResourceLoader); // TODO: TitleCache should be a part of the ResourceManager. mTitleCache = mHost.getTitleCache();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromePhone.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromePhone.java index dd6da30..3c32937 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromePhone.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromePhone.java
@@ -9,7 +9,6 @@ import org.chromium.base.supplier.ObservableSupplier; import org.chromium.base.supplier.OneshotSupplierImpl; -import org.chromium.chrome.browser.ActivityTabProvider; import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager; import org.chromium.chrome.browser.compositor.layouts.phone.SimpleAnimationLayout; import org.chromium.chrome.browser.compositor.overlays.SceneOverlay; @@ -52,7 +51,7 @@ public void init(TabModelSelector selector, TabCreatorManager creator, ControlContainer controlContainer, ContextualSearchManagementDelegate contextualSearchDelegate, - DynamicResourceLoader dynamicResourceLoader, ActivityTabProvider tabProvider) { + DynamicResourceLoader dynamicResourceLoader) { Context context = mHost.getContext(); LayoutRenderHost renderHost = mHost.getLayoutRenderHost(); @@ -60,7 +59,7 @@ mSimpleAnimationLayout = new SimpleAnimationLayout(context, this, renderHost); super.init(selector, creator, controlContainer, contextualSearchDelegate, - dynamicResourceLoader, tabProvider); + dynamicResourceLoader); // Set up layout parameters mStaticLayout.setLayoutHandlesTabLifecycles(false);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromeTablet.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromeTablet.java index 46d3eccc..2766759 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromeTablet.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromeTablet.java
@@ -9,7 +9,6 @@ import org.chromium.base.supplier.ObservableSupplier; import org.chromium.base.supplier.OneshotSupplierImpl; import org.chromium.chrome.R; -import org.chromium.chrome.browser.ActivityTabProvider; import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager; import org.chromium.chrome.browser.compositor.overlays.strip.StripLayoutHelperManager; import org.chromium.chrome.browser.contextualsearch.ContextualSearchManagementDelegate; @@ -85,13 +84,13 @@ public void init(TabModelSelector selector, TabCreatorManager creator, ControlContainer controlContainer, ContextualSearchManagementDelegate contextualSearchDelegate, - DynamicResourceLoader dynamicResourceLoader, ActivityTabProvider tabProvider) { + DynamicResourceLoader dynamicResourceLoader) { if (mTabStripLayoutHelperManager != null) { mTabStripLayoutHelperManager.setTabModelSelector(selector, creator); } super.init(selector, creator, controlContainer, contextualSearchDelegate, - dynamicResourceLoader, tabProvider); + dynamicResourceLoader); // Make sure any tabs already restored get loaded into the title cache. List<TabModel> models = selector.getModels();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/toolbar/TopToolbarOverlayCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/toolbar/TopToolbarOverlayCoordinator.java index c6ff93c..a4e4a75 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/toolbar/TopToolbarOverlayCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/toolbar/TopToolbarOverlayCoordinator.java
@@ -8,8 +8,6 @@ import android.graphics.RectF; import org.chromium.base.Callback; -import org.chromium.base.supplier.ObservableSupplier; -import org.chromium.base.supplier.Supplier; import org.chromium.chrome.R; import org.chromium.chrome.browser.ActivityTabProvider; import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider; @@ -40,14 +38,10 @@ /** Business logic for this overlay. */ private final TopToolbarOverlayMediator mMediator; - public TopToolbarOverlayCoordinator(Context context, - CompositorModelChangeProcessor.FrameRequestSupplier frameRequestSupplier, - LayoutManager layoutManager, + public TopToolbarOverlayCoordinator(Context context, LayoutManager layoutManager, Callback<ClipDrawableProgressBar.DrawingInfo> progressInfoCallback, ActivityTabProvider tabSupplier, - BrowserControlsStateProvider browserControlsStateProvider, - ObservableSupplier<Boolean> androidViewShownSupplier, - Supplier<ResourceManager> resourceManagerSupplier) { + BrowserControlsStateProvider browserControlsStateProvider) { mModel = new PropertyModel.Builder(TopToolbarOverlayProperties.ALL_KEYS) .with(TopToolbarOverlayProperties.RESOURCE_ID, R.id.control_container) .with(TopToolbarOverlayProperties.URL_BAR_RESOURCE_ID, @@ -56,13 +50,20 @@ .with(TopToolbarOverlayProperties.CONTENT_OFFSET, browserControlsStateProvider.getContentOffset()) .build(); - mSceneLayer = new TopToolbarSceneLayer(resourceManagerSupplier); - mChangeProcessor = CompositorModelChangeProcessor.create( - mModel, mSceneLayer, TopToolbarSceneLayer::bind, frameRequestSupplier, true); + mSceneLayer = new TopToolbarSceneLayer(() -> layoutManager.getResourceManager()); + mChangeProcessor = + layoutManager.createCompositorMCP(mModel, mSceneLayer, TopToolbarSceneLayer::bind); - mMediator = - new TopToolbarOverlayMediator(mModel, context, layoutManager, progressInfoCallback, - tabSupplier, browserControlsStateProvider, androidViewShownSupplier); + mMediator = new TopToolbarOverlayMediator(mModel, context, layoutManager, + progressInfoCallback, tabSupplier, browserControlsStateProvider); + } + + /** + * Set whether the android view corresponding with this overlay is showing. + * @param isVisible Whether the android view is visible. + */ + public void setIsAndroidViewVisible(boolean isVisible) { + mMediator.setIsAndroidViewVisible(isVisible); } /** Clean up this component. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/toolbar/TopToolbarOverlayMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/toolbar/TopToolbarOverlayMediator.java index e22db22..2b7fe3c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/toolbar/TopToolbarOverlayMediator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/toolbar/TopToolbarOverlayMediator.java
@@ -10,7 +10,6 @@ import androidx.annotation.VisibleForTesting; import org.chromium.base.Callback; -import org.chromium.base.supplier.ObservableSupplier; import org.chromium.chrome.browser.ActivityTabProvider; import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider; import org.chromium.chrome.browser.browser_controls.BrowserControlsUtils; @@ -58,12 +57,6 @@ /** An observer of the browser controls offsets. */ private final BrowserControlsStateProvider.Observer mBrowserControlsObserver; - /** A means of checking whether the toolbar android view is being force-hidden or shown. */ - private final ObservableSupplier<Boolean> mAndroidViewShownSupplier; - - /** An observer of the android view's hidden state. */ - private final Callback<Boolean> mAndroidViewShownObserver; - /** The view state for this overlay. */ private final PropertyModel mModel; @@ -73,17 +66,18 @@ /** Whether the active layout has its own toolbar to display instead of this one. */ private boolean mLayoutHasOwnToolbar; + /** Whether the android view for this overlay is visible. */ + private boolean mIsAndroidViewVisible; + TopToolbarOverlayMediator(PropertyModel model, Context context, LayoutManager layoutManager, Callback<ClipDrawableProgressBar.DrawingInfo> progressInfoCallback, ActivityTabProvider tabSupplier, - BrowserControlsStateProvider browserControlsStateProvider, - ObservableSupplier<Boolean> androidViewShownSupplier) { + BrowserControlsStateProvider browserControlsStateProvider) { mContext = context; mLayoutManager = layoutManager; mProgressInfoCallback = progressInfoCallback; mTabSupplier = tabSupplier; mBrowserControlsStateProvider = browserControlsStateProvider; - mAndroidViewShownSupplier = androidViewShownSupplier; mModel = model; mSceneChangeObserver = new SceneChangeObserver() { @@ -134,9 +128,6 @@ }; mTabSupplier.addObserverAndTrigger(mTabSupplierObserver); - mAndroidViewShownObserver = (shown) -> updateShadowState(); - mAndroidViewShownSupplier.addObserver(mAndroidViewShownObserver); - mBrowserControlsObserver = new BrowserControlsStateProvider.Observer() { @Override public void onControlsOffsetChanged(int topOffset, int topControlsMinHeightOffset, @@ -158,13 +149,22 @@ } /** + * Set whether the android view corresponding with this overlay is showing. + * @param isVisible Whether the android view is visible. + */ + void setIsAndroidViewVisible(boolean isVisible) { + mIsAndroidViewVisible = isVisible; + updateShadowState(); + } + + /** * Compute whether the texture's shadow should be visible. The shadow is visible whenever the * android view is not shown. */ private void updateShadowState() { boolean drawControlsAsTexture = BrowserControlsUtils.drawControlsAsTexture(mBrowserControlsStateProvider); - boolean showShadow = drawControlsAsTexture || !mAndroidViewShownSupplier.get(); + boolean showShadow = drawControlsAsTexture || !mIsAndroidViewVisible; mModel.set(TopToolbarOverlayProperties.SHOW_SHADOW, showShadow); } @@ -231,7 +231,6 @@ mLastActiveTab = null; mLayoutManager.removeSceneChangeObserver(mSceneChangeObserver); - mAndroidViewShownSupplier.removeObserver(mAndroidViewShownObserver); mBrowserControlsStateProvider.removeObserver(mBrowserControlsObserver); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/content_capture/ContentCaptureHistoryDeletionObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/content_capture/ContentCaptureHistoryDeletionObserver.java index f322b34..043ca55 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/content_capture/ContentCaptureHistoryDeletionObserver.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/content_capture/ContentCaptureHistoryDeletionObserver.java
@@ -4,27 +4,37 @@ package org.chromium.chrome.browser.content_capture; +import org.chromium.base.supplier.Supplier; import org.chromium.chrome.browser.history.HistoryDeletionBridge; import org.chromium.chrome.browser.history.HistoryDeletionInfo; import org.chromium.components.content_capture.ContentCaptureController; /** History deletion observer that calls ContentCapture methods. */ public class ContentCaptureHistoryDeletionObserver implements HistoryDeletionBridge.Observer { + Supplier<ContentCaptureController> mContentCaptureControllerSupplier; + + public ContentCaptureHistoryDeletionObserver( + Supplier<ContentCaptureController> contentCaptureControllerSupplier) { + mContentCaptureControllerSupplier = contentCaptureControllerSupplier; + } + /** Observer method when a bit of history is deleted. */ @Override public void onURLsDeleted(HistoryDeletionInfo historyDeletionInfo) { - ContentCaptureController contentCaptureController = ContentCaptureController.getInstance(); + ContentCaptureController contentCaptureController = mContentCaptureControllerSupplier.get(); if (contentCaptureController == null) return; - if (historyDeletionInfo.isTimeRangeForAllTime() - || (historyDeletionInfo.isTimeRangeValid() - && historyDeletionInfo.getTimeRangeBegin() - != historyDeletionInfo.getTimeRangeEnd())) { + // A timerange deletion is equivalent to deleting "all" history. + if (historyDeletionInfo.isTimeRangeForAllTime() || historyDeletionInfo.isTimeRangeValid()) { contentCaptureController.clearAllContentCaptureData(); } else { String[] deletedURLs = historyDeletionInfo.getDeletedURLs(); if (deletedURLs.length > 0) { - contentCaptureController.clearContentCaptureDataForURLs(deletedURLs); + try { + contentCaptureController.clearContentCaptureDataForURLs(deletedURLs); + } catch (RuntimeException e) { + throw new RuntimeException("Deleted URLs length: " + deletedURLs.length, e); + } } } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java index 47c67c0..b32e3b26 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java
@@ -15,7 +15,6 @@ import androidx.annotation.VisibleForTesting; import org.chromium.base.CollectionUtil; -import org.chromium.chrome.browser.ChromeVersionInfo; import org.chromium.chrome.browser.compositor.bottombar.contextualsearch.ContextualSearchPanel; import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial.ContextualSearchSetting; import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial.ContextualSearchSwitch; @@ -27,6 +26,7 @@ import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory; import org.chromium.chrome.browser.signin.UnifiedConsentServiceBridge; +import org.chromium.chrome.browser.version.ChromeVersionInfo; import org.chromium.components.embedder_support.util.UrlConstants; import java.net.URL;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/crash/PureJavaExceptionReporter.java b/chrome/android/java/src/org/chromium/chrome/browser/crash/PureJavaExceptionReporter.java index 452b70a..4739e8b2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/crash/PureJavaExceptionReporter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/crash/PureJavaExceptionReporter.java
@@ -19,7 +19,7 @@ import org.chromium.base.PiiElider; import org.chromium.base.StrictModeContext; import org.chromium.base.annotations.MainDex; -import org.chromium.chrome.browser.ChromeVersionInfo; +import org.chromium.chrome.browser.version.ChromeVersionInfo; import org.chromium.components.crash.CrashKeys; import java.io.File;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java index 79b99fe..d78d69bd 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
@@ -40,11 +40,11 @@ import org.chromium.base.Log; import org.chromium.base.metrics.RecordUserAction; import org.chromium.chrome.R; -import org.chromium.chrome.browser.ChromeVersionInfo; import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.app.ChromeActivity; import org.chromium.chrome.browser.browserservices.BrowserServicesIntentDataProvider; import org.chromium.chrome.browser.flags.ActivityType; +import org.chromium.chrome.browser.version.ChromeVersionInfo; import org.chromium.components.browser_ui.styles.ChromeColors; import org.chromium.components.browser_ui.widget.TintedDrawable; import org.chromium.components.embedder_support.util.UrlConstants;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadForegroundService.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadForegroundService.java index f252594..49a4e4c4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadForegroundService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadForegroundService.java
@@ -1,248 +1,16 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. +// 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. package org.chromium.chrome.browser.download; -import static org.chromium.chrome.browser.download.DownloadSnackbarController.INVALID_NOTIFICATION_ID; +import org.chromium.chrome.browser.base.SplitCompatService; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.Service; -import android.content.Context; -import android.content.Intent; -import android.os.Binder; -import android.os.Build; -import android.os.IBinder; - -import androidx.annotation.IntDef; -import androidx.annotation.Nullable; -import androidx.annotation.VisibleForTesting; -import androidx.core.app.ServiceCompat; - -import org.chromium.base.ContextUtils; -import org.chromium.base.Log; -import org.chromium.components.browser_ui.notifications.ForegroundServiceUtils; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * Keep-alive foreground service for downloads. - */ -public class DownloadForegroundService extends Service { - private static final String TAG = "DownloadFg"; - private final IBinder mBinder = new LocalBinder(); - - private NotificationManager mNotificationManager; - - @IntDef({StopForegroundNotification.KILL, StopForegroundNotification.DETACH}) - @Retention(RetentionPolicy.SOURCE) - public @interface StopForegroundNotification { - int KILL = 0; // Kill notification regardless of ability to detach. - int DETACH = 1; // Try to detach, otherwise kill and relaunch. - } - - @Override - public void onCreate() { - super.onCreate(); - - mNotificationManager = - (NotificationManager) ContextUtils.getApplicationContext().getSystemService( - Context.NOTIFICATION_SERVICE); - } - - /** - * Start the foreground service with this given context. - * @param context The context used to start service. - */ - public static void startDownloadForegroundService(Context context) { - // TODO(crbug.com/770389): Grab a WakeLock here until the service has started. - ForegroundServiceUtils.getInstance().startForegroundService( - new Intent(context, DownloadForegroundService.class)); - } - - /** - * Start the foreground service or update it to be pinned to a different notification. - * - * @param newNotificationId The ID of the new notification to pin the service to. - * @param newNotification The new notification to be pinned to the service. - * @param oldNotificationId The ID of the original notification that was pinned to the - * service, can be INVALID_NOTIFICATION_ID if the service is just - * starting. - * @param oldNotification The original notification the service was pinned to, in case an - * adjustment needs to be made (in the case it could not be - * detached). - * @param killOldNotification Whether or not to detach or kill the old notification. - */ - public void startOrUpdateForegroundService(int newNotificationId, Notification newNotification, - int oldNotificationId, Notification oldNotification, boolean killOldNotification) { - Log.w(TAG, - "startOrUpdateForegroundService new: " + newNotificationId - + ", old: " + oldNotificationId + ", kill old: " + killOldNotification); - // Handle notifications and start foreground. - if (oldNotificationId == INVALID_NOTIFICATION_ID && oldNotification == null) { - // If there is no old notification or old notification id, just start foreground. - startForegroundInternal(newNotificationId, newNotification); - } else { - if (getCurrentSdk() >= 24) { - // If possible, detach notification so it doesn't get cancelled by accident. - stopForegroundInternal(killOldNotification ? ServiceCompat.STOP_FOREGROUND_REMOVE - : ServiceCompat.STOP_FOREGROUND_DETACH); - startForegroundInternal(newNotificationId, newNotification); - } else { - // Otherwise start the foreground and relaunch the originally pinned notification. - startForegroundInternal(newNotificationId, newNotification); - if (!killOldNotification) { - relaunchOldNotification(oldNotificationId, oldNotification); - } - } - } - - // Record when starting foreground and when updating pinned notification. - if (oldNotificationId == INVALID_NOTIFICATION_ID) { - DownloadNotificationUmaHelper.recordForegroundServiceLifecycleHistogram( - DownloadNotificationUmaHelper.ForegroundLifecycle.START); - } else { - if (oldNotificationId != newNotificationId) { - DownloadNotificationUmaHelper.recordForegroundServiceLifecycleHistogram( - DownloadNotificationUmaHelper.ForegroundLifecycle.UPDATE); - } - } - } - - /** - * Stop the foreground service that is running. - * - * @param stopForegroundNotification How to handle the notification upon the foreground - * stopping (options are: kill, detach or adjust, or detach - * or persist, see {@link StopForegroundNotification}. - * @param pinnedNotificationId Id of the notification that is pinned to the foreground - * and would need adjustment. - * @param pinnedNotification The actual notification that is pinned to the foreground - * and would need adjustment. - */ - public void stopDownloadForegroundService( - @StopForegroundNotification int stopForegroundNotification, int pinnedNotificationId, - Notification pinnedNotification) { - Log.w(TAG, - "stopDownloadForegroundService status: " + stopForegroundNotification - + ", id: " + pinnedNotificationId); - // Record when stopping foreground. - DownloadNotificationUmaHelper.recordForegroundServiceLifecycleHistogram( - DownloadNotificationUmaHelper.ForegroundLifecycle.STOP); - DownloadNotificationUmaHelper.recordServiceStoppedHistogram( - DownloadNotificationUmaHelper.ServiceStopped.STOPPED, true /* withForeground */); - - // Handle notifications and stop foreground. - if (stopForegroundNotification == StopForegroundNotification.KILL) { - // Regardless of the SDK level, stop foreground and kill if so indicated. - stopForegroundInternal(ServiceCompat.STOP_FOREGROUND_REMOVE); - } else { - if (getCurrentSdk() >= 24) { - // Android N+ has the option to detach notifications from the service, so detach or - // kill the notification as needed when stopping service. - stopForegroundInternal(ServiceCompat.STOP_FOREGROUND_DETACH); - } else if (getCurrentSdk() >= 23) { - // Android M+ can't detach the notification but doesn't have other caveats. Kill the - // notification and relaunch if detach was desired. - stopForegroundInternal(ServiceCompat.STOP_FOREGROUND_REMOVE); - relaunchOldNotification(pinnedNotificationId, pinnedNotification); - } else { - // In phones that are Lollipop and older (API < 23), the service gets killed with - // the task, which might result in the notification being unable to be relaunched - // where it needs to be. kill and relaunch the old notification before stopping the - // service. - relaunchOldNotification( - getNewNotificationIdFor(pinnedNotificationId), pinnedNotification); - stopForegroundInternal(ServiceCompat.STOP_FOREGROUND_REMOVE); - } - } - stopSelf(); - } - - @VisibleForTesting - void relaunchOldNotification(int notificationId, Notification notification) { - if (notificationId != INVALID_NOTIFICATION_ID && notification != null) { - mNotificationManager.notify(notificationId, notification); - } - } - - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - // In the case the service was restarted when the intent is null. - if (intent == null) { - DownloadNotificationUmaHelper.recordServiceStoppedHistogram( - DownloadNotificationUmaHelper.ServiceStopped.START_STICKY, true); - - // Allow observers to restart service on their own, if needed. - stopSelf(); - } - - // This should restart service after Chrome gets killed (except for Android 4.4.2). - return START_STICKY; - } - - @Override - public void onDestroy() { - DownloadNotificationUmaHelper.recordServiceStoppedHistogram( - DownloadNotificationUmaHelper.ServiceStopped.DESTROYED, true /* withForeground */); - DownloadForegroundServiceObservers.alertObserversServiceDestroyed(); - super.onDestroy(); - } - - @Override - public void onTaskRemoved(Intent rootIntent) { - DownloadNotificationUmaHelper.recordServiceStoppedHistogram( - DownloadNotificationUmaHelper.ServiceStopped.TASK_REMOVED, true /*withForeground*/); - DownloadForegroundServiceObservers.alertObserversTaskRemoved(); - super.onTaskRemoved(rootIntent); - } - - @Override - public void onLowMemory() { - DownloadNotificationUmaHelper.recordServiceStoppedHistogram( - DownloadNotificationUmaHelper.ServiceStopped.LOW_MEMORY, true /* withForeground */); - super.onLowMemory(); - } - - @Nullable - @Override - public IBinder onBind(Intent intent) { - return mBinder; - } - - /** - * Class for clients to access. - */ - class LocalBinder extends Binder { - DownloadForegroundService getService() { - return DownloadForegroundService.this; - } - } - - /** Methods for testing. */ - - @VisibleForTesting - int getNewNotificationIdFor(int oldNotificationId) { - return DownloadNotificationService.getNewNotificationIdFor(oldNotificationId); - } - - @VisibleForTesting - void startForegroundInternal(int notificationId, Notification notification) { - Log.w(TAG, "startForegroundInternal id: " + notificationId); - ForegroundServiceUtils.getInstance().startForeground( - this, notificationId, notification, 0 /* foregroundServiceType */); - } - - @VisibleForTesting - void stopForegroundInternal(int flags) { - Log.w(TAG, "stopForegroundInternal flags: " + flags); - ForegroundServiceUtils.getInstance().stopForeground(this, flags); - } - - @VisibleForTesting - int getCurrentSdk() { - return Build.VERSION.SDK_INT; +/** See {@link DownloadForegroundServiceImpl}. */ +public class DownloadForegroundService extends SplitCompatService { + // TODO(crbug.com/1126301): Use R8's -identifiernamestring to verify this and other + // SplitCompatService subclasses. + public DownloadForegroundService() { + super("org.chromium.chrome.browser.download.DownloadForegroundServiceImpl"); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadForegroundServiceImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadForegroundServiceImpl.java new file mode 100644 index 0000000..ce190d2d --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadForegroundServiceImpl.java
@@ -0,0 +1,253 @@ +// Copyright 2017 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. + +package org.chromium.chrome.browser.download; + +import static org.chromium.chrome.browser.download.DownloadSnackbarController.INVALID_NOTIFICATION_ID; + +import android.app.Notification; +import android.app.NotificationManager; +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.os.Binder; +import android.os.Build; +import android.os.IBinder; + +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; +import androidx.core.app.ServiceCompat; + +import org.chromium.base.ContextUtils; +import org.chromium.base.Log; +import org.chromium.base.annotations.UsedByReflection; +import org.chromium.components.browser_ui.notifications.ForegroundServiceUtils; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Keep-alive foreground service for downloads. + */ +@UsedByReflection("DownloadForegroundService.java") +public class DownloadForegroundServiceImpl extends DownloadForegroundService.Impl { + private static final String TAG = "DownloadFg"; + private final IBinder mBinder = new LocalBinder(); + + private NotificationManager mNotificationManager; + + @IntDef({StopForegroundNotification.KILL, StopForegroundNotification.DETACH}) + @Retention(RetentionPolicy.SOURCE) + public @interface StopForegroundNotification { + int KILL = 0; // Kill notification regardless of ability to detach. + int DETACH = 1; // Try to detach, otherwise kill and relaunch. + } + + @UsedByReflection("DownloadForegroundService.java") + public DownloadForegroundServiceImpl() {} + + @Override + public void onCreate() { + super.onCreate(); + + mNotificationManager = + (NotificationManager) ContextUtils.getApplicationContext().getSystemService( + Context.NOTIFICATION_SERVICE); + } + + /** + * Start the foreground service with this given context. + * @param context The context used to start service. + */ + public static void startDownloadForegroundService(Context context) { + // TODO(crbug.com/770389): Grab a WakeLock here until the service has started. + ForegroundServiceUtils.getInstance().startForegroundService( + new Intent(context, DownloadForegroundService.class)); + } + + /** + * Start the foreground service or update it to be pinned to a different notification. + * + * @param newNotificationId The ID of the new notification to pin the service to. + * @param newNotification The new notification to be pinned to the service. + * @param oldNotificationId The ID of the original notification that was pinned to the + * service, can be INVALID_NOTIFICATION_ID if the service is just + * starting. + * @param oldNotification The original notification the service was pinned to, in case an + * adjustment needs to be made (in the case it could not be + * detached). + * @param killOldNotification Whether or not to detach or kill the old notification. + */ + public void startOrUpdateForegroundService(int newNotificationId, Notification newNotification, + int oldNotificationId, Notification oldNotification, boolean killOldNotification) { + Log.w(TAG, + "startOrUpdateForegroundService new: " + newNotificationId + + ", old: " + oldNotificationId + ", kill old: " + killOldNotification); + // Handle notifications and start foreground. + if (oldNotificationId == INVALID_NOTIFICATION_ID && oldNotification == null) { + // If there is no old notification or old notification id, just start foreground. + startForegroundInternal(newNotificationId, newNotification); + } else { + if (getCurrentSdk() >= 24) { + // If possible, detach notification so it doesn't get cancelled by accident. + stopForegroundInternal(killOldNotification ? ServiceCompat.STOP_FOREGROUND_REMOVE + : ServiceCompat.STOP_FOREGROUND_DETACH); + startForegroundInternal(newNotificationId, newNotification); + } else { + // Otherwise start the foreground and relaunch the originally pinned notification. + startForegroundInternal(newNotificationId, newNotification); + if (!killOldNotification) { + relaunchOldNotification(oldNotificationId, oldNotification); + } + } + } + + // Record when starting foreground and when updating pinned notification. + if (oldNotificationId == INVALID_NOTIFICATION_ID) { + DownloadNotificationUmaHelper.recordForegroundServiceLifecycleHistogram( + DownloadNotificationUmaHelper.ForegroundLifecycle.START); + } else { + if (oldNotificationId != newNotificationId) { + DownloadNotificationUmaHelper.recordForegroundServiceLifecycleHistogram( + DownloadNotificationUmaHelper.ForegroundLifecycle.UPDATE); + } + } + } + + /** + * Stop the foreground service that is running. + * + * @param stopForegroundNotification How to handle the notification upon the foreground + * stopping (options are: kill, detach or adjust, or detach + * or persist, see {@link StopForegroundNotification}. + * @param pinnedNotificationId Id of the notification that is pinned to the foreground + * and would need adjustment. + * @param pinnedNotification The actual notification that is pinned to the foreground + * and would need adjustment. + */ + public void stopDownloadForegroundService( + @StopForegroundNotification int stopForegroundNotification, int pinnedNotificationId, + Notification pinnedNotification) { + Log.w(TAG, + "stopDownloadForegroundService status: " + stopForegroundNotification + + ", id: " + pinnedNotificationId); + // Record when stopping foreground. + DownloadNotificationUmaHelper.recordForegroundServiceLifecycleHistogram( + DownloadNotificationUmaHelper.ForegroundLifecycle.STOP); + DownloadNotificationUmaHelper.recordServiceStoppedHistogram( + DownloadNotificationUmaHelper.ServiceStopped.STOPPED, true /* withForeground */); + + // Handle notifications and stop foreground. + if (stopForegroundNotification == StopForegroundNotification.KILL) { + // Regardless of the SDK level, stop foreground and kill if so indicated. + stopForegroundInternal(ServiceCompat.STOP_FOREGROUND_REMOVE); + } else { + if (getCurrentSdk() >= 24) { + // Android N+ has the option to detach notifications from the service, so detach or + // kill the notification as needed when stopping service. + stopForegroundInternal(ServiceCompat.STOP_FOREGROUND_DETACH); + } else if (getCurrentSdk() >= 23) { + // Android M+ can't detach the notification but doesn't have other caveats. Kill the + // notification and relaunch if detach was desired. + stopForegroundInternal(ServiceCompat.STOP_FOREGROUND_REMOVE); + relaunchOldNotification(pinnedNotificationId, pinnedNotification); + } else { + // In phones that are Lollipop and older (API < 23), the service gets killed with + // the task, which might result in the notification being unable to be relaunched + // where it needs to be. kill and relaunch the old notification before stopping the + // service. + relaunchOldNotification( + getNewNotificationIdFor(pinnedNotificationId), pinnedNotification); + stopForegroundInternal(ServiceCompat.STOP_FOREGROUND_REMOVE); + } + } + getService().stopSelf(); + } + + @VisibleForTesting + void relaunchOldNotification(int notificationId, Notification notification) { + if (notificationId != INVALID_NOTIFICATION_ID && notification != null) { + mNotificationManager.notify(notificationId, notification); + } + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + // In the case the service was restarted when the intent is null. + if (intent == null) { + DownloadNotificationUmaHelper.recordServiceStoppedHistogram( + DownloadNotificationUmaHelper.ServiceStopped.START_STICKY, true); + + // Allow observers to restart service on their own, if needed. + getService().stopSelf(); + } + + // This should restart service after Chrome gets killed (except for Android 4.4.2). + return Service.START_STICKY; + } + + @Override + public void onDestroy() { + DownloadNotificationUmaHelper.recordServiceStoppedHistogram( + DownloadNotificationUmaHelper.ServiceStopped.DESTROYED, true /* withForeground */); + DownloadForegroundServiceObservers.alertObserversServiceDestroyed(); + super.onDestroy(); + } + + @Override + public void onTaskRemoved(Intent rootIntent) { + DownloadNotificationUmaHelper.recordServiceStoppedHistogram( + DownloadNotificationUmaHelper.ServiceStopped.TASK_REMOVED, true /*withForeground*/); + DownloadForegroundServiceObservers.alertObserversTaskRemoved(); + super.onTaskRemoved(rootIntent); + } + + @Override + public void onLowMemory() { + DownloadNotificationUmaHelper.recordServiceStoppedHistogram( + DownloadNotificationUmaHelper.ServiceStopped.LOW_MEMORY, true /* withForeground */); + super.onLowMemory(); + } + + @Nullable + @Override + public IBinder onBind(Intent intent) { + return mBinder; + } + + /** + * Class for clients to access. + */ + class LocalBinder extends Binder { + DownloadForegroundServiceImpl getService() { + return DownloadForegroundServiceImpl.this; + } + } + + /** Methods for testing. */ + + @VisibleForTesting + int getNewNotificationIdFor(int oldNotificationId) { + return DownloadNotificationService.getNewNotificationIdFor(oldNotificationId); + } + + @VisibleForTesting + void startForegroundInternal(int notificationId, Notification notification) { + Log.w(TAG, "startForegroundInternal id: " + notificationId); + ForegroundServiceUtils.getInstance().startForeground( + getService(), notificationId, notification, 0 /* foregroundServiceType */); + } + + @VisibleForTesting + void stopForegroundInternal(int flags) { + Log.w(TAG, "stopForegroundInternal flags: " + flags); + ForegroundServiceUtils.getInstance().stopForeground(getService(), flags); + } + + @VisibleForTesting + int getCurrentSdk() { + return Build.VERSION.SDK_INT; + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadForegroundServiceManager.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadForegroundServiceManager.java index ec2ad32..7678179 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadForegroundServiceManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadForegroundServiceManager.java
@@ -80,7 +80,7 @@ private boolean mStartForegroundCalled; // This is non-null when onServiceConnected has been called (aka service is active). - private DownloadForegroundService mBoundService; + private DownloadForegroundServiceImpl mBoundService; @VisibleForTesting final Map<Integer, DownloadUpdate> mDownloadUpdateQueue = new HashMap<>(); @@ -221,7 +221,7 @@ @VisibleForTesting void startAndBindServiceInternal(Context context) { - DownloadForegroundService.startDownloadForegroundService(context); + DownloadForegroundServiceImpl.startDownloadForegroundService(context); context.bindService(new Intent(context, DownloadForegroundService.class), mConnection, Context.BIND_AUTO_CREATE); } @@ -230,13 +230,13 @@ @Override public void onServiceConnected(ComponentName className, IBinder service) { Log.w(TAG, "onServiceConnected"); - if (!(service instanceof DownloadForegroundService.LocalBinder)) { + if (!(service instanceof DownloadForegroundServiceImpl.LocalBinder)) { Log.w(TAG, "Not from DownloadNotificationService, do not connect." + " Component name: " + className); return; } - mBoundService = ((DownloadForegroundService.LocalBinder) service).getService(); + mBoundService = ((DownloadForegroundServiceImpl.LocalBinder) service).getService(); DownloadForegroundServiceObservers.addObserver( DownloadNotificationServiceObserver.class); processDownloadUpdateQueue(true /* isProcessingPending */); @@ -307,13 +307,14 @@ checkNotNull(mBoundService); mIsServiceBound = false; - @DownloadForegroundService.StopForegroundNotification + @DownloadForegroundServiceImpl.StopForegroundNotification int stopForegroundNotification; if (downloadStatus == DownloadNotificationService.DownloadStatus.CANCELLED) { - stopForegroundNotification = DownloadForegroundService.StopForegroundNotification.KILL; + stopForegroundNotification = + DownloadForegroundServiceImpl.StopForegroundNotification.KILL; } else { stopForegroundNotification = - DownloadForegroundService.StopForegroundNotification.DETACH; + DownloadForegroundServiceImpl.StopForegroundNotification.DETACH; } DownloadUpdate downloadUpdate = mDownloadUpdateQueue.get(mPinnedNotificationId); @@ -330,7 +331,7 @@ @VisibleForTesting void stopAndUnbindServiceInternal( - @DownloadForegroundService.StopForegroundNotification int stopForegroundStatus, + @DownloadForegroundServiceImpl.StopForegroundNotification int stopForegroundStatus, int pinnedNotificationId, Notification pinnedNotification) { mBoundService.stopDownloadForegroundService( stopForegroundStatus, pinnedNotificationId, pinnedNotification); @@ -343,7 +344,7 @@ /** Helper code for testing. */ @VisibleForTesting - void setBoundService(DownloadForegroundService service) { + void setBoundService(DownloadForegroundServiceImpl service) { mBoundService = service; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ToSAndUMAFirstRunFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ToSAndUMAFirstRunFragment.java index ba7e11a..ba3fc17 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ToSAndUMAFirstRunFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/ToSAndUMAFirstRunFragment.java
@@ -16,11 +16,10 @@ import android.widget.TextView; import androidx.annotation.VisibleForTesting; -import androidx.core.view.ViewCompat; import androidx.fragment.app.Fragment; import org.chromium.chrome.R; -import org.chromium.chrome.browser.ChromeVersionInfo; +import org.chromium.chrome.browser.version.ChromeVersionInfo; import org.chromium.components.signin.ChildAccountStatus; import org.chromium.ui.text.NoUnderlineClickableSpan; import org.chromium.ui.text.SpanApplier; @@ -80,11 +79,6 @@ } }); - int paddingStart = getResources().getDimensionPixelSize(R.dimen.fre_tos_checkbox_padding); - ViewCompat.setPaddingRelative(mSendReportCheckBox, - ViewCompat.getPaddingStart(mSendReportCheckBox) + paddingStart, - mSendReportCheckBox.getPaddingTop(), ViewCompat.getPaddingEnd(mSendReportCheckBox), - mSendReportCheckBox.getPaddingBottom()); mSendReportCheckBox.setChecked(FirstRunActivity.DEFAULT_METRICS_AND_CRASH_REPORTING); if (!canShowUmaCheckBox()) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryDeletionInfo.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryDeletionInfo.java index b71abd1..db99a9a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryDeletionInfo.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryDeletionInfo.java
@@ -45,26 +45,10 @@ return HistoryDeletionInfoJni.get().isTimeRangeForAllTime(mHistoryDeletionInfoPtr); } - /** - * @return The beginning of the time range if the time range is valid. - */ - public long getTimeRangeBegin() { - return HistoryDeletionInfoJni.get().getTimeRangeBegin(mHistoryDeletionInfoPtr); - } - - /** - * @return The end of the time range if the time range is valid. - */ - public long getTimeRangeEnd() { - return HistoryDeletionInfoJni.get().getTimeRangeBegin(mHistoryDeletionInfoPtr); - } - @NativeMethods interface Natives { String[] getDeletedURLs(long historyDeletionInfoPtr); boolean isTimeRangeValid(long historyDeletionInfoPtr); boolean isTimeRangeForAllTime(long historyDeletionInfoPtr); - long getTimeRangeBegin(long historyDeletionInfoPtr); - long getTimeRangeEnd(long historyDeletionInfoPtr); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/identity/UniqueIdentificationGenerator.java b/chrome/android/java/src/org/chromium/chrome/browser/identity/UniqueIdentificationGenerator.java index 35f771f6..3605b959 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/identity/UniqueIdentificationGenerator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/identity/UniqueIdentificationGenerator.java
@@ -4,20 +4,9 @@ package org.chromium.chrome.browser.identity; -import androidx.annotation.Nullable; - /** * Interface used for uniquely identifying an installation of Chrome. To get an instance you should * use {@link UniqueIdentificationGeneratorFactory}. */ -public interface UniqueIdentificationGenerator { - /** - * Creates a string that uniquely identifies this installation. - * <p/> - * If there is an error in generating the string, an empty string must be returned, not null. - * - * @param salt the salt to use for the unique ID. - * @return a unique ID. On failure to generate, it must return the empty string. - */ - String getUniqueId(@Nullable String salt); -} +public interface UniqueIdentificationGenerator + extends org.chromium.chrome.browser.uid.UniqueIdentificationGenerator {}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/identity/UniqueIdentificationGeneratorFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/identity/UniqueIdentificationGeneratorFactory.java index 9780f57..3205138e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/identity/UniqueIdentificationGeneratorFactory.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/identity/UniqueIdentificationGeneratorFactory.java
@@ -4,11 +4,6 @@ package org.chromium.chrome.browser.identity; -import androidx.annotation.VisibleForTesting; - -import java.util.HashMap; -import java.util.Map; - /** * Factory for setting and retrieving instances of {@link UniqueIdentificationGenerator}s. * <p/> @@ -17,27 +12,6 @@ * field in the generator itself. */ public final class UniqueIdentificationGeneratorFactory { - private static final Object LOCK = new Object(); - private static final Map<String, UniqueIdentificationGenerator> GENERATOR_MAP = - new HashMap<String, UniqueIdentificationGenerator>(); - - private UniqueIdentificationGeneratorFactory() { - } - - /** - * Returns a UniqueIdentificationGenerator if it exists, else throws IllegalArgumentException. - * - * @param generatorType the generator type you want - * @return a unique ID generator - */ - public static UniqueIdentificationGenerator getInstance(String generatorType) { - synchronized (LOCK) { - if (!GENERATOR_MAP.containsKey(generatorType)) { - throw new IllegalArgumentException("Unknown generator type " + generatorType); - } - return GENERATOR_MAP.get(generatorType); - } - } /** * During startup of the application, and before any calls to @@ -51,18 +25,8 @@ */ public static void registerGenerator(String generatorType, UniqueIdentificationGenerator gen, boolean force) { - synchronized (LOCK) { - if (GENERATOR_MAP.containsKey(generatorType) && !force) { - return; - } - GENERATOR_MAP.put(generatorType, gen); - } - } - - @VisibleForTesting - public static void clearGeneratorMapForTest() { - synchronized (LOCK) { - GENERATOR_MAP.clear(); - } + // TODO(crbug.com/1131415): remove this file after the downstream is updated. + org.chromium.chrome.browser.uid.UniqueIdentificationGeneratorFactory.registerGenerator( + generatorType, gen, force); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoTabLauncher.java b/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoTabLauncher.java index d0854818..9c5c01f5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoTabLauncher.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoTabLauncher.java
@@ -24,10 +24,10 @@ import org.chromium.base.task.PostTask; import org.chromium.base.task.TaskTraits; import org.chromium.chrome.browser.ChromeApplication; -import org.chromium.chrome.browser.ChromeVersionInfo; import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.customtabs.CustomTabsConnection; import org.chromium.chrome.browser.flags.ChromeFeatureList; +import org.chromium.chrome.browser.version.ChromeVersionInfo; /** * An exposed Activity that allows launching an Incognito Tab.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/AsyncInitTaskRunner.java b/chrome/android/java/src/org/chromium/chrome/browser/init/AsyncInitTaskRunner.java index 1b2f9de..017a891 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/init/AsyncInitTaskRunner.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/init/AsyncInitTaskRunner.java
@@ -15,8 +15,8 @@ import org.chromium.base.task.PostTask; import org.chromium.base.task.TaskTraits; import org.chromium.chrome.browser.ChromeActivitySessionTracker; -import org.chromium.chrome.browser.ChromeVersionInfo; import org.chromium.chrome.browser.flags.CachedFeatureFlags; +import org.chromium.chrome.browser.version.ChromeVersionInfo; import org.chromium.components.variations.firstrun.VariationsSeedFetcher; import org.chromium.content_public.browser.ChildProcessLauncherHelper; import org.chromium.content_public.browser.UiThreadTaskTraits;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java index dc215e92..e0c17ad1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java
@@ -51,8 +51,6 @@ import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.history.HistoryDeletionBridge; import org.chromium.chrome.browser.homepage.HomepageManager; -import org.chromium.chrome.browser.identity.UniqueIdentificationGeneratorFactory; -import org.chromium.chrome.browser.identity.UuidBasedUniqueIdentificationGenerator; import org.chromium.chrome.browser.incognito.IncognitoTabLauncher; import org.chromium.chrome.browser.locale.LocaleManager; import org.chromium.chrome.browser.media.MediaCaptureNotificationService; @@ -75,6 +73,8 @@ import org.chromium.chrome.browser.sharing.shared_clipboard.SharedClipboardShareActivity; import org.chromium.chrome.browser.signin.SigninHelper; import org.chromium.chrome.browser.sync.SyncController; +import org.chromium.chrome.browser.uid.UniqueIdentificationGeneratorFactory; +import org.chromium.chrome.browser.uid.UuidBasedUniqueIdentificationGenerator; import org.chromium.chrome.browser.webapps.WebApkVersionManager; import org.chromium.chrome.browser.webapps.WebappRegistry; import org.chromium.components.background_task_scheduler.BackgroundTaskSchedulerFactory; @@ -83,6 +83,7 @@ import org.chromium.components.browser_ui.photo_picker.PhotoPickerDialog; import org.chromium.components.browser_ui.share.ShareImageFileUtils; import org.chromium.components.browser_ui.util.ConversionUtils; +import org.chromium.components.content_capture.ContentCaptureController; import org.chromium.components.minidump_uploader.CrashFileManager; import org.chromium.components.signin.AccountManagerFacadeImpl; import org.chromium.components.signin.AccountManagerFacadeProvider; @@ -259,8 +260,8 @@ }); SearchWidgetProvider.initialize(); - HistoryDeletionBridge.getInstance().addObserver( - new ContentCaptureHistoryDeletionObserver()); + HistoryDeletionBridge.getInstance().addObserver(new ContentCaptureHistoryDeletionObserver( + () -> ContentCaptureController.getInstance())); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationJobService.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationJobService.java index 62110db..190d6ee 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationJobService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationJobService.java
@@ -1,96 +1,14 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. +// 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. package org.chromium.chrome.browser.notifications; -import android.annotation.TargetApi; -import android.app.job.JobParameters; -import android.app.job.JobService; -import android.content.Intent; -import android.os.Build; -import android.os.Bundle; -import android.os.PersistableBundle; -import android.os.SystemClock; +import org.chromium.chrome.browser.base.SplitCompatJobService; -import org.chromium.base.ThreadUtils; - -/** - * Processes jobs scheduled when user actions are issued on web notifications. - * We use this instead of starting the NotificationService on N+. - */ -@TargetApi(Build.VERSION_CODES.N) -public class NotificationJobService extends JobService { - static PersistableBundle getJobExtrasFromIntent(Intent intent) { - PersistableBundle bundle = new PersistableBundle(); - bundle.putString(NotificationConstants.EXTRA_NOTIFICATION_ID, - intent.getStringExtra(NotificationConstants.EXTRA_NOTIFICATION_ID)); - bundle.putInt(NotificationConstants.EXTRA_NOTIFICATION_TYPE, - intent.getIntExtra(NotificationConstants.EXTRA_NOTIFICATION_TYPE, - NotificationType.WEB_PERSISTENT)); - bundle.putString(NotificationConstants.EXTRA_NOTIFICATION_INFO_ORIGIN, - intent.getStringExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_ORIGIN)); - bundle.putString(NotificationConstants.EXTRA_NOTIFICATION_INFO_SCOPE, - intent.getStringExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_SCOPE)); - bundle.putString(NotificationConstants.EXTRA_NOTIFICATION_INFO_PROFILE_ID, - intent.getStringExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_PROFILE_ID)); - bundle.putBoolean(NotificationConstants.EXTRA_NOTIFICATION_INFO_PROFILE_INCOGNITO, - intent.getBooleanExtra( - NotificationConstants.EXTRA_NOTIFICATION_INFO_PROFILE_INCOGNITO, false)); - bundle.putInt(NotificationConstants.EXTRA_NOTIFICATION_INFO_ACTION_INDEX, - intent.getIntExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_ACTION_INDEX, -1)); - bundle.putString(NotificationConstants.EXTRA_NOTIFICATION_INFO_WEBAPK_PACKAGE, - intent.getStringExtra( - NotificationConstants.EXTRA_NOTIFICATION_INFO_WEBAPK_PACKAGE)); - bundle.putString(NotificationConstants.EXTRA_NOTIFICATION_ACTION, intent.getAction()); - // Only primitives can be set on a persistable bundle, so extract the raw reply. - bundle.putString(NotificationConstants.EXTRA_NOTIFICATION_REPLY, - NotificationPlatformBridge.getNotificationReply(intent)); - return bundle; - } - - /** - * Called when a Notification has been interacted with by the user. If we can verify that - * the Intent has a notification Id, start Chrome (if needed) on the UI thread. - * - * We get a wakelock for our process for the duration of this method. - * - * @return True if there is more work to be done to handle the job, to signal we would like our - * wakelock extended until we call {@link #jobFinished}. False if we have finished handling the - * job. - */ - @Override - public boolean onStartJob(final JobParameters params) { - PersistableBundle extras = params.getExtras(); - putJobStartedTimeInExtras(extras); - if (!extras.containsKey(NotificationConstants.EXTRA_NOTIFICATION_ID) - || !extras.containsKey(NotificationConstants.EXTRA_NOTIFICATION_INFO_ORIGIN)) { - return false; - } - - Intent intent = - new Intent(extras.getString(NotificationConstants.EXTRA_NOTIFICATION_ACTION)); - intent.putExtras(new Bundle(extras)); - - ThreadUtils.assertOnUiThread(); - NotificationService.dispatchIntentOnUIThread(intent); - - // TODO(crbug.com/685197): Return true here and call jobFinished to release the wake - // lock only after the event has been completely handled by the service worker. - return false; - } - - private static void putJobStartedTimeInExtras(PersistableBundle extras) { - extras.putLong( - NotificationConstants.EXTRA_JOB_STARTED_TIME_MS, SystemClock.elapsedRealtime()); - } - - @Override - public boolean onStopJob(JobParameters params) { - // As it stands, all our job processing is done synchronously in onStartJob so there is - // nothing to do here. Even once we include further async processing in our jobs - // (crbug.com/685197) it may by infeasible to cancel this halfway through. - // TODO(crbug.com/685197): Check what we can safely do here and update comment. - return false; +/** See {@link NotificationJobServiceImpl}. */ +public class NotificationJobService extends SplitCompatJobService { + public NotificationJobService() { + super("org.chromium.chrome.browser.notifications.NotificationJobServiceImpl"); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationJobServiceImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationJobServiceImpl.java new file mode 100644 index 0000000..39d5054 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationJobServiceImpl.java
@@ -0,0 +1,100 @@ +// Copyright 2017 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. + +package org.chromium.chrome.browser.notifications; + +import android.annotation.TargetApi; +import android.app.job.JobParameters; +import android.content.Intent; +import android.os.Build; +import android.os.Bundle; +import android.os.PersistableBundle; +import android.os.SystemClock; + +import org.chromium.base.ThreadUtils; +import org.chromium.base.annotations.UsedByReflection; + +/** + * Processes jobs scheduled when user actions are issued on web notifications. + * We use this instead of starting the NotificationService on N+. + */ +@UsedByReflection("NotificationService.java") +@TargetApi(Build.VERSION_CODES.N) +public class NotificationJobServiceImpl extends NotificationJobService.Impl { + @UsedByReflection("NotificationService.java") + public NotificationJobServiceImpl() {} + + static PersistableBundle getJobExtrasFromIntent(Intent intent) { + PersistableBundle bundle = new PersistableBundle(); + bundle.putString(NotificationConstants.EXTRA_NOTIFICATION_ID, + intent.getStringExtra(NotificationConstants.EXTRA_NOTIFICATION_ID)); + bundle.putInt(NotificationConstants.EXTRA_NOTIFICATION_TYPE, + intent.getIntExtra(NotificationConstants.EXTRA_NOTIFICATION_TYPE, + NotificationType.WEB_PERSISTENT)); + bundle.putString(NotificationConstants.EXTRA_NOTIFICATION_INFO_ORIGIN, + intent.getStringExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_ORIGIN)); + bundle.putString(NotificationConstants.EXTRA_NOTIFICATION_INFO_SCOPE, + intent.getStringExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_SCOPE)); + bundle.putString(NotificationConstants.EXTRA_NOTIFICATION_INFO_PROFILE_ID, + intent.getStringExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_PROFILE_ID)); + bundle.putBoolean(NotificationConstants.EXTRA_NOTIFICATION_INFO_PROFILE_INCOGNITO, + intent.getBooleanExtra( + NotificationConstants.EXTRA_NOTIFICATION_INFO_PROFILE_INCOGNITO, false)); + bundle.putInt(NotificationConstants.EXTRA_NOTIFICATION_INFO_ACTION_INDEX, + intent.getIntExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_ACTION_INDEX, -1)); + bundle.putString(NotificationConstants.EXTRA_NOTIFICATION_INFO_WEBAPK_PACKAGE, + intent.getStringExtra( + NotificationConstants.EXTRA_NOTIFICATION_INFO_WEBAPK_PACKAGE)); + bundle.putString(NotificationConstants.EXTRA_NOTIFICATION_ACTION, intent.getAction()); + // Only primitives can be set on a persistable bundle, so extract the raw reply. + bundle.putString(NotificationConstants.EXTRA_NOTIFICATION_REPLY, + NotificationPlatformBridge.getNotificationReply(intent)); + return bundle; + } + + /** + * Called when a Notification has been interacted with by the user. If we can verify that + * the Intent has a notification Id, start Chrome (if needed) on the UI thread. + * + * We get a wakelock for our process for the duration of this method. + * + * @return True if there is more work to be done to handle the job, to signal we would like our + * wakelock extended until we call {@link #jobFinished}. False if we have finished handling the + * job. + */ + @Override + public boolean onStartJob(final JobParameters params) { + PersistableBundle extras = params.getExtras(); + putJobStartedTimeInExtras(extras); + if (!extras.containsKey(NotificationConstants.EXTRA_NOTIFICATION_ID) + || !extras.containsKey(NotificationConstants.EXTRA_NOTIFICATION_INFO_ORIGIN)) { + return false; + } + + Intent intent = + new Intent(extras.getString(NotificationConstants.EXTRA_NOTIFICATION_ACTION)); + intent.putExtras(new Bundle(extras)); + + ThreadUtils.assertOnUiThread(); + NotificationServiceImpl.dispatchIntentOnUIThread(intent); + + // TODO(crbug.com/685197): Return true here and call jobFinished to release the wake + // lock only after the event has been completely handled by the service worker. + return false; + } + + private static void putJobStartedTimeInExtras(PersistableBundle extras) { + extras.putLong( + NotificationConstants.EXTRA_JOB_STARTED_TIME_MS, SystemClock.elapsedRealtime()); + } + + @Override + public boolean onStopJob(JobParameters params) { + // As it stands, all our job processing is done synchronously in onStartJob so there is + // nothing to do here. Even once we include further async processing in our jobs + // (crbug.com/685197) it may by infeasible to cancel this halfway through. + // TODO(crbug.com/685197): Check what we can safely do here and update comment. + return false; + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java index cf9d0ae..ede170ca 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java
@@ -327,7 +327,7 @@ int actionIndex) { Uri intentData = makeIntentData(notificationId, origin, actionIndex); Intent intent = new Intent(action, intentData); - intent.setClass(context, NotificationService.Receiver.class); + intent.setClass(context, NotificationServiceImpl.Receiver.class); // Make sure to update NotificationJobService.getJobExtrasFromIntent() when changing any // of the extras included with the |intent|.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationService.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationService.java index c72c141..ff173b64 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationService.java
@@ -1,119 +1,34 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. +// 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. package org.chromium.chrome.browser.notifications; -import android.annotation.TargetApi; -import android.app.IntentService; -import android.app.job.JobInfo; -import android.app.job.JobScheduler; import android.content.BroadcastReceiver; -import android.content.ComponentName; import android.content.Context; import android.content.Intent; -import android.os.Build; -import android.os.PersistableBundle; -import android.os.SystemClock; -import android.util.Log; -import org.chromium.base.task.PostTask; -import org.chromium.chrome.browser.init.ChromeBrowserInitializer; -import org.chromium.chrome.browser.webapps.WebappRegistry; -import org.chromium.components.background_task_scheduler.TaskIds; -import org.chromium.content_public.browser.UiThreadTaskTraits; +import org.chromium.chrome.browser.base.SplitCompatIntentService; +import org.chromium.chrome.browser.base.SplitCompatUtils; -/** - * The Notification service receives intents fired as responses to user actions issued on Android - * notifications displayed in the notification tray. - */ -public class NotificationService extends IntentService { +/** See {@link NotificationServiceImpl}. */ +public class NotificationService extends SplitCompatIntentService { private static final String TAG = NotificationService.class.getSimpleName(); + public NotificationService() { + super("org.chromium.chrome.browser.notifications.NotificationServiceImpl", TAG); + } + /** - * The class which receives the intents from the Android framework. It initializes the - * Notification service, and forward the intents there. Declared public as it needs to be - * initialized by the Android framework. + * This receiver forwards the onReceive() call to the implementation version. This is needed to + * handle pending intents referring to the old receiver name. */ public static class Receiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { - Log.i(TAG, "Received a notification intent in the NotificationService's receiver."); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - // Android encourages us not to start services directly on N+, so instead we - // schedule a job to handle the notification intent. We use the Android JobScheduler - // rather than GcmNetworkManager or FirebaseJobDispatcher since the JobScheduler - // allows us to execute immediately by setting an override deadline of zero - // milliseconds. - JobScheduler scheduler = - (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE); - PersistableBundle extras = NotificationJobService.getJobExtrasFromIntent(intent); - putJobScheduledTimeInExtras(extras); - JobInfo job = - new JobInfo - .Builder(TaskIds.NOTIFICATION_SERVICE_JOB_ID, - new ComponentName(context, NotificationJobService.class)) - .setExtras(extras) - .setOverrideDeadline(0) - .build(); - scheduler.schedule(job); - } else { - // TODO(peter): Do we need to acquire a wake lock here? - - intent.setClass(context, NotificationService.class); - context.startService(intent); - } + BroadcastReceiver receiver = (BroadcastReceiver) SplitCompatUtils.newInstance(context, + "org.chromium.chrome.browser.notifications.NotificationServiceImpl$Receiver"); + receiver.onReceive(context, intent); } - - @TargetApi(Build.VERSION_CODES.N) - private static void putJobScheduledTimeInExtras(PersistableBundle extras) { - extras.putLong(NotificationConstants.EXTRA_JOB_SCHEDULED_TIME_MS, - SystemClock.elapsedRealtime()); - } - } - - public NotificationService() { - super(TAG); - } - - /** - * Called when a Notification has been interacted with by the user. If we can verify that - * the Intent has a notification Id, start Chrome (if needed) on the UI thread. - * - * @param intent The intent containing the specific information. - */ - @Override - public void onHandleIntent(final Intent intent) { - if (!intent.hasExtra(NotificationConstants.EXTRA_NOTIFICATION_ID) - || !intent.hasExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_ORIGIN)) { - return; - } - - PostTask.runOrPostTask( - UiThreadTaskTraits.DEFAULT, () -> { dispatchIntentOnUIThread(intent); }); - } - - /** - * Initializes Chrome and starts the browser process if it's not running as of yet, and - * dispatch |intent| to the NotificationPlatformBridge once this is done. - * - * @param intent The intent containing the notification's information. - */ - static void dispatchIntentOnUIThread(Intent intent) { - ChromeBrowserInitializer.getInstance().handleSynchronousStartup(); - - // Warm up the WebappRegistry, as we need to check if this notification should launch a - // standalone web app. This no-ops if the registry is already initialized and warmed. - WebappRegistry.getInstance(); - WebappRegistry.warmUpSharedPrefs(); - - // Now that the browser process is initialized, we pass forward the call to the - // NotificationPlatformBridge which will take care of delivering the appropriate events. - if (!NotificationPlatformBridge.dispatchNotificationEvent(intent)) { - Log.w(TAG, "Unable to dispatch the notification event to Chrome."); - } - - // TODO(peter): Verify that the lifetime of the NotificationService is sufficient - // when a notification event could be dispatched successfully. } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationServiceImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationServiceImpl.java new file mode 100644 index 0000000..8b044b5 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationServiceImpl.java
@@ -0,0 +1,120 @@ +// Copyright 2014 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. + +package org.chromium.chrome.browser.notifications; + +import android.annotation.TargetApi; +import android.app.job.JobInfo; +import android.app.job.JobScheduler; +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.os.Build; +import android.os.PersistableBundle; +import android.os.SystemClock; +import android.util.Log; + +import org.chromium.base.annotations.UsedByReflection; +import org.chromium.base.task.PostTask; +import org.chromium.chrome.browser.init.ChromeBrowserInitializer; +import org.chromium.chrome.browser.webapps.WebappRegistry; +import org.chromium.components.background_task_scheduler.TaskIds; +import org.chromium.content_public.browser.UiThreadTaskTraits; + +/** + * The Notification service receives intents fired as responses to user actions issued on Android + * notifications displayed in the notification tray. + */ +@UsedByReflection("NotificationService.java") +public class NotificationServiceImpl extends NotificationService.Impl { + private static final String TAG = NotificationServiceImpl.class.getSimpleName(); + + /** + * The class which receives the intents from the Android framework. It initializes the + * Notification service, and forward the intents there. Declared public as it needs to be + * initialized by the Android framework. + */ + public static class Receiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + Log.i(TAG, "Received a notification intent in the NotificationService's receiver."); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + // Android encourages us not to start services directly on N+, so instead we + // schedule a job to handle the notification intent. We use the Android JobScheduler + // rather than GcmNetworkManager or FirebaseJobDispatcher since the JobScheduler + // allows us to execute immediately by setting an override deadline of zero + // milliseconds. + JobScheduler scheduler = + (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE); + PersistableBundle extras = + NotificationJobServiceImpl.getJobExtrasFromIntent(intent); + putJobScheduledTimeInExtras(extras); + JobInfo job = + new JobInfo + .Builder(TaskIds.NOTIFICATION_SERVICE_JOB_ID, + new ComponentName(context, NotificationJobService.class)) + .setExtras(extras) + .setOverrideDeadline(0) + .build(); + scheduler.schedule(job); + } else { + // TODO(peter): Do we need to acquire a wake lock here? + + intent.setClass(context, NotificationService.class); + context.startService(intent); + } + } + + @TargetApi(Build.VERSION_CODES.N) + private static void putJobScheduledTimeInExtras(PersistableBundle extras) { + extras.putLong(NotificationConstants.EXTRA_JOB_SCHEDULED_TIME_MS, + SystemClock.elapsedRealtime()); + } + } + + @UsedByReflection("NotificationService.java") + public NotificationServiceImpl() {} + + /** + * Called when a Notification has been interacted with by the user. If we can verify that + * the Intent has a notification Id, start Chrome (if needed) on the UI thread. + * + * @param intent The intent containing the specific information. + */ + @Override + public void onHandleIntent(final Intent intent) { + if (!intent.hasExtra(NotificationConstants.EXTRA_NOTIFICATION_ID) + || !intent.hasExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_ORIGIN)) { + return; + } + + PostTask.runOrPostTask( + UiThreadTaskTraits.DEFAULT, () -> { dispatchIntentOnUIThread(intent); }); + } + + /** + * Initializes Chrome and starts the browser process if it's not running as of yet, and + * dispatch |intent| to the NotificationPlatformBridge once this is done. + * + * @param intent The intent containing the notification's information. + */ + static void dispatchIntentOnUIThread(Intent intent) { + ChromeBrowserInitializer.getInstance().handleSynchronousStartup(); + + // Warm up the WebappRegistry, as we need to check if this notification should launch a + // standalone web app. This no-ops if the registry is already initialized and warmed. + WebappRegistry.getInstance(); + WebappRegistry.warmUpSharedPrefs(); + + // Now that the browser process is initialized, we pass forward the call to the + // NotificationPlatformBridge which will take care of delivering the appropriate events. + if (!NotificationPlatformBridge.dispatchNotificationEvent(intent)) { + Log.w(TAG, "Unable to dispatch the notification event to Chrome."); + } + + // TODO(peter): Verify that the lifetime of the NotificationService is sufficient + // when a notification event could be dispatched successfully. + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineDetector.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineDetector.java index d28e028..8b534480 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineDetector.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineDetector.java
@@ -15,9 +15,9 @@ import org.chromium.base.Callback; import org.chromium.base.Log; import org.chromium.base.supplier.Supplier; -import org.chromium.chrome.browser.ChromeVersionInfo; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.offlinepages.indicator.ConnectivityDetector.ConnectionState; +import org.chromium.chrome.browser.version.ChromeVersionInfo; import org.chromium.components.variations.VariationsAssociatedData; /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omaha/OmahaBase.java b/chrome/android/java/src/org/chromium/chrome/browser/omaha/OmahaBase.java index 92879e7b..41610a2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omaha/OmahaBase.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omaha/OmahaBase.java
@@ -18,7 +18,7 @@ import org.chromium.base.Log; import org.chromium.base.StreamUtil; import org.chromium.base.ThreadUtils; -import org.chromium.chrome.browser.ChromeVersionInfo; +import org.chromium.chrome.browser.version.ChromeVersionInfo; import java.io.BufferedOutputStream; import java.io.BufferedReader;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omaha/RequestGenerator.java b/chrome/android/java/src/org/chromium/chrome/browser/omaha/RequestGenerator.java index 3c7e92696..b135fdf 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omaha/RequestGenerator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omaha/RequestGenerator.java
@@ -14,8 +14,8 @@ import org.xmlpull.v1.XmlSerializer; import org.chromium.base.BuildInfo; -import org.chromium.chrome.browser.identity.SettingsSecureBasedIdentificationGenerator; -import org.chromium.chrome.browser.identity.UniqueIdentificationGeneratorFactory; +import org.chromium.chrome.browser.uid.SettingsSecureBasedIdentificationGenerator; +import org.chromium.chrome.browser.uid.UniqueIdentificationGeneratorFactory; import org.chromium.ui.base.DeviceFormFactor; import java.io.IOException;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksShim.java b/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksShim.java index 819eaf3..375443c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksShim.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksShim.java
@@ -7,8 +7,8 @@ import android.content.Context; import android.content.pm.ApplicationInfo; -import org.chromium.chrome.browser.ChromeVersionInfo; import org.chromium.chrome.browser.partnercustomizations.PartnerBrowserCustomizations; +import org.chromium.chrome.browser.version.ChromeVersionInfo; /** * The Java counterpart for the C++ partner bookmarks shim.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java b/chrome/android/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java index 088531d..cb15407b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java
@@ -21,9 +21,9 @@ import org.chromium.base.task.AsyncTask; import org.chromium.base.task.PostTask; import org.chromium.chrome.browser.AppHooks; -import org.chromium.chrome.browser.ChromeVersionInfo; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.ntp.NewTabPage; +import org.chromium.chrome.browser.version.ChromeVersionInfo; import org.chromium.components.embedder_support.util.UrlConstants; import org.chromium.components.embedder_support.util.UrlUtilities; import org.chromium.content_public.browser.UiThreadTaskTraits;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/PaymentHandlerCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/PaymentHandlerCoordinator.java index be4cd7a..c8417d5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/PaymentHandlerCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/PaymentHandlerCoordinator.java
@@ -6,10 +6,10 @@ import androidx.annotation.VisibleForTesting; -import org.chromium.chrome.browser.ChromeVersionInfo; import org.chromium.chrome.browser.WebContentsFactory; import org.chromium.chrome.browser.app.ChromeActivity; import org.chromium.chrome.browser.payments.handler.toolbar.PaymentHandlerToolbarCoordinator; +import org.chromium.chrome.browser.version.ChromeVersionInfo; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.browser_ui.bottomsheet.BottomSheetControllerProvider; import org.chromium.components.embedder_support.view.ContentView;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java index dcabb36..d42de57 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java
@@ -37,7 +37,6 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.Callback; import org.chromium.chrome.R; -import org.chromium.chrome.browser.ChromeVersionInfo; import org.chromium.chrome.browser.autofill.prefeditor.EditorDialog; import org.chromium.chrome.browser.autofill.prefeditor.EditorObserverForTest; import org.chromium.chrome.browser.lifecycle.PauseResumeWithNativeObserver; @@ -48,6 +47,7 @@ import org.chromium.chrome.browser.payments.ui.PaymentUIsManager.PaymentUisShowStateReconciler; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.signin.IdentityServicesProvider; +import org.chromium.chrome.browser.version.ChromeVersionInfo; import org.chromium.components.autofill.EditableOption; import org.chromium.components.browser_ui.widget.FadingEdgeScrollView; import org.chromium.components.browser_ui.widget.animation.FocusAnimator;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/prerender/ChromePrerenderService.java b/chrome/android/java/src/org/chromium/chrome/browser/prerender/ChromePrerenderService.java index a2aed4ca..98fda62 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/prerender/ChromePrerenderService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/prerender/ChromePrerenderService.java
@@ -12,9 +12,9 @@ import android.os.Messenger; import org.chromium.chrome.browser.AppHooks; -import org.chromium.chrome.browser.ChromeVersionInfo; import org.chromium.chrome.browser.externalauth.ExternalAuthUtils; import org.chromium.chrome.browser.externalauth.VerifiedHandler; +import org.chromium.chrome.browser.version.ChromeVersionInfo; /** * A bound service that does nothing. Kept here to prevent old clients relying on it being
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/rlz/RlzPingHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/rlz/RlzPingHandler.java index f79e64fc..f686bdb0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/rlz/RlzPingHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/rlz/RlzPingHandler.java
@@ -10,8 +10,8 @@ import org.chromium.base.ContextUtils; import org.chromium.base.annotations.JNINamespace; import org.chromium.base.annotations.NativeMethods; -import org.chromium.chrome.browser.identity.SettingsSecureBasedIdentificationGenerator; import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.uid.SettingsSecureBasedIdentificationGenerator; import java.util.List; import java.util.Locale;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceNotification.java b/chrome/android/java/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceNotification.java index 03e6401..fe6e6b9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceNotification.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceNotification.java
@@ -9,7 +9,6 @@ import androidx.annotation.Nullable; import org.chromium.chrome.R; -import org.chromium.chrome.browser.ChromeVersionInfo; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.omaha.VersionNumber; import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; @@ -20,6 +19,7 @@ import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar; import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager.SnackbarController; +import org.chromium.chrome.browser.version.ChromeVersionInfo; import java.util.concurrent.TimeUnit;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninPromoUtil.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninPromoUtil.java index 8602a9c..348fe787 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninPromoUtil.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninPromoUtil.java
@@ -14,9 +14,9 @@ import org.chromium.base.annotations.CalledByNative; import org.chromium.chrome.R; -import org.chromium.chrome.browser.ChromeVersionInfo; import org.chromium.chrome.browser.preferences.Pref; import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.version.ChromeVersionInfo; import org.chromium.components.signin.AccountManagerFacadeProvider; import org.chromium.components.signin.AccountUtils; import org.chromium.components.signin.base.CoreAccountInfo;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/site_settings/ManageSpaceActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/site_settings/ManageSpaceActivity.java index a847b2e..9f875f7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/site_settings/ManageSpaceActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/site_settings/ManageSpaceActivity.java
@@ -28,7 +28,6 @@ import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordUserAction; import org.chromium.chrome.R; -import org.chromium.chrome.browser.ChromeVersionInfo; import org.chromium.chrome.browser.about_settings.AboutChromeSettings; import org.chromium.chrome.browser.init.BrowserParts; import org.chromium.chrome.browser.init.ChromeBrowserInitializer; @@ -40,6 +39,7 @@ import org.chromium.chrome.browser.searchwidget.SearchWidgetProvider; import org.chromium.chrome.browser.settings.SettingsLauncher; import org.chromium.chrome.browser.settings.SettingsLauncherImpl; +import org.chromium.chrome.browser.version.ChromeVersionInfo; import org.chromium.components.browser_ui.site_settings.AllSiteSettings; import org.chromium.components.browser_ui.site_settings.SingleCategorySettings; import org.chromium.components.browser_ui.site_settings.SiteSettingsCategory;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/survey/ChromeSurveyController.java b/chrome/android/java/src/org/chromium/chrome/browser/survey/ChromeSurveyController.java index ecf89e6..b98aede 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/survey/ChromeSurveyController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/survey/ChromeSurveyController.java
@@ -18,7 +18,6 @@ import org.chromium.base.metrics.RecordUserAction; import org.chromium.base.task.AsyncTask; import org.chromium.chrome.R; -import org.chromium.chrome.browser.ChromeVersionInfo; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.infobar.InfoBarContainer; @@ -35,6 +34,7 @@ import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver; import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver; +import org.chromium.chrome.browser.version.ChromeVersionInfo; import org.chromium.components.infobars.InfoBarAnimationListener; import org.chromium.components.infobars.InfoBarUiItem; import org.chromium.components.variations.VariationsAssociatedData;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncController.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncController.java index 27c9182..f0cc5985 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncController.java
@@ -12,11 +12,11 @@ import org.chromium.base.Log; import org.chromium.base.ThreadUtils; import org.chromium.base.metrics.RecordHistogram; -import org.chromium.chrome.browser.identity.UniqueIdentificationGenerator; -import org.chromium.chrome.browser.identity.UniqueIdentificationGeneratorFactory; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.signin.IdentityServicesProvider; import org.chromium.chrome.browser.signin.SigninManager; +import org.chromium.chrome.browser.uid.UniqueIdentificationGenerator; +import org.chromium.chrome.browser.uid.UniqueIdentificationGeneratorFactory; import org.chromium.components.sync.ModelType; import org.chromium.components.sync.PassphraseType; import org.chromium.components.sync.StopSource;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/DEPS b/chrome/android/java/src/org/chromium/chrome/browser/tab/DEPS index bf259e7..7f0f324 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/DEPS +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/DEPS
@@ -25,6 +25,7 @@ "+chrome/browser/preferences", "+chrome/browser/tab", "+chrome/browser/ui/android/native_page", + "+chrome/browser/version", "+components/browser_ui/styles/android", "+components/browser_ui/widget/android", "+content/public/android/java/src/org/chromium/content_public", @@ -47,7 +48,6 @@ 'TabImpl\.java': [ "+chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrModuleProvider.java", "+chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java", - "+chrome/android/java/src/org/chromium/chrome/browser/ChromeVersionInfo.java", "+chrome/android/java/src/org/chromium/chrome/browser/WarmupManager.java", "+chrome/android/java/src/org/chromium/chrome/browser/WebContentsFactory.java", "+chrome/android/java/src/org/chromium/chrome/browser/content/ContentUtils.java", @@ -70,9 +70,6 @@ "+ui/android/java/src/org/chromium/ui/base", "+ui/android/java/src/org/chromium/ui/mojom", ], - 'TabStateFileManager\.java': [ - "+chrome/android/java/src/org/chromium/chrome/browser/ChromeVersionInfo.java", - ], 'TabStateBrowserControlsVisibilityDelegate\.java': [ "+chrome/browser/util/android/java/src/org/chromium/chrome/browser/util/ChromeAccessibilityUtil.java", ],
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java index 68b45557..cdbbb8af 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java
@@ -25,7 +25,6 @@ import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.NativeMethods; import org.chromium.chrome.R; -import org.chromium.chrome.browser.ChromeVersionInfo; import org.chromium.chrome.browser.WarmupManager; import org.chromium.chrome.browser.WebContentsFactory; import org.chromium.chrome.browser.app.ChromeActivity; @@ -42,6 +41,7 @@ import org.chromium.chrome.browser.ui.TabObscuringHandler; import org.chromium.chrome.browser.ui.native_page.FrozenNativePage; import org.chromium.chrome.browser.ui.native_page.NativePage; +import org.chromium.chrome.browser.version.ChromeVersionInfo; import org.chromium.chrome.browser.vr.VrModuleProvider; import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils; import org.chromium.components.embedder_support.util.UrlConstants;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabStateFileManager.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabStateFileManager.java index 6341e7db..9e24bfc 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabStateFileManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabStateFileManager.java
@@ -10,8 +10,8 @@ import org.chromium.base.Log; import org.chromium.base.StreamUtil; -import org.chromium.chrome.browser.ChromeVersionInfo; import org.chromium.chrome.browser.crypto.CipherFactory; +import org.chromium.chrome.browser.version.ChromeVersionInfo; import java.io.BufferedOutputStream; import java.io.DataInputStream;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tasks/JourneyManager.java b/chrome/android/java/src/org/chromium/chrome/browser/tasks/JourneyManager.java index 7ce51f370..05eec56 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tasks/JourneyManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tasks/JourneyManager.java
@@ -14,7 +14,6 @@ import org.chromium.base.ContextUtils; import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.task.AsyncTask; -import org.chromium.chrome.browser.ChromeVersionInfo; import org.chromium.chrome.browser.compositor.layouts.EmptyOverviewModeObserver; import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior; import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher; @@ -27,6 +26,7 @@ import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabModelObserver; import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabObserver; +import org.chromium.chrome.browser.version.ChromeVersionInfo; import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.browser.NavigationHandle; import org.chromium.ui.base.PageTransition;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java index 6c423a5..eacaabd0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -322,6 +322,7 @@ mToolbar = createTopToolbarCoordinator(controlContainer, toolbarLayout, buttonDataProviders, browsingModeThemeColorProvider, startSurfaceMenuButtonCoordinator, invalidator, identityDiscController); + mActionModeController = new ActionModeController(mActivity, mActionBarDelegate, toolbarActionModeCallback); @@ -731,7 +732,8 @@ mToolbar.initializeWithNative(layoutManager::requestUpdate, tabSwitcherClickHandler, tabSwitcherLongClickHandler, newTabClickHandler, bookmarkClickHandler, - customTabsBackClickHandler); + customTabsBackClickHandler, layoutManager, mActivityTabProvider, + mBrowserControlsSizer); mToolbar.addOnAttachStateChangeListener(new OnAttachStateChangeListener() { @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarLayout.java index 8ada087..9d61264 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarLayout.java
@@ -28,6 +28,8 @@ import org.chromium.base.TraceEvent; import org.chromium.chrome.R; import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior; +import org.chromium.chrome.browser.compositor.overlays.toolbar.TopToolbarOverlayCoordinator; +import org.chromium.chrome.browser.findinpage.FindToolbar; import org.chromium.chrome.browser.ntp.NewTabPage; import org.chromium.chrome.browser.omnibox.LocationBar; import org.chromium.chrome.browser.omnibox.UrlBarData; @@ -83,6 +85,8 @@ private MenuButtonCoordinator mMenuButtonCoordinator; private AppMenuButtonHelper mAppMenuButtonHelper; + private TopToolbarOverlayCoordinator mOverlayCoordinator; + /** * Basic constructor for {@link ToolbarLayout}. */ @@ -119,6 +123,20 @@ mMenuButtonCoordinator = menuButtonCoordinator; } + /** @param overlay The coordinator for the texture version of the top toolbar. */ + void setOverlayCoordinator(TopToolbarOverlayCoordinator overlay) { + mOverlayCoordinator = overlay; + mOverlayCoordinator.setIsAndroidViewVisible(getVisibility() == View.VISIBLE); + } + + @Override + public void setVisibility(int visibility) { + super.setVisibility(visibility); + if (mOverlayCoordinator != null) { + mOverlayCoordinator.setIsAndroidViewVisible(visibility == View.VISIBLE); + } + } + /** * @param appMenuButtonHelper The helper for managing menu button interactions. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarCoordinator.java index ced8a04..ed9a5b8e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarCoordinator.java
@@ -20,7 +20,14 @@ import org.chromium.base.supplier.OneshotSupplier; import org.chromium.base.supplier.Supplier; import org.chromium.chrome.R; +import org.chromium.chrome.browser.ActivityTabProvider; +import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider; +import org.chromium.chrome.browser.compositor.Invalidator; +import org.chromium.chrome.browser.compositor.layouts.LayoutManager; import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior; +import org.chromium.chrome.browser.compositor.overlays.toolbar.TopToolbarOverlayCoordinator; +import org.chromium.chrome.browser.device.DeviceClassManager; +import org.chromium.chrome.browser.findinpage.FindToolbar; import org.chromium.chrome.browser.omnibox.LocationBar; import org.chromium.chrome.browser.tabmodel.IncognitoStateProvider; import org.chromium.chrome.browser.tabmodel.TabModelSelector; @@ -36,6 +43,7 @@ import org.chromium.chrome.browser.ui.appmenu.AppMenuButtonHelper; import org.chromium.chrome.browser.user_education.UserEducationHelper; import org.chromium.chrome.features.start_surface.StartSurfaceConfiguration; +import org.chromium.components.browser_ui.widget.ClipDrawableProgressBar; import java.util.List; @@ -79,6 +87,9 @@ private ObservableSupplier<AppMenuButtonHelper> mAppMenuButtonHelperSupplier; private CallbackController mCallbackController = new CallbackController(); private ObservableSupplier<TabModelSelector> mTabModelSelectorSupplier; + private TopToolbarOverlayCoordinator mOverlayCoordinator; + + private Callback<ClipDrawableProgressBar.DrawingInfo> mProgressDrawInfoCallback; /** * Creates a new {@link TopToolbarCoordinator}. @@ -118,6 +129,10 @@ mMenuButtonCoordinator = browsingModeMenuButtonCoordinator; mOptionalButtonController = new OptionalBrowsingModeButtonController(buttonDataProviders, userEducationHelper, mToolbarLayout, () -> toolbarDataProvider.getTab()); + mProgressDrawInfoCallback = (info) -> { + if (controlContainer == null) return; + controlContainer.getProgressBarDrawingInfo(info); + }; overviewModeBehaviorSupplier.onAvailable( mCallbackController.makeCancelable(this::setOverviewModeBehavior)); @@ -165,11 +180,16 @@ * @param newTabClickHandler The click handler for the new tab button. * @param bookmarkClickHandler The click handler for the bookmarks button. * @param customTabsBackClickHandler The click handler for the custom tabs back button. + * @param layoutManager A means of adding SceneOverlays. + * @param tabProvider A means of accessing the currently active tab. + * @param browserControlsStateProvider Access to the state of the browser controls. */ public void initializeWithNative(Runnable layoutUpdater, OnClickListener tabSwitcherClickHandler, OnLongClickListener tabSwitcherLongClickHandler, OnClickListener newTabClickHandler, - OnClickListener bookmarkClickHandler, OnClickListener customTabsBackClickHandler) { + OnClickListener bookmarkClickHandler, OnClickListener customTabsBackClickHandler, + LayoutManager layoutManager, ActivityTabProvider tabProvider, + BrowserControlsStateProvider browserControlsStateProvider) { assert mTabModelSelectorSupplier.get() != null; if (mTabSwitcherModeCoordinatorPhone != null) { mTabSwitcherModeCoordinatorPhone.setOnTabSwitcherClickHandler(tabSwitcherClickHandler); @@ -194,6 +214,16 @@ mToolbarLayout.setLayoutUpdater(layoutUpdater); mToolbarLayout.onNativeLibraryReady(); + + // If fullscreen is disabled, don't bother creating this overlay; only the android view will + // ever be shown. + if (DeviceClassManager.enableFullscreen()) { + mOverlayCoordinator = + new TopToolbarOverlayCoordinator(mToolbarLayout.getContext(), layoutManager, + mProgressDrawInfoCallback, tabProvider, browserControlsStateProvider); + layoutManager.addSceneOverlay(mOverlayCoordinator); + mToolbarLayout.setOverlayCoordinator(mOverlayCoordinator); + } } private void setOverviewModeBehavior(OverviewModeBehavior overviewModeBehavior) { @@ -226,6 +256,11 @@ * Cleans up any code as necessary. */ public void destroy() { + if (mOverlayCoordinator != null) { + mOverlayCoordinator.destroy(); + mOverlayCoordinator = null; + } + mToolbarLayout.destroy(); if (mTabSwitcherModeCoordinatorPhone != null) { mTabSwitcherModeCoordinatorPhone.destroy();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tracing/settings/DeveloperSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/tracing/settings/DeveloperSettings.java index e07a8f2f..1f9156c7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tracing/settings/DeveloperSettings.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tracing/settings/DeveloperSettings.java
@@ -10,9 +10,9 @@ import androidx.preference.PreferenceFragmentCompat; import org.chromium.chrome.R; -import org.chromium.chrome.browser.ChromeVersionInfo; import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; import org.chromium.chrome.browser.preferences.SharedPreferencesManager; +import org.chromium.chrome.browser.version.ChromeVersionInfo; import org.chromium.components.browser_ui.settings.SettingsUtils; import org.chromium.components.version_info.Channel; import org.chromium.components.version_info.VersionConstants;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/ChromeWebApkHost.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/ChromeWebApkHost.java index efdab39c..064de37 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/ChromeWebApkHost.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/ChromeWebApkHost.java
@@ -12,7 +12,7 @@ import org.chromium.base.ContextUtils; import org.chromium.base.ThreadUtils; import org.chromium.base.task.PostTask; -import org.chromium.chrome.browser.ChromeVersionInfo; +import org.chromium.chrome.browser.version.ChromeVersionInfo; import org.chromium.components.webapk.lib.client.ChromeWebApkHostSignature; import org.chromium.components.webapk.lib.client.WebApkValidator; import org.chromium.content_public.browser.UiThreadTaskTraits;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java index bc1b24f..70183175 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java
@@ -177,7 +177,7 @@ tabContentManagerSupplier.set(tabContentManager); mManager = mManagerPhone; CompositorAnimationHandler.setTestingMode(true); - mManager.init(mTabModelSelector, null, null, null, null, mTabSupplier); + mManager.init(mTabModelSelector, null, null, null, null); initializeMotionEvent(); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityIncognitoTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityIncognitoTest.java index fe026212..72542e8 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityIncognitoTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityIncognitoTest.java
@@ -11,7 +11,6 @@ import static org.chromium.chrome.browser.customtabs.CustomTabsTestUtils.addActionButtonToIntent; import static org.chromium.chrome.browser.customtabs.CustomTabsTestUtils.createTestBitmap; -import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.NotificationManager; import android.app.PendingIntent; @@ -43,6 +42,7 @@ import org.chromium.base.ContextUtils; import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.chrome.R; import org.chromium.chrome.browser.customtabs.CustomTabsTestUtils.OnFinishedForTest; import org.chromium.chrome.browser.customtabs.features.toolbar.CustomTabToolbar; @@ -197,7 +197,7 @@ @MediumTest @Features.EnableFeatures({ChromeFeatureList.CCT_INCOGNITO}) @TargetApi(Build.VERSION_CODES.M) - @SuppressLint("NewApi") + @MinAndroidSdkLevel(Build.VERSION_CODES.M) public void closeAllIncognitoNotificationIsNotDisplayed() throws Exception { // It may happen that some previous incognito notification from tabbed activity may be // already be lying around. So, we test the delta instead to be 0.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/OWNERS b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/OWNERS index 8c01572..a73e0828 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/OWNERS +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/OWNERS
@@ -1 +1,2 @@ file://chrome/android/java/src/org/chromium/chrome/browser/customtabs/OWNERS +per-file *CustomTabActivityIncognitoTest*=roagarwal@chromium.org
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadForegroundServiceManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadForegroundServiceManagerTest.java index f3ac086c..0f2880e6 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadForegroundServiceManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadForegroundServiceManagerTest.java
@@ -72,7 +72,7 @@ } @Override - void stopAndUnbindServiceInternal(@DownloadForegroundService.StopForegroundNotification + void stopAndUnbindServiceInternal(@DownloadForegroundServiceImpl.StopForegroundNotification int stopForegroundNotification, int pinnedNotificationId, Notification pinnedNotification) { mStopForegroundNotificationFlag = stopForegroundNotification; @@ -102,7 +102,7 @@ * Implementation of DownloadForegroundService for testing. * Does not implement startOrUpdateForegroundService to avoid test service lifecycle. */ - public static class MockDownloadForegroundService extends DownloadForegroundService { + public static class MockDownloadForegroundService extends DownloadForegroundServiceImpl { @Override public void startOrUpdateForegroundService(int newNotificationId, Notification newNotification, int oldNotificationId, Notification oldNotification, @@ -231,7 +231,7 @@ mDownloadServiceManager.updateDownloadStatus(mContext, DownloadNotificationService.DownloadStatus.PAUSED, FAKE_DOWNLOAD_1, mNotification); assertFalse(mDownloadServiceManager.mIsServiceBound); - assertEquals(DownloadForegroundService.StopForegroundNotification.DETACH, + assertEquals(DownloadForegroundServiceImpl.StopForegroundNotification.DETACH, mDownloadServiceManager.mStopForegroundNotificationFlag); // Service restarts and then is cancelled, so notification is killed. @@ -245,7 +245,7 @@ DownloadNotificationService.DownloadStatus.CANCELLED, FAKE_DOWNLOAD_1, mNotification); assertFalse(mDownloadServiceManager.mIsServiceBound); - assertEquals(DownloadForegroundService.StopForegroundNotification.KILL, + assertEquals(DownloadForegroundServiceImpl.StopForegroundNotification.KILL, mDownloadServiceManager.mStopForegroundNotificationFlag); // Download starts and completes, notification is either detached or killed. @@ -259,7 +259,7 @@ DownloadNotificationService.DownloadStatus.COMPLETED, FAKE_DOWNLOAD_2, mNotification); assertFalse(mDownloadServiceManager.mIsServiceBound); - assertEquals(DownloadForegroundService.StopForegroundNotification.DETACH, + assertEquals(DownloadForegroundServiceImpl.StopForegroundNotification.DETACH, mDownloadServiceManager.mStopForegroundNotificationFlag); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadForegroundServiceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadForegroundServiceTest.java index f746c2c..6c31240 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadForegroundServiceTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadForegroundServiceTest.java
@@ -47,7 +47,7 @@ * Implementation of DownloadForegroundService for testing. * Mimics behavior of DownloadForegroundService except for calls to the actual service. */ - public static class MockDownloadForegroundService extends DownloadForegroundService { + public static class MockDownloadForegroundService extends DownloadForegroundServiceImpl { @IntDef({MethodID.START_FOREGROUND, MethodID.STOP_FOREGROUND_FLAGS, MethodID.RELAUNCH_NOTIFICATION}) @Retention(RetentionPolicy.SOURCE) @@ -65,6 +65,10 @@ // Used for saving MethodID values. List<Integer> mMethodCalls = new ArrayList<>(); + public MockDownloadForegroundService() { + setService(new DownloadForegroundService()); + } + // Clears stored flags/boolean/id/method calls. Call between tests runs. void clearStoredState() { mStopForegroundFlags = -1; @@ -214,7 +218,7 @@ mForegroundService.clearStoredState(); mForegroundService.stopDownloadForegroundService( - DownloadForegroundService.StopForegroundNotification.DETACH, + DownloadForegroundServiceImpl.StopForegroundNotification.DETACH, INVALID_NOTIFICATION_ID, null); assertEquals(expectedMethodCalls, mForegroundService.mMethodCalls); assertEquals(STOP_FOREGROUND_DETACH, mForegroundService.mStopForegroundFlags); @@ -225,7 +229,7 @@ mForegroundService.clearStoredState(); mForegroundService.stopDownloadForegroundService( - DownloadForegroundService.StopForegroundNotification.DETACH, + DownloadForegroundServiceImpl.StopForegroundNotification.DETACH, INVALID_NOTIFICATION_ID, null); assertEquals(expectedMethodCalls, mForegroundService.mMethodCalls); assertEquals(STOP_FOREGROUND_DETACH, mForegroundService.mStopForegroundFlags); @@ -236,8 +240,8 @@ mForegroundService.clearStoredState(); mForegroundService.stopDownloadForegroundService( - DownloadForegroundService.StopForegroundNotification.KILL, INVALID_NOTIFICATION_ID, - null); + DownloadForegroundServiceImpl.StopForegroundNotification.KILL, + INVALID_NOTIFICATION_ID, null); assertEquals(expectedMethodCalls, mForegroundService.mMethodCalls); assertEquals(STOP_FOREGROUND_REMOVE, mForegroundService.mStopForegroundFlags); } @@ -260,7 +264,7 @@ mForegroundService.clearStoredState(); mForegroundService.stopDownloadForegroundService( - DownloadForegroundService.StopForegroundNotification.DETACH, FAKE_DOWNLOAD_ID1, + DownloadForegroundServiceImpl.StopForegroundNotification.DETACH, FAKE_DOWNLOAD_ID1, mNotification); List<Integer> expectedMethodCalls = Arrays.asList(MockDownloadForegroundService.MethodID.STOP_FOREGROUND_FLAGS, @@ -276,7 +280,7 @@ mForegroundService.clearStoredState(); mForegroundService.stopDownloadForegroundService( - DownloadForegroundService.StopForegroundNotification.DETACH, FAKE_DOWNLOAD_ID1, + DownloadForegroundServiceImpl.StopForegroundNotification.DETACH, FAKE_DOWNLOAD_ID1, mNotification); expectedMethodCalls = Arrays.asList(MockDownloadForegroundService.MethodID.STOP_FOREGROUND_FLAGS, @@ -291,7 +295,7 @@ mForegroundService.clearStoredState(); mForegroundService.stopDownloadForegroundService( - DownloadForegroundService.StopForegroundNotification.KILL, FAKE_DOWNLOAD_ID1, + DownloadForegroundServiceImpl.StopForegroundNotification.KILL, FAKE_DOWNLOAD_ID1, mNotification); expectedMethodCalls = Arrays.asList(MockDownloadForegroundService.MethodID.STOP_FOREGROUND_FLAGS); @@ -316,7 +320,7 @@ mForegroundService.clearStoredState(); mForegroundService.stopDownloadForegroundService( - DownloadForegroundService.StopForegroundNotification.DETACH, FAKE_DOWNLOAD_ID1, + DownloadForegroundServiceImpl.StopForegroundNotification.DETACH, FAKE_DOWNLOAD_ID1, mNotification); List<Integer> expectedMethodCalls = Arrays.asList(MockDownloadForegroundService.MethodID.RELAUNCH_NOTIFICATION, @@ -331,7 +335,7 @@ mForegroundService.mNextNotificationId = FAKE_DOWNLOAD_ID2; mForegroundService.stopDownloadForegroundService( - DownloadForegroundService.StopForegroundNotification.DETACH, FAKE_DOWNLOAD_ID1, + DownloadForegroundServiceImpl.StopForegroundNotification.DETACH, FAKE_DOWNLOAD_ID1, mNotification); expectedMethodCalls = Arrays.asList(MockDownloadForegroundService.MethodID.RELAUNCH_NOTIFICATION, @@ -347,7 +351,7 @@ mForegroundService.clearStoredState(); mForegroundService.stopDownloadForegroundService( - DownloadForegroundService.StopForegroundNotification.KILL, FAKE_DOWNLOAD_ID1, + DownloadForegroundServiceImpl.StopForegroundNotification.KILL, FAKE_DOWNLOAD_ID1, mNotification); expectedMethodCalls = Arrays.asList(MockDownloadForegroundService.MethodID.STOP_FOREGROUND_FLAGS); @@ -371,7 +375,7 @@ mForegroundService.mNextNotificationId = FAKE_DOWNLOAD_ID2; mForegroundService.stopDownloadForegroundService( - DownloadForegroundService.StopForegroundNotification.DETACH, FAKE_DOWNLOAD_ID1, + DownloadForegroundServiceImpl.StopForegroundNotification.DETACH, FAKE_DOWNLOAD_ID1, mNotification); List<Integer> expectedMethodCalls = Arrays.asList(MockDownloadForegroundService.MethodID.RELAUNCH_NOTIFICATION, @@ -388,7 +392,7 @@ mForegroundService.mNextNotificationId = FAKE_DOWNLOAD_ID2; mForegroundService.stopDownloadForegroundService( - DownloadForegroundService.StopForegroundNotification.DETACH, FAKE_DOWNLOAD_ID1, + DownloadForegroundServiceImpl.StopForegroundNotification.DETACH, FAKE_DOWNLOAD_ID1, mNotification); assertEquals(expectedMethodCalls, mForegroundService.mMethodCalls); assertEquals(ServiceCompat.STOP_FOREGROUND_REMOVE, mForegroundService.mStopForegroundFlags); @@ -401,7 +405,7 @@ mForegroundService.clearStoredState(); mForegroundService.stopDownloadForegroundService( - DownloadForegroundService.StopForegroundNotification.KILL, FAKE_DOWNLOAD_ID1, + DownloadForegroundServiceImpl.StopForegroundNotification.KILL, FAKE_DOWNLOAD_ID1, mNotification); expectedMethodCalls = Arrays.asList(MockDownloadForegroundService.MethodID.STOP_FOREGROUND_FLAGS);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/TosAndUmaFirstRunFragmentWithEnterpriseSupportTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/TosAndUmaFirstRunFragmentWithEnterpriseSupportTest.java index 4bad010d..9872ae5 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/TosAndUmaFirstRunFragmentWithEnterpriseSupportTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/TosAndUmaFirstRunFragmentWithEnterpriseSupportTest.java
@@ -4,6 +4,8 @@ package org.chromium.chrome.browser.firstrun; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import android.app.Activity; @@ -11,6 +13,8 @@ import android.app.Instrumentation.ActivityMonitor; import android.content.Context; import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.res.Configuration; import android.os.Bundle; import android.os.SystemClock; import android.support.test.InstrumentationRegistry; @@ -35,6 +39,7 @@ import org.chromium.base.CommandLine; import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.test.util.CallbackHelper; +import org.chromium.base.test.util.Feature; import org.chromium.chrome.R; import org.chromium.chrome.browser.customtabs.CustomTabsTestUtils; import org.chromium.chrome.browser.flags.ChromeSwitches; @@ -44,6 +49,7 @@ import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.chrome.browser.privacy.settings.PrivacyPreferencesManager; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.util.ChromeRenderTestRule; import org.chromium.components.policy.PolicyService; import org.chromium.content_public.browser.test.util.Criteria; import org.chromium.content_public.browser.test.util.CriteriaHelper; @@ -82,6 +88,10 @@ @Rule public DisableAnimationsTestRule mDisableAnimationsTestRule = new DisableAnimationsTestRule(); + @Rule + public ChromeRenderTestRule mRenderTestRule = + ChromeRenderTestRule.Builder.withPublicCorpus().build(); + @Mock public FirstRunAppRestrictionInfo mMockAppRestrictionInfo; @Mock @@ -174,7 +184,7 @@ assertHistograms(true, SpeedComparedToInflation.SLOWER, SpeedComparedToInflation.NOT_RECORDED, SpeedComparedToInflation.NOT_RECORDED); - // Try to accept Tos. + // Try to accept ToS. TestThreadUtils.runOnUiThreadBlocking((Runnable) mAcceptButton::performClick); Assert.assertTrue("Crash report should be enabled.", PrivacyPreferencesManager.getInstance().isUsageAndCrashReportingPermittedByUser()); @@ -402,6 +412,26 @@ PrivacyPreferencesManager.getInstance().isUsageAndCrashReportingPermittedByUser()); } + @Test + @SmallTest + @Feature({"RenderTest", "FirstRun"}) + public void testRender() throws Exception { + launchFirstRunThroughCustomTab(); + assertUIState(FragmentState.LOADING); + + // Clear the focus on view to avoid unexpected highlight on background. + View tosAndUmaFragment = + mActivity.getSupportFragmentManager().getFragments().get(0).getView(); + Assert.assertNotNull(tosAndUmaFragment); + TestThreadUtils.runOnUiThreadBlocking(tosAndUmaFragment::clearFocus); + + renderWithPortraitAndLandscape(tosAndUmaFragment, "fre_tosanduma_loading"); + + setAppRestrictionsMockInitialized(false); + assertUIState(FragmentState.NO_POLICY); + renderWithPortraitAndLandscape(tosAndUmaFragment, "fre_tosanduma_nopolicy"); + } + /** * Launch chrome through custom tab and trigger first run. */ @@ -617,4 +647,35 @@ } }); } + + private void renderWithPortraitAndLandscape(View tosAndUmaFragmentView, String testPrefix) + throws Exception { + mRenderTestRule.render(tosAndUmaFragmentView, testPrefix + "_portrait"); + + setDeviceOrientation(tosAndUmaFragmentView, Configuration.ORIENTATION_LANDSCAPE); + mRenderTestRule.render(tosAndUmaFragmentView, testPrefix + "_landscape"); + + setDeviceOrientation(tosAndUmaFragmentView, Configuration.ORIENTATION_PORTRAIT); + mRenderTestRule.render(tosAndUmaFragmentView, testPrefix + "_portrait"); + } + + private void setDeviceOrientation(View tosAndUmaFragmentView, int orientation) { + // TODO(https://crbug.com/1133789): This function is copied mostly copied from + // TabUiTestHelper#rotateDeviceToOrientation. Merge / move these two test functions if + // applicable. + if (mActivity.getResources().getConfiguration().orientation == orientation) return; + assertTrue(orientation == Configuration.ORIENTATION_LANDSCAPE + || orientation == Configuration.ORIENTATION_PORTRAIT); + + boolean isLandscape = orientation == Configuration.ORIENTATION_LANDSCAPE; + mActivity.setRequestedOrientation(isLandscape ? ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE + : ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + + CriteriaHelper.pollUiThread(() -> { + Criteria.checkThat( + mActivity.getResources().getConfiguration().orientation, is(orientation)); + Criteria.checkThat(tosAndUmaFragmentView.getWidth() > tosAndUmaFragmentView.getHeight(), + is(isLandscape)); + }); + } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/incognito/IncognitoNotificationServiceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/incognito/IncognitoNotificationServiceTest.java index a80557d..ffec71e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/incognito/IncognitoNotificationServiceTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/incognito/IncognitoNotificationServiceTest.java
@@ -6,7 +6,6 @@ import static org.junit.Assert.assertEquals; -import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.NotificationManager; import android.app.PendingIntent; @@ -29,6 +28,7 @@ import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; +import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.tab.TabLaunchType; @@ -190,7 +190,7 @@ @MediumTest @Feature("Incognito") @TargetApi(Build.VERSION_CODES.M) - @SuppressLint("NewApi") + @MinAndroidSdkLevel(Build.VERSION_CODES.M) public void testCloseAllIncognitoNotificationIsDisplayed() { mActivityTestRule.startMainActivityOnBlankPage();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/incognito/OWNERS b/chrome/android/javatests/src/org/chromium/chrome/browser/incognito/OWNERS new file mode 100644 index 0000000..409cdd8 --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/incognito/OWNERS
@@ -0,0 +1,5 @@ +per-file *Leakage*=roagarwal@chromium.org +per-file *IncognitoDataTestUtils*=roagarwal@chromium.org + +# TEAM: chrome-privacy-core@google.com +# COMPONENT: Privacy>Incognito
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeIntentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeIntentTest.java index 4025ce2a9..fe9c25f 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeIntentTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeIntentTest.java
@@ -148,7 +148,7 @@ .getApplicationContext(); Intent intent = new Intent(NotificationConstants.ACTION_CLICK_NOTIFICATION); - intent.setClass(context, NotificationService.Receiver.class); + intent.setClass(context, NotificationServiceImpl.Receiver.class); intent.putExtra(NotificationConstants.EXTRA_NOTIFICATION_ID, "42"); intent.putExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_PROFILE_ID, "Default");
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omaha/RequestGeneratorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omaha/RequestGeneratorTest.java index 0aa38ed..fafad4c 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omaha/RequestGeneratorTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omaha/RequestGeneratorTest.java
@@ -21,10 +21,10 @@ import org.chromium.base.test.util.AdvancedMockContext; import org.chromium.base.test.util.Feature; -import org.chromium.chrome.browser.identity.SettingsSecureBasedIdentificationGenerator; -import org.chromium.chrome.browser.identity.UniqueIdentificationGenerator; -import org.chromium.chrome.browser.identity.UniqueIdentificationGeneratorFactory; import org.chromium.chrome.browser.signin.IdentityServicesProvider; +import org.chromium.chrome.browser.uid.SettingsSecureBasedIdentificationGenerator; +import org.chromium.chrome.browser.uid.UniqueIdentificationGenerator; +import org.chromium.chrome.browser.uid.UniqueIdentificationGeneratorFactory; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.omaha.AttributeFinder; import org.chromium.chrome.test.omaha.MockRequestGenerator;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewTest.java index 4fb6cbd..2643058 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewTest.java
@@ -15,8 +15,6 @@ import static org.hamcrest.CoreMatchers.allOf; import static org.hamcrest.CoreMatchers.containsString; -import static org.hamcrest.Matchers.instanceOf; -import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -25,7 +23,6 @@ import android.os.Build; import android.view.View; -import android.widget.Button; import androidx.test.filters.MediumTest; @@ -404,7 +401,7 @@ onView(withId(R.id.page_info_permissions_row)).perform(click()); // Clear permissions in page info. onView(withText("Reset permissions")).perform(click()); - onView(allOf(is(instanceOf(Button.class)), withText("Reset permissions"))).perform(click()); + onView(withText("Reset")).perform(click()); // Wait until the UI navigates back and check permissions are reset. onViewWaiting(allOf(withId(R.id.page_info_row_wrapper), isDisplayed())); // Make sure that the permission section is gone because there are no longer exceptions.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncTestRule.java index 3048bee..6e69add 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncTestRule.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncTestRule.java
@@ -23,11 +23,11 @@ import org.chromium.chrome.browser.app.ChromeActivity; import org.chromium.chrome.browser.autofill.PersonalDataManager; import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard; -import org.chromium.chrome.browser.identity.UniqueIdentificationGenerator; -import org.chromium.chrome.browser.identity.UniqueIdentificationGeneratorFactory; -import org.chromium.chrome.browser.identity.UuidBasedUniqueIdentificationGenerator; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.signin.UnifiedConsentServiceBridge; +import org.chromium.chrome.browser.uid.UniqueIdentificationGenerator; +import org.chromium.chrome.browser.uid.UniqueIdentificationGeneratorFactory; +import org.chromium.chrome.browser.uid.UuidBasedUniqueIdentificationGenerator; import org.chromium.chrome.test.ChromeActivityTestRule; import org.chromium.chrome.test.util.browser.signin.AccountManagerTestRule; import org.chromium.chrome.test.util.browser.signin.SigninTestUtil;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/test/ScreenShooter.java b/chrome/android/javatests/src/org/chromium/chrome/browser/test/ScreenShooter.java index 18a35b61..a5f1fe9b 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/test/ScreenShooter.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/test/ScreenShooter.java
@@ -25,7 +25,7 @@ import org.junit.runner.Description; import org.chromium.base.test.util.Feature; -import org.chromium.chrome.browser.ChromeVersionInfo; +import org.chromium.chrome.browser.version.ChromeVersionInfo; import java.io.File; import java.io.FileWriter;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/translate/TranslateCompactInfoBarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/translate/TranslateCompactInfoBarTest.java index f131f68..87b48d3 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/translate/TranslateCompactInfoBarTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/translate/TranslateCompactInfoBarTest.java
@@ -17,6 +17,7 @@ import org.junit.runner.RunWith; import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.Restriction; import org.chromium.chrome.R; @@ -72,11 +73,9 @@ @Test @MediumTest @Feature({"Browser", "Main"}) - // TODO(crbug.com/1134812): Remove the reliance on a network connection for these tests. - @Restriction({ChromeRestriction.RESTRICTION_TYPE_GOOGLE_PLAY_SERVICES, - Restriction.RESTRICTION_TYPE_INTERNET}) - public void - testTranslateCompactInfoBarAppears() throws TimeoutException { + @Restriction(ChromeRestriction.RESTRICTION_TYPE_GOOGLE_PLAY_SERVICES) + @DisabledTest(message = "https://crbug.com/1130712") + public void testTranslateCompactInfoBarAppears() throws TimeoutException { mActivityTestRule.loadUrl(mTestServer.getURL(TRANSLATE_PAGE)); mListener.addInfoBarAnimationFinished("InfoBar not opened."); InfoBar infoBar = mInfoBarContainer.getInfoBarsForTesting().get(0); @@ -90,10 +89,9 @@ @Test @MediumTest @Feature({"Browser", "Main"}) - @Restriction({ChromeRestriction.RESTRICTION_TYPE_GOOGLE_PLAY_SERVICES, - Restriction.RESTRICTION_TYPE_INTERNET}) - public void - testTranslateCompactInfoBarOverflowMenus() throws TimeoutException { + @Restriction(ChromeRestriction.RESTRICTION_TYPE_GOOGLE_PLAY_SERVICES) + @DisabledTest(message = "https://crbug.com/1130712") + public void testTranslateCompactInfoBarOverflowMenus() throws TimeoutException { mActivityTestRule.loadUrl(mTestServer.getURL(TRANSLATE_PAGE)); mListener.addInfoBarAnimationFinished("InfoBar not opened."); TranslateCompactInfoBar infoBar = @@ -114,10 +112,9 @@ @Test @MediumTest @Feature({"Browser", "Main"}) - @Restriction({ChromeRestriction.RESTRICTION_TYPE_GOOGLE_PLAY_SERVICES, - Restriction.RESTRICTION_TYPE_INTERNET}) - public void - testTabMenuDismissedOnOrientationChange() throws Exception { + @Restriction(ChromeRestriction.RESTRICTION_TYPE_GOOGLE_PLAY_SERVICES) + @DisabledTest(message = "https://crbug.com/1130712") + public void testTabMenuDismissedOnOrientationChange() throws Exception { mActivityTestRule.loadUrl(mTestServer.getURL(TRANSLATE_PAGE)); mListener.addInfoBarAnimationFinished("InfoBar not opened."); TranslateCompactInfoBar infoBar = @@ -145,10 +142,9 @@ @Test @MediumTest @Feature({"Browser", "Main"}) - @Restriction({ChromeRestriction.RESTRICTION_TYPE_GOOGLE_PLAY_SERVICES, - Restriction.RESTRICTION_TYPE_INTERNET}) - public void - testTranslateCompactInfoBarReopenOnTarget() throws TimeoutException { + @Restriction(ChromeRestriction.RESTRICTION_TYPE_GOOGLE_PLAY_SERVICES) + @DisabledTest(message = "https://crbug.com/1130712") + public void testTranslateCompactInfoBarReopenOnTarget() throws TimeoutException { mActivityTestRule.loadUrl(mTestServer.getURL(TRANSLATE_PAGE)); mListener.addInfoBarAnimationFinished("InfoBar not opened."); @@ -181,10 +177,9 @@ @Test @MediumTest @Feature({"Browser", "Main"}) - @Restriction({ChromeRestriction.RESTRICTION_TYPE_GOOGLE_PLAY_SERVICES, - Restriction.RESTRICTION_TYPE_INTERNET}) - public void - testStartTranslateOnManualInitiation() throws TimeoutException { + @Restriction(ChromeRestriction.RESTRICTION_TYPE_GOOGLE_PLAY_SERVICES) + @DisabledTest(message = "https://crbug.com/1130712") + public void testStartTranslateOnManualInitiation() throws TimeoutException { // Load a page that won't trigger the translate recommendation. mActivityTestRule.loadUrl(mTestServer.getURL(NON_TRANSLATE_PAGE)); @@ -209,10 +204,9 @@ @Test @MediumTest @Feature({"Browser", "Main"}) - @Restriction({ChromeRestriction.RESTRICTION_TYPE_GOOGLE_PLAY_SERVICES, - Restriction.RESTRICTION_TYPE_INTERNET}) - public void - testManualInitiationWithBarOpen() throws TimeoutException { + @Restriction(ChromeRestriction.RESTRICTION_TYPE_GOOGLE_PLAY_SERVICES) + @DisabledTest(message = "https://crbug.com/1130712") + public void testManualInitiationWithBarOpen() throws TimeoutException { mActivityTestRule.loadUrl(mTestServer.getURL(TRANSLATE_PAGE)); mListener.addInfoBarAnimationFinished("InfoBar not opened.");
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/translate/TranslateIntentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/translate/TranslateIntentTest.java index 79278f0..2dd274c 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/translate/TranslateIntentTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/translate/TranslateIntentTest.java
@@ -8,6 +8,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; +import android.os.Build.VERSION_CODES; import androidx.test.filters.MediumTest; import androidx.test.filters.SmallTest; @@ -24,7 +25,7 @@ import org.chromium.base.ContextUtils; import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.CommandLineFlags; -import org.chromium.base.test.util.Restriction; +import org.chromium.base.test.util.DisableIf; import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.document.ChromeLauncherActivity; import org.chromium.chrome.browser.flags.ChromeFeatureList; @@ -135,10 +136,12 @@ @Test @MediumTest - // TODO(crbug.com/1134812): Remove the reliance on a network connection for these tests. - @Restriction(Restriction.RESTRICTION_TYPE_INTERNET) + @DisableIf. + Build(sdk_is_greater_than = VERSION_CODES.LOLLIPOP_MR1, sdk_is_less_than = VERSION_CODES.N, + message = "Consistently failing on Marshmallow https://crbug.com/1127786") @Features.DisableFeatures({ChromeFeatureList.TRANSLATE_INTENT}) - public void testTranslateIntentDisabled() throws TimeoutException { + public void + testTranslateIntentDisabled() throws TimeoutException { final String url = sActivityTestRule.getTestServer().getURL(TRANSLATE_PAGE); // Load a page that triggers the translate recommendation. sActivityTestRule.loadUrl(url); @@ -153,9 +156,12 @@ @Test @MediumTest - @Restriction(Restriction.RESTRICTION_TYPE_INTERNET) + @DisableIf. + Build(sdk_is_greater_than = VERSION_CODES.LOLLIPOP_MR1, sdk_is_less_than = VERSION_CODES.N, + message = "Consistently failing on Marshmallow https://crbug.com/1127786") @Features.EnableFeatures({ChromeFeatureList.TRANSLATE_INTENT}) - public void testTranslateIntentOnTranslatePage() throws TimeoutException { + public void + testTranslateIntentOnTranslatePage() throws TimeoutException { final String url = sActivityTestRule.getTestServer().getURL(TRANSLATE_PAGE); // Load a page that triggers the translate recommendation. sActivityTestRule.loadUrl(url); @@ -170,9 +176,12 @@ @Test @MediumTest - @Restriction(Restriction.RESTRICTION_TYPE_INTERNET) + @DisableIf. + Build(sdk_is_greater_than = VERSION_CODES.LOLLIPOP_MR1, sdk_is_less_than = VERSION_CODES.N, + message = "Consistently failing on Marshmallow https://crbug.com/1127786") @Features.EnableFeatures({ChromeFeatureList.TRANSLATE_INTENT}) - public void testTranslateIntentOnNonTranslatePage() throws TimeoutException { + public void + testTranslateIntentOnNonTranslatePage() throws TimeoutException { final String url = sActivityTestRule.getTestServer().getURL(NON_TRANSLATE_PAGE); // Load a page that doesn't trigger the translate recommendation. sActivityTestRule.loadUrl(url); @@ -189,10 +198,12 @@ @Test @MediumTest - @Restriction(Restriction.RESTRICTION_TYPE_INTERNET) + @DisableIf. + Build(sdk_is_greater_than = VERSION_CODES.LOLLIPOP_MR1, sdk_is_less_than = VERSION_CODES.N, + message = "Consistently failing on Marshmallow https://crbug.com/1127786") @Features.EnableFeatures({ChromeFeatureList.TRANSLATE_INTENT}) - public void testTranslateIntentWithTargetLanguage() - throws TimeoutException, ExecutionException { + public void + testTranslateIntentWithTargetLanguage() throws TimeoutException, ExecutionException { final String url = sActivityTestRule.getTestServer().getURL(NON_TRANSLATE_PAGE); // Load a page that doesn't trigger the translate recommendation. sActivityTestRule.loadUrl(url); @@ -218,9 +229,12 @@ @Test @MediumTest - @Restriction(Restriction.RESTRICTION_TYPE_INTERNET) + @DisableIf. + Build(sdk_is_greater_than = VERSION_CODES.LOLLIPOP_MR1, sdk_is_less_than = VERSION_CODES.N, + message = "Consistently failing on Marshmallow https://crbug.com/1127786") @Features.EnableFeatures({ChromeFeatureList.TRANSLATE_INTENT}) - public void testTranslateIntentWithUnsupportedTargetLanguage() throws TimeoutException { + public void + testTranslateIntentWithUnsupportedTargetLanguage() throws TimeoutException { final String url = sActivityTestRule.getTestServer().getURL(NON_TRANSLATE_PAGE); // Load a page that doesn't trigger the translate recommendation. sActivityTestRule.loadUrl(url); @@ -235,9 +249,12 @@ @Test @MediumTest - @Restriction(Restriction.RESTRICTION_TYPE_INTERNET) + @DisableIf. + Build(sdk_is_greater_than = VERSION_CODES.LOLLIPOP_MR1, sdk_is_less_than = VERSION_CODES.N, + message = "Consistently failing on Marshmallow https://crbug.com/1127786") @Features.EnableFeatures({ChromeFeatureList.TRANSLATE_INTENT}) - public void testTranslateIntentOnIncognito() throws TimeoutException { + public void + testTranslateIntentOnIncognito() throws TimeoutException { final String url = sActivityTestRule.getTestServer().getURL(TRANSLATE_PAGE); // Load a page that triggers the translate recommendation. sActivityTestRule.loadUrlInNewTab(url, /*incognito=*/true); @@ -256,9 +273,12 @@ @Test @MediumTest - @Restriction(Restriction.RESTRICTION_TYPE_INTERNET) + @DisableIf. + Build(sdk_is_greater_than = VERSION_CODES.LOLLIPOP_MR1, sdk_is_less_than = VERSION_CODES.N, + message = "Consistently failing on Marshmallow https://crbug.com/1127786") @Features.EnableFeatures({ChromeFeatureList.TRANSLATE_INTENT}) - public void testTranslateIntentWithUrlMismatch() throws TimeoutException { + public void + testTranslateIntentWithUrlMismatch() throws TimeoutException { final String url = sActivityTestRule.getTestServer().getURL(TRANSLATE_PAGE); // Load a page that triggers the translate recommendation. sActivityTestRule.loadUrl(url); @@ -273,9 +293,12 @@ @Test @MediumTest - @Restriction(Restriction.RESTRICTION_TYPE_INTERNET) + @DisableIf. + Build(sdk_is_greater_than = VERSION_CODES.LOLLIPOP_MR1, sdk_is_less_than = VERSION_CODES.N, + message = "Consistently failing on Marshmallow https://crbug.com/1127786") @Features.EnableFeatures({ChromeFeatureList.TRANSLATE_INTENT}) - public void testTranslateIntentWithoutExpectedUrl() throws TimeoutException { + public void + testTranslateIntentWithoutExpectedUrl() throws TimeoutException { final String url = sActivityTestRule.getTestServer().getURL(TRANSLATE_PAGE); // Load a page that triggers the translate recommendation. sActivityTestRule.loadUrl(url); @@ -290,9 +313,12 @@ @Test @MediumTest - @Restriction(Restriction.RESTRICTION_TYPE_INTERNET) + @DisableIf. + Build(sdk_is_greater_than = VERSION_CODES.LOLLIPOP_MR1, sdk_is_less_than = VERSION_CODES.N, + message = "Consistently failing on Marshmallow https://crbug.com/1127786") @Features.EnableFeatures({ChromeFeatureList.TRANSLATE_INTENT}) - public void testTranslateIntentVerifyComponent() throws TimeoutException { + public void + testTranslateIntentVerifyComponent() throws TimeoutException { final String url = sActivityTestRule.getTestServer().getURL(TRANSLATE_PAGE); // Load a page that triggers the translate recommendation. sActivityTestRule.loadUrl(url); @@ -313,9 +339,12 @@ @Test @MediumTest - @Restriction(Restriction.RESTRICTION_TYPE_INTERNET) + @DisableIf. + Build(sdk_is_greater_than = VERSION_CODES.LOLLIPOP_MR1, sdk_is_less_than = VERSION_CODES.N, + message = "Consistently failing on Marshmallow https://crbug.com/1127786") @Features.EnableFeatures({ChromeFeatureList.TRANSLATE_INTENT}) - public void testTranslateIntentIncorrectComponent() throws TimeoutException { + public void + testTranslateIntentIncorrectComponent() throws TimeoutException { final String url = sActivityTestRule.getTestServer().getURL(TRANSLATE_PAGE); // Load a page that triggers the translate recommendation. sActivityTestRule.loadUrl(url);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/toolbar/TopToolbarOverlayMediatorTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/toolbar/TopToolbarOverlayMediatorTest.java index d23102b..d875eec 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/toolbar/TopToolbarOverlayMediatorTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/toolbar/TopToolbarOverlayMediatorTest.java
@@ -20,7 +20,6 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import org.chromium.base.supplier.ObservableSupplierImpl; import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.chrome.browser.ActivityTabProvider; import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider; @@ -63,15 +62,10 @@ @Captor private ArgumentCaptor<ActivityTabProvider.ActivityTabObserver> mActivityTabObserverCaptor; - private ObservableSupplierImpl<Boolean> mAndroidViewShownSupplier; - @Before public void beforeTest() { MockitoAnnotations.initMocks(this); - mAndroidViewShownSupplier = new ObservableSupplierImpl<>(); - mAndroidViewShownSupplier.set(true); - TopToolbarOverlayMediator.setToolbarBackgroundColorForTesting(Color.RED); TopToolbarOverlayMediator.setUrlBarColorForTesting(Color.BLUE); TopToolbarOverlayMediator.setIsTabletForTesting(false); @@ -88,7 +82,8 @@ .build(); mMediator = new TopToolbarOverlayMediator(mModel, mContext, mLayoutManager, - (info) -> {}, mTabSupplier, mBrowserControlsProvider, mAndroidViewShownSupplier); + (info) -> {}, mTabSupplier, mBrowserControlsProvider); + mMediator.setIsAndroidViewVisible(true); // Ensure the observer is added to the initial tab. verify(mTabSupplier).addObserverAndTrigger(mActivityTabObserverCaptor.capture()); @@ -137,12 +132,12 @@ @Test public void testShadowVisibility_androidViewForceHidden() { - mAndroidViewShownSupplier.set(true); + mMediator.setIsAndroidViewVisible(true); Assert.assertFalse( "Shadow should be invisible.", mModel.get(TopToolbarOverlayProperties.SHOW_SHADOW)); - mAndroidViewShownSupplier.set(false); + mMediator.setIsAndroidViewVisible(false); Assert.assertTrue( "Shadow should be visible.", mModel.get(TopToolbarOverlayProperties.SHOW_SHADOW));
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/content_capture/ContentCaptureHistoryDeletionObserverTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/content_capture/ContentCaptureHistoryDeletionObserverTest.java new file mode 100644 index 0000000..4f0a031 --- /dev/null +++ b/chrome/android/junit/src/org/chromium/chrome/browser/content_capture/ContentCaptureHistoryDeletionObserverTest.java
@@ -0,0 +1,92 @@ +// 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. + +package org.chromium.chrome.browser.content_capture; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.verify; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; + +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.chrome.browser.history.HistoryDeletionInfo; +import org.chromium.components.content_capture.ContentCaptureController; + +/** + * Unit tests for the ContentCaptureHistoryDeletionObserver. + */ +@RunWith(BaseRobolectricTestRunner.class) +@Config(manifest = Config.NONE) +public class ContentCaptureHistoryDeletionObserverTest { + @Mock + ContentCaptureController mContentCaptureController; + @Mock + HistoryDeletionInfo mHistoryDeletionInfo; + + ContentCaptureHistoryDeletionObserver mContentCaptureHistoryDeletionObserver; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mContentCaptureHistoryDeletionObserver = + new ContentCaptureHistoryDeletionObserver(() -> mContentCaptureController); + } + + @Test + public void clearAllData_FromSpecificTimeRange() { + doReturn(false).when(mHistoryDeletionInfo).isTimeRangeForAllTime(); + doReturn(true).when(mHistoryDeletionInfo).isTimeRangeValid(); + + mContentCaptureHistoryDeletionObserver.onURLsDeleted(mHistoryDeletionInfo); + verify(mContentCaptureController).clearAllContentCaptureData(); + } + + @Test + public void clearAllData_ForAllTime() { + doReturn(true).when(mHistoryDeletionInfo).isTimeRangeForAllTime(); + doReturn(false).when(mHistoryDeletionInfo).isTimeRangeValid(); + + mContentCaptureHistoryDeletionObserver.onURLsDeleted(mHistoryDeletionInfo); + verify(mContentCaptureController).clearAllContentCaptureData(); + } + + @Test + public void clearAllData_ForSpecficURLs() { + doReturn(false).when(mHistoryDeletionInfo).isTimeRangeForAllTime(); + doReturn(false).when(mHistoryDeletionInfo).isTimeRangeValid(); + String[] urls = new String[] {"one", "two", "three"}; + doReturn(urls).when(mHistoryDeletionInfo).getDeletedURLs(); + + mContentCaptureHistoryDeletionObserver.onURLsDeleted(mHistoryDeletionInfo); + verify(mContentCaptureController).clearContentCaptureDataForURLs(urls); + } + + @Test + public void clearAllData_ThrowsRuntimeException() { + doThrow(RuntimeException.class) + .when(mContentCaptureController) + .clearContentCaptureDataForURLs(any()); + doReturn(false).when(mHistoryDeletionInfo).isTimeRangeForAllTime(); + doReturn(false).when(mHistoryDeletionInfo).isTimeRangeValid(); + String[] urls = new String[] {"one", "two", "three"}; + doReturn(urls).when(mHistoryDeletionInfo).getDeletedURLs(); + + try { + mContentCaptureHistoryDeletionObserver.onURLsDeleted(mHistoryDeletionInfo); + fail("Expected exception to be thrown."); + } catch (RuntimeException e) { + assertTrue(e.toString().contains("Deleted URLs length: " + urls.length)); + } + } +} \ No newline at end of file
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceNotificationTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceNotificationTest.java index f924e74c..ad7343e 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceNotificationTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceNotificationTest.java
@@ -33,11 +33,11 @@ import org.chromium.base.ContextUtils; import org.chromium.base.metrics.test.ShadowRecordHistogram; import org.chromium.base.test.BaseRobolectricTestRunner; -import org.chromium.chrome.browser.ChromeVersionInfo; import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar; import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; +import org.chromium.chrome.browser.version.ChromeVersionInfo; import org.chromium.chrome.test.util.browser.Features; import org.chromium.components.search_engines.TemplateUrl; import org.chromium.components.search_engines.TemplateUrlService;
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 31dcb84..69f0b7d 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -5133,11 +5133,6 @@ flag_descriptions::kEnableImplicitRootScrollerDescription, kOsAll, FEATURE_VALUE_TYPE(blink::features::kImplicitRootScroller)}, - {"enable-cssom-view-scroll-coordinates", - flag_descriptions::kEnableCSSOMViewScrollCoordinatesName, - flag_descriptions::kEnableCSSOMViewScrollCoordinatesDescription, kOsAll, - FEATURE_VALUE_TYPE(blink::features::kCSSOMViewScrollCoordinates)}, - {"enable-text-fragment-anchor", flag_descriptions::kEnableTextFragmentAnchorName, flag_descriptions::kEnableTextFragmentAnchorDescription, kOsAll,
diff --git a/chrome/browser/android/history/history_deletion_info.cc b/chrome/browser/android/history/history_deletion_info.cc index ff78d78..244b8c7 100644 --- a/chrome/browser/android/history/history_deletion_info.cc +++ b/chrome/browser/android/history/history_deletion_info.cc
@@ -47,21 +47,6 @@ return deletion_info->time_range().IsAllTime(); } -jlong JNI_HistoryDeletionInfo_GetTimeRangeBegin( - JNIEnv* env, - jlong history_deletion_info_ptr) { - history::DeletionInfo* deletion_info = - ToDeletionInfo(history_deletion_info_ptr); - return deletion_info->time_range().begin().ToJavaTime(); -} - -jlong JNI_HistoryDeletionInfo_GetTimeRangeEnd(JNIEnv* env, - jlong history_deletion_info_ptr) { - history::DeletionInfo* deletion_info = - ToDeletionInfo(history_deletion_info_ptr); - return deletion_info->time_range().end().ToJavaTime(); -} - ScopedJavaLocalRef<jobject> CreateHistoryDeletionInfo( JNIEnv* env, const history::DeletionInfo* deletion_info) {
diff --git a/chrome/browser/chrome_browser_main_win.cc b/chrome/browser/chrome_browser_main_win.cc index c5bd51f..45e80d78 100644 --- a/chrome/browser/chrome_browser_main_win.cc +++ b/chrome/browser/chrome_browser_main_win.cc
@@ -52,6 +52,7 @@ #include "chrome/browser/safe_browsing/chrome_cleaner/settings_resetter_win.h" #include "chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_config.h" #include "chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_util_win.h" +#include "chrome/browser/shell_integration_win.h" #include "chrome/browser/ui/simple_message_box.h" #include "chrome/browser/ui/uninstall_browser_prompt.h" #include "chrome/browser/web_applications/chrome_pwa_launcher/last_browser_file_util.h" @@ -75,6 +76,7 @@ #include "chrome/common/conflicts/module_watcher_win.h" #include "chrome/common/crash_keys.h" #include "chrome/common/env_vars.h" +#include "chrome/common/pref_names.h" #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" #include "chrome/install_static/install_details.h" @@ -87,7 +89,9 @@ #include "components/crash/core/app/dump_hung_process_with_ptype.h" #include "components/crash/core/common/crash_key.h" #include "components/os_crypt/os_crypt.h" +#include "components/prefs/pref_service.h" #include "components/version_info/channel.h" +#include "components/version_info/version_info.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_process_host.h" @@ -488,6 +492,28 @@ std::move(pwa_launcher_paths))); } +void MigratePinnedTaskBarShortcutsIfNeeded() { + // Update this number when users should go through a taskbar shortcut + // migration again. The last reason to do this was crrev.com/798174. @ + // 86.0.4231.0. + // + // Note: If shortcut updates need to be done once after a future OS upgrade, + // that should be done by re-versioning Active Setup (see //chrome/installer + // and https://crbug.com/577697 for details). + const base::Version kLastVersionNeedingMigration({86, 0, 4231, 0}); + + PrefService* local_state = g_browser_process->local_state(); + if (local_state) { + const base::Version last_version_migrated( + local_state->GetString(prefs::kShortcutMigrationVersion)); + if (!last_version_migrated.IsValid() || + last_version_migrated < kLastVersionNeedingMigration) { + shell_integration::win::MigrateTaskbarPins(base::BindOnce( + &PrefService::SetString, base::Unretained(local_state), + prefs::kShortcutMigrationVersion, version_info::GetVersionNumber())); + } + } +} // This error message is not localized because we failed to load the // localization data files. const char kMissingLocaleDataTitle[] = "Missing File Error"; @@ -707,6 +733,12 @@ FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()}, base::BindOnce(&web_app::RecordPwaLauncherResult)); + // Possibly migrate pinned taskbar shortcuts. + content::GetUIThreadTaskRunner({base::TaskPriority::BEST_EFFORT, + base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}) + ->PostTask(FROM_HERE, + base::BindOnce(&MigratePinnedTaskBarShortcutsIfNeeded)); + base::ImportantFileWriterCleaner::GetInstance().Start(); }
diff --git a/chrome/browser/chrome_browser_main_win_browsertest.cc b/chrome/browser/chrome_browser_main_win_browsertest.cc new file mode 100644 index 0000000..c2b193e --- /dev/null +++ b/chrome/browser/chrome_browser_main_win_browsertest.cc
@@ -0,0 +1,42 @@ +// 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/chrome_browser_main_win.h" + +#include "chrome/browser/browser_process.h" +#include "chrome/common/pref_names.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "components/prefs/pref_service.h" +#include "components/version_info/version_info.h" +#include "content/public/test/browser_test.h" +#include "content/public/test/test_utils.h" + +using ChromeBrowserMainWinTest = InProcessBrowserTest; + +IN_PROC_BROWSER_TEST_F(ChromeBrowserMainWinTest, PRE_ShortcutsAreMigratedOnce) { + // Wait for all startup tasks to run. + content::RunAllTasksUntilIdle(); + + // Confirm that shortcuts were migrated. + const std::string last_version_migrated = + g_browser_process->local_state()->GetString( + prefs::kShortcutMigrationVersion); + EXPECT_EQ(last_version_migrated, version_info::GetVersionNumber()); + + // Set the version back as far as kLastVersionNeedingMigration and ensure it's + // not migrated again. + g_browser_process->local_state()->SetString(prefs::kShortcutMigrationVersion, + "86.0.4231.0"); +} + +IN_PROC_BROWSER_TEST_F(ChromeBrowserMainWinTest, ShortcutsAreMigratedOnce) { + content::RunAllTasksUntilIdle(); + + // Confirm that shortcuts weren't migrated when marked as having last been + // migrated in kLastVersionNeedingMigration+. + const std::string last_version_migrated = + g_browser_process->local_state()->GetString( + prefs::kShortcutMigrationVersion); + EXPECT_EQ(last_version_migrated, "86.0.4231.0"); +}
diff --git a/chrome/browser/chromeos/extensions/document_scan/document_scan_api.cc b/chrome/browser/chromeos/extensions/document_scan/document_scan_api.cc index 0927d22..c7e5ff3 100644 --- a/chrome/browser/chromeos/extensions/document_scan/document_scan_api.cc +++ b/chrome/browser/chromeos/extensions/document_scan/document_scan_api.cc
@@ -85,7 +85,8 @@ base::BindOnce(&DocumentScanScanFunction::OnScanCompleted, this)); } -void DocumentScanScanFunction::OnPageReceived(std::string scanned_image) { +void DocumentScanScanFunction::OnPageReceived(std::string scanned_image, + uint32_t /*page_number*/) { // Take only the first page of the scan. if (!scan_data_.has_value()) { scan_data_ = std::move(scanned_image);
diff --git a/chrome/browser/chromeos/extensions/document_scan/document_scan_api.h b/chrome/browser/chromeos/extensions/document_scan/document_scan_api.h index f423596..c6e1b11b 100644 --- a/chrome/browser/chromeos/extensions/document_scan/document_scan_api.h +++ b/chrome/browser/chromeos/extensions/document_scan/document_scan_api.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_CHROMEOS_EXTENSIONS_DOCUMENT_SCAN_DOCUMENT_SCAN_API_H_ #define CHROME_BROWSER_CHROMEOS_EXTENSIONS_DOCUMENT_SCAN_DOCUMENT_SCAN_API_H_ +#include <cstdint> #include <memory> #include <string> #include <vector> @@ -34,7 +35,7 @@ friend class DocumentScanScanFunctionTest; void OnNamesReceived(std::vector<std::string> scanner_names); - void OnPageReceived(std::string scanned_image); + void OnPageReceived(std::string scanned_image, uint32_t /*page_number*/); void OnScanCompleted(bool success); base::Optional<std::string> scan_data_;
diff --git a/chrome/browser/chromeos/login/session/user_session_manager.cc b/chrome/browser/chromeos/login/session/user_session_manager.cc index c5be3aa..f830ce7 100644 --- a/chrome/browser/chromeos/login/session/user_session_manager.cc +++ b/chrome/browser/chromeos/login/session/user_session_manager.cc
@@ -2136,7 +2136,7 @@ void UserSessionManager::DoBrowserLaunchInternal(Profile* profile, LoginDisplayHost* login_host, bool locale_pref_checked) { - if (browser_shutdown::IsTryingToQuit()) + if (browser_shutdown::IsTryingToQuit() || chrome::IsAttemptingShutdown()) return; if (!locale_pref_checked) { @@ -2210,7 +2210,7 @@ void UserSessionManager::RespectLocalePreferenceWrapper( Profile* profile, const base::Closure& callback) { - if (browser_shutdown::IsTryingToQuit()) + if (browser_shutdown::IsTryingToQuit() || chrome::IsAttemptingShutdown()) return; const user_manager::User* const user =
diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc index fd4ac7e..d0d56fd 100644 --- a/chrome/browser/chromeos/login/wizard_controller.cc +++ b/chrome/browser/chromeos/login/wizard_controller.cc
@@ -1445,11 +1445,10 @@ // Launch browser and delete login host controller. content::GetUIThreadTaskRunner({})->PostTask( - FROM_HERE, - base::BindOnce(&UserSessionManager::DoBrowserLaunch, - base::Unretained(UserSessionManager::GetInstance()), - ProfileManager::GetActiveUserProfile(), - GetLoginDisplayHost())); + FROM_HERE, base::BindOnce(&UserSessionManager::DoBrowserLaunch, + UserSessionManager::GetInstance()->AsWeakPtr(), + ProfileManager::GetActiveUserProfile(), + GetLoginDisplayHost())); } void WizardController::OnDeviceDisabledChecked(bool device_disabled) {
diff --git a/chrome/browser/chromeos/scanning/fake_lorgnette_scanner_manager.cc b/chrome/browser/chromeos/scanning/fake_lorgnette_scanner_manager.cc index 2939cf3..39018988 100644 --- a/chrome/browser/chromeos/scanning/fake_lorgnette_scanner_manager.cc +++ b/chrome/browser/chromeos/scanning/fake_lorgnette_scanner_manager.cc
@@ -36,7 +36,8 @@ ScanCallback callback) { if (scan_data_.has_value()) { base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(page_callback, scan_data_.value())); + FROM_HERE, + base::BindOnce(page_callback, scan_data_.value(), /*page_number=*/0)); } base::ThreadTaskRunnerHandle::Get()->PostTask(
diff --git a/chrome/browser/chromeos/scanning/lorgnette_scanner_manager.h b/chrome/browser/chromeos/scanning/lorgnette_scanner_manager.h index c152484c..6d0dd94c 100644 --- a/chrome/browser/chromeos/scanning/lorgnette_scanner_manager.h +++ b/chrome/browser/chromeos/scanning/lorgnette_scanner_manager.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_CHROMEOS_SCANNING_LORGNETTE_SCANNER_MANAGER_H_ #define CHROME_BROWSER_CHROMEOS_SCANNING_LORGNETTE_SCANNER_MANAGER_H_ +#include <cstdint> #include <memory> #include <string> #include <vector> @@ -27,7 +28,8 @@ base::OnceCallback<void(std::vector<std::string> scanner_names)>; using GetScannerCapabilitiesCallback = base::OnceCallback<void( const base::Optional<lorgnette::ScannerCapabilities>& capabilities)>; - using PageCallback = base::RepeatingCallback<void(std::string scan_data)>; + using PageCallback = base::RepeatingCallback<void(std::string scan_data, + uint32_t page_number)>; using ScanCallback = base::OnceCallback<void(bool success)>; ~LorgnetteScannerManager() override = default;
diff --git a/chrome/browser/chromeos/scanning/lorgnette_scanner_manager_unittest.cc b/chrome/browser/chromeos/scanning/lorgnette_scanner_manager_unittest.cc index c975077..e6e1d8e 100644 --- a/chrome/browser/chromeos/scanning/lorgnette_scanner_manager_unittest.cc +++ b/chrome/browser/chromeos/scanning/lorgnette_scanner_manager_unittest.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/chromeos/scanning/lorgnette_scanner_manager.h" +#include <cstdint> #include <memory> #include <string> #include <utility> @@ -209,7 +210,9 @@ } // Handles receiving a page from LorgnetteScannerManager::Scan(). - void PageCallback(std::string page_data) { scan_data_.push_back(page_data); } + void PageCallback(std::string page_data, uint32_t /*page_number*/) { + scan_data_.push_back(page_data); + } // Handles completion of LorgnetteScannerManager::Scan(). void ScanCallback(bool success) {
diff --git a/chrome/browser/chromeos/scanning/scan_service.cc b/chrome/browser/chromeos/scanning/scan_service.cc index 3b2b641..d1d01bb 100644 --- a/chrome/browser/chromeos/scanning/scan_service.cc +++ b/chrome/browser/chromeos/scanning/scan_service.cc
@@ -59,6 +59,7 @@ if (scanner_name.empty()) std::move(callback).Run(false); + base::Time::Now().UTCExplode(&start_time_); save_failed_ = false; // TODO(jschettler): Create a TypeConverter to convert from @@ -118,13 +119,13 @@ mojo::ConvertTo<mojo_ipc::ScannerCapabilitiesPtr>(capabilities.value())); } -void ScanService::OnPageReceived(std::string scanned_image) { - // TODO(jschettler): Add page number to filename. - base::Time::Exploded time; - base::Time::Now().UTCExplode(&time); +void ScanService::OnPageReceived(std::string scanned_image, + uint32_t page_number) { + // The |page_number| is 0-indexed. const std::string filename = base::StringPrintf( - "scan_%02d%02d%02d-%02d%02d%02d.png", time.year, time.month, - time.day_of_month, time.hour, time.minute, time.second); + "scan_%02d%02d%02d-%02d%02d%02d_page_%d.png", start_time_.year, + start_time_.month, start_time_.day_of_month, start_time_.hour, + start_time_.minute, start_time_.second, page_number + 1); const auto file_path = root_dir_.Append(kMyFilesPath).Append(filename); if (!base::WriteFile(file_path, scanned_image)) { LOG(ERROR) << "Failed to save scanned image: " << file_path.value().c_str();
diff --git a/chrome/browser/chromeos/scanning/scan_service.h b/chrome/browser/chromeos/scanning/scan_service.h index 30f0acb..1fdd2bf7 100644 --- a/chrome/browser/chromeos/scanning/scan_service.h +++ b/chrome/browser/chromeos/scanning/scan_service.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_CHROMEOS_SCANNING_SCAN_SERVICE_H_ #define CHROME_BROWSER_CHROMEOS_SCANNING_SCAN_SERVICE_H_ +#include <cstdint> #include <string> #include <vector> @@ -12,6 +13,7 @@ #include "base/files/file_path.h" #include "base/memory/weak_ptr.h" #include "base/optional.h" +#include "base/time/time.h" #include "base/unguessable_token.h" #include "chromeos/components/scanning/mojom/scanning.mojom.h" #include "chromeos/dbus/lorgnette/lorgnette_service.pb.h" @@ -65,7 +67,7 @@ // Processes each |scanned_image| received after calling // LorgnetteScannerManager::Scan(). - void OnPageReceived(std::string scanned_image); + void OnPageReceived(std::string scanned_image, uint32_t page_number); // Processes the final result of calling LorgnetteScannerManager::Scan(). void OnScanCompleted(ScanCallback callback, bool success); @@ -92,6 +94,9 @@ // Indicates whether there was a failure to save scanned images. bool save_failed_; + // The time a scan was started. Used in filenames when saving scanned images. + base::Time::Exploded start_time_; + base::WeakPtrFactory<ScanService> weak_ptr_factory_{this}; };
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 4330987..950cba5 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -1375,11 +1375,6 @@ "expiry_milestone": 85 }, { - "name": "enable-cssom-view-scroll-coordinates", - "owners": [ "cathiechen@igalia.com", "fwang@igalia.com" ], - "expiry_milestone": 87 - }, - { "name": "enable-data-reduction-proxy-server-experiment", "owners": [ "//components/data_reduction_proxy/OWNERS" ], // This flag is used for frequent manual testing and should not be removed.
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 3713c06..db4131e 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -752,16 +752,6 @@ "scroller'. i.e. The one that gets special features like URL bar movement, " "overscroll glow, rotation anchoring, etc."; -const char kEnableCSSOMViewScrollCoordinatesName[] = - "CSSOM View Scroll Coordinates"; -const char kEnableCSSOMViewScrollCoordinatesDescription[] = - "Enables CSSOM View Scroll Coordinates, this affects to box scroll " - "coordinates in scrollTop / scrollLeft / scrollTo' when ScrollOrigin isn't " - "at the left top corner. i.e. For leftwards overflow direction box " - "the X coordinate will start from 0 to negative value. For upwards box the " - "Y coordinate will start from 0 to negative value. And for other directions" - "(rightwards and downwards) the value will start from 0 to positive"; - const char kEnablePreviewsCoinFlipName[] = "Enable Previews Coin Flip"; const char kEnablePreviewsCoinFlipDescription[] = "Enable coin flip experimentation of Previews.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index ab141170..db1a60d5 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -445,9 +445,6 @@ extern const char kEnableImplicitRootScrollerName[]; extern const char kEnableImplicitRootScrollerDescription[]; -extern const char kEnableCSSOMViewScrollCoordinatesName[]; -extern const char kEnableCSSOMViewScrollCoordinatesDescription[]; - extern const char kEnableLayoutNGName[]; extern const char kEnableLayoutNGDescription[];
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java index 08a0d5f..1708f8d5 100644 --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java
@@ -52,7 +52,7 @@ put(ChromeFeatureList.CONDITIONAL_TAB_STRIP_ANDROID, false); put(ChromeFeatureList.HOMEPAGE_LOCATION_POLICY, false); put(ChromeFeatureList.HORIZONTAL_TAB_SWITCHER_ANDROID, false); - put(ChromeFeatureList.SERVICE_MANAGER_FOR_DOWNLOAD, false); + put(ChromeFeatureList.SERVICE_MANAGER_FOR_DOWNLOAD, true); put(ChromeFeatureList.SERVICE_MANAGER_FOR_BACKGROUND_PREFETCH, true); put(ChromeFeatureList.COMMAND_LINE_ON_NON_ROOTED, false); put(ChromeFeatureList.DOWNLOADS_AUTO_RESUMPTION_NATIVE, true);
diff --git a/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc b/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc index b57a994..9d633b5 100644 --- a/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc +++ b/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc
@@ -166,6 +166,14 @@ DCHECK(patch_level) << "Windows version too high!"; base::UmaHistogramSparse("Windows.PatchLevel", patch_level); + int kernel32_patch = os_info.Kernel32VersionNumber().patch; + int kernel32_build = os_info.Kernel32VersionNumber().build; + int kernel32_patch_level = 0; + if (kernel32_patch < 65536 && kernel32_build < 65536) + kernel32_patch_level = MAKELONG(kernel32_patch, kernel32_build); + DCHECK(kernel32_patch_level) << "Windows kernel32.dll version too high!"; + base::UmaHistogramSparse("Windows.PatchLevelKernel32", kernel32_patch_level); + base::UmaHistogramBoolean("Windows.HasHighResolutionTimeTicks", base::TimeTicks::IsHighResolution());
diff --git a/chrome/browser/nearby_sharing/nearby_connections_manager_impl.cc b/chrome/browser/nearby_sharing/nearby_connections_manager_impl.cc index 820d7973..0e29e18 100644 --- a/chrome/browser/nearby_sharing/nearby_connections_manager_impl.cc +++ b/chrome/browser/nearby_sharing/nearby_connections_manager_impl.cc
@@ -132,10 +132,10 @@ } discovery_listener_ = listener; - // TODO(b/168659459): Inject kFastAdvertisementServiceUuid once BLE scanning - // actually uses it. nearby_connections_->StartDiscovery( - kServiceId, DiscoveryOptions::New(kStrategy), + kServiceId, + DiscoveryOptions::New( + kStrategy, device::BluetoothUUID(kFastAdvertisementServiceUuid)), endpoint_discovery_listener_.BindNewPipeAndPassRemote(), std::move(callback)); }
diff --git a/chrome/browser/nearby_sharing/nearby_connections_manager_impl_unittest.cc b/chrome/browser/nearby_sharing/nearby_connections_manager_impl_unittest.cc index be59aa9..207abe4 100644 --- a/chrome/browser/nearby_sharing/nearby_connections_manager_impl_unittest.cc +++ b/chrome/browser/nearby_sharing/nearby_connections_manager_impl_unittest.cc
@@ -145,6 +145,9 @@ NearbyConnectionsMojom::StartDiscoveryCallback callback) { EXPECT_EQ(kServiceId, service_id); EXPECT_EQ(kStrategy, options->strategy); + EXPECT_EQ( + device::BluetoothUUID("0000fef3-0000-1000-8000-00805f9b34fb"), + options->fast_advertisement_service_uuid); listener_remote.Bind(std::move(listener)); std::move(callback).Run(Status::kSuccess);
diff --git a/chrome/browser/net/profile_network_context_service.cc b/chrome/browser/net/profile_network_context_service.cc index 082cff3..61b3047 100644 --- a/chrome/browser/net/profile_network_context_service.cc +++ b/chrome/browser/net/profile_network_context_service.cc
@@ -136,13 +136,13 @@ // feature flag and policy. Next steps would be changing the feature value to // false after enough heads up and then removing the feature. bool IsAmbientAuthAllowedForProfile(Profile* profile) { - if (profile->IsRegularProfile()) + if (profile->IsRegularProfile() && !profile->IsEphemeralGuestProfile()) return true; // Non-primary OTR profiles are not used to create browser windows and are // only technical means for a task that does not need to leave state after // it's completed. - if (!profile->IsPrimaryOTRProfile()) + if (profile->IsOffTheRecord() && !profile->IsPrimaryOTRProfile()) return true; PrefService* local_state = g_browser_process->local_state(); @@ -154,7 +154,7 @@ static_cast<net::AmbientAuthAllowedProfileTypes>(local_state->GetInteger( prefs::kAmbientAuthenticationInPrivateModesEnabled)); - if (profile->IsGuestSession()) { + if (profile->IsGuestSession() || profile->IsEphemeralGuestProfile()) { return base::FeatureList::IsEnabled( features::kEnableAmbientAuthenticationInGuestSession) || type == net::AmbientAuthAllowedProfileTypes::GUEST_AND_REGULAR ||
diff --git a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.cc index f706d5b4..b325d08 100644 --- a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.cc +++ b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.cc
@@ -979,14 +979,7 @@ // as these numbers do not change for different visibility types. if (visibility != FrameData::FrameVisibility::kAnyVisibility) return; - ADS_HISTOGRAM("Bytes.FullPage.SameOrigin2", PAGE_BYTES_HISTOGRAM, visibility, - aggregate_frame_data_->same_origin_bytes()); - if (aggregate_frame_data_->bytes()) { - ADS_HISTOGRAM("Bytes.FullPage.PercentSameOrigin2", UMA_HISTOGRAM_PERCENTAGE, - visibility, - aggregate_frame_data_->same_origin_bytes() * 100 / - aggregate_frame_data_->bytes()); - } + ADS_HISTOGRAM("Bytes.MainFrame.Network", PAGE_BYTES_HISTOGRAM, visibility, main_frame_data_->network_bytes()); ADS_HISTOGRAM("Bytes.MainFrame.Total2", PAGE_BYTES_HISTOGRAM, visibility, @@ -1097,17 +1090,11 @@ visibility, ad_frame_data.bytes()); ADS_HISTOGRAM("Bytes.AdFrames.PerFrame.Network", PAGE_BYTES_HISTOGRAM, visibility, ad_frame_data.network_bytes()); - ADS_HISTOGRAM("Bytes.AdFrames.PerFrame.SameOrigin2", PAGE_BYTES_HISTOGRAM, - visibility, ad_frame_data.same_origin_bytes()); if (ad_frame_data.bytes() > 0) { ADS_HISTOGRAM( "Bytes.AdFrames.PerFrame.PercentNetwork2", UMA_HISTOGRAM_PERCENTAGE, visibility, ad_frame_data.network_bytes() * 100 / ad_frame_data.bytes()); - ADS_HISTOGRAM( - "Bytes.AdFrames.PerFrame.PercentSameOrigin2", - UMA_HISTOGRAM_PERCENTAGE, visibility, - ad_frame_data.same_origin_bytes() * 100 / ad_frame_data.bytes()); } ADS_HISTOGRAM("FrameCounts.AdFrames.PerFrame.OriginStatus", UMA_HISTOGRAM_ENUMERATION, visibility,
diff --git a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_browsertest.cc b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_browsertest.cc index 9076e58..fea7c99 100644 --- a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_browsertest.cc +++ b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_browsertest.cc
@@ -1098,43 +1098,6 @@ } IN_PROC_BROWSER_TEST_F(AdsPageLoadMetricsObserverBrowserTest, - AdFrameSameOriginByteMetrics) { - base::HistogramTester histogram_tester; - - // cross_site_iframe_factory loads URLs like: - // http://b.com:40919/cross_site_iframe_factory.html?b() - SetRulesetWithRules({subresource_filter::testing::CreateSuffixRule("b()))"), - subresource_filter::testing::CreateSuffixRule("e())")}); - const GURL main_url(embedded_test_server()->GetURL( - "a.com", "/cross_site_iframe_factory.html?a(b(c(),d(b())),e(e,e()))")); - - auto waiter = CreatePageLoadMetricsTestWaiter(); - ui_test_utils::NavigateToURL(browser(), main_url); - - // One favicon resource and 2 resources for each frame. - waiter->AddMinimumCompleteResourcesExpectation(17); - waiter->Wait(); - - // Navigate away to force the histogram recording. - ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL)); - - // Verify that iframe e is only same origin. - histogram_tester.ExpectBucketCount( - "PageLoad.Clients.Ads.Bytes.AdFrames.PerFrame.PercentSameOrigin2", 100, - 1); - - // Verify that iframe b counts subframes as cross origin and a nested same - // origin subframe as same origin. - histogram_tester.ExpectBucketCount( - "PageLoad.Clients.Ads.Bytes.AdFrames.PerFrame.PercentSameOrigin2", 50, 1); - - // Verify that all iframe are treated as cross-origin to the page. Only 1/8 of - // resources are on origin a.com. - histogram_tester.ExpectBucketCount( - "PageLoad.Clients.Ads.Bytes.FullPage.PercentSameOrigin2", 12.5, 1); -} - -IN_PROC_BROWSER_TEST_F(AdsPageLoadMetricsObserverBrowserTest, AdFrameRecordMediaStatusNotPlayed) { SetRulesetWithRules( {subresource_filter::testing::CreateSuffixRule("pixel.png")});
diff --git a/chrome/browser/page_load_metrics/observers/ad_metrics/frame_data.cc b/chrome/browser/page_load_metrics/observers/ad_metrics/frame_data.cc index 80c3f35..7dcdc33 100644 --- a/chrome/browser/page_load_metrics/observers/ad_metrics/frame_data.cc +++ b/chrome/browser/page_load_metrics/observers/ad_metrics/frame_data.cc
@@ -69,7 +69,6 @@ : root_frame_tree_node_id_(root_frame_tree_node_id), bytes_(0u), network_bytes_(0u), - same_origin_bytes_(0u), origin_status_(OriginStatus::kUnknown), creative_origin_status_(OriginStatus::kUnknown), frame_navigated_(false), @@ -111,11 +110,8 @@ const page_load_metrics::mojom::ResourceDataUpdatePtr& resource, int process_id, const page_load_metrics::ResourceTracker& resource_tracker) { - bool is_same_origin = origin_.IsSameOriginWith(resource->origin); bytes_ += resource->delta_bytes; network_bytes_ += resource->delta_bytes; - if (is_same_origin) - same_origin_bytes_ += resource->delta_bytes; content::GlobalRequestID global_id(process_id, resource->request_id); if (!resource_tracker.HasPreviousUpdateForResource(global_id)) @@ -125,8 +121,6 @@ if (resource->is_complete && resource->cache_type != page_load_metrics::mojom::CacheType::kNotCached) { bytes_ += resource->encoded_body_length; - if (is_same_origin) - same_origin_bytes_ += resource->encoded_body_length; } if (resource->reported_as_ad_resource) {
diff --git a/chrome/browser/page_load_metrics/observers/ad_metrics/frame_data.h b/chrome/browser/page_load_metrics/observers/ad_metrics/frame_data.h index 8593f50..f1a8c3c 100644 --- a/chrome/browser/page_load_metrics/observers/ad_metrics/frame_data.h +++ b/chrome/browser/page_load_metrics/observers/ad_metrics/frame_data.h
@@ -243,8 +243,6 @@ size_t network_bytes() const { return network_bytes_; } - size_t same_origin_bytes() const { return same_origin_bytes_; } - size_t ad_bytes() const { return ad_bytes_; } size_t ad_network_bytes() const { return ad_network_bytes_; } @@ -362,8 +360,6 @@ size_t ad_bytes_ = 0u; size_t ad_network_bytes_ = 0u; - // The number of bytes that are same origin to the root ad frame. - size_t same_origin_bytes_; OriginStatus origin_status_; OriginStatus creative_origin_status_; bool frame_navigated_;
diff --git a/chrome/browser/payments/load_and_remove_iframe_with_many_payment_requests_browsertest.cc b/chrome/browser/payments/load_and_remove_iframe_with_many_payment_requests_browsertest.cc index f170cea..b0c7d4f 100644 --- a/chrome/browser/payments/load_and_remove_iframe_with_many_payment_requests_browsertest.cc +++ b/chrome/browser/payments/load_and_remove_iframe_with_many_payment_requests_browsertest.cc
@@ -2,8 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "build/build_config.h" +#include "base/test/scoped_feature_list.h" #include "chrome/test/payments/payment_request_platform_browsertest_base.h" +#include "components/payments/core/features.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" #include "testing/gtest/include/gtest/gtest.h" @@ -11,18 +12,21 @@ namespace payments { namespace { -// TODO(crbug.com/1129573): fix flakiness and reenable -#if defined(OS_MAC) -#define MAYBE_LoadAndRemoveIframeWithManyPaymentRequestsTest \ - DISABLED_LoadAndRemoveIframeWithManyPaymentRequestsTest -#else -#define MAYBE_LoadAndRemoveIframeWithManyPaymentRequestsTest \ - LoadAndRemoveIframeWithManyPaymentRequestsTest -#endif - -class MAYBE_LoadAndRemoveIframeWithManyPaymentRequestsTest +class LoadAndRemoveIframeWithManyPaymentRequestsTest : public PaymentRequestPlatformBrowserTestBase { public: + LoadAndRemoveIframeWithManyPaymentRequestsTest() { + // Enable the browser-side feature flag as it's disabled by default on + // non-origin trial platforms. + feature_list_.InitAndEnableFeature(features::kSecurePaymentConfirmation); + } + + void SetUpCommandLine(base::CommandLine* command_line) override { + PaymentRequestPlatformBrowserTestBase::SetUpCommandLine(command_line); + command_line->AppendSwitch( + switches::kEnableExperimentalWebPlatformFeatures); + } + void RunTest(const std::string& iframe_hostname) { NavigateTo("a.com", "/load_and_remove_iframe.html"); @@ -36,14 +40,16 @@ "/create_many_requests.html") .spec()))); } + + base::test::ScopedFeatureList feature_list_; }; -IN_PROC_BROWSER_TEST_F(MAYBE_LoadAndRemoveIframeWithManyPaymentRequestsTest, +IN_PROC_BROWSER_TEST_F(LoadAndRemoveIframeWithManyPaymentRequestsTest, CrossOriginNoCrash) { RunTest(/*iframe_hostname=*/"b.com"); } -IN_PROC_BROWSER_TEST_F(MAYBE_LoadAndRemoveIframeWithManyPaymentRequestsTest, +IN_PROC_BROWSER_TEST_F(LoadAndRemoveIframeWithManyPaymentRequestsTest, SameOriginNoCrash) { RunTest(/*iframe_hostname=*/"a.com"); }
diff --git a/chrome/browser/previews/defer_all_script_browsertest.cc b/chrome/browser/previews/defer_all_script_browsertest.cc index 5e9a1a4e..6f26e522 100644 --- a/chrome/browser/previews/defer_all_script_browsertest.cc +++ b/chrome/browser/previews/defer_all_script_browsertest.cc
@@ -242,6 +242,14 @@ entry, UkmDeferEntry::kforce_deferred_scripts_mainframeName, 2); test_ukm_recorder.ExpectEntryMetric( entry, UkmDeferEntry::kforce_deferred_scripts_mainframe_externalName, 1); + + // Opt out of the Preview page. + PreviewsUITabHelper::FromWebContents( + browser()->tab_strip_model()->GetActiveWebContents()) + ->ReloadWithoutPreviews(); + + histogram_tester.ExpectBucketCount( + "Previews.OptOut.UserOptedOut.DeferAllScript", 1, 1); } // Test with an incognito browser.
diff --git a/chrome/browser/previews/previews_browsertest.cc b/chrome/browser/previews/previews_browsertest.cc index f5a4e80..43b97e5 100644 --- a/chrome/browser/previews/previews_browsertest.cc +++ b/chrome/browser/previews/previews_browsertest.cc
@@ -263,63 +263,8 @@ PreviewsNoScriptBrowserTest, ::testing::Bool()); -// Loads a webpage that has both script and noscript tags and also requests -// a script resource. Verifies that the noscript tag is evaluated and the -// script resource is not loaded. -IN_PROC_BROWSER_TEST_P( - PreviewsNoScriptBrowserTest, - DISABLE_ON_WIN_MAC_CHROMEOS_LINUX(NoScriptPreviewsEnabled)) { - GURL url = https_url(); - // Whitelist NoScript for https_hint_setup_url()'s' host. - SetUpNoScriptWhitelist(https_hint_setup_url()); - base::HistogramTester histogram_tester; - ui_test_utils::NavigateToURL(browser(), url); - - // Verify loaded noscript tag triggered css resource but not js one. - EXPECT_TRUE(noscript_css_requested()); - EXPECT_FALSE(noscript_js_requested()); - - // Verify info bar presented via histogram check. - RetryForHistogramUntilCountReached(&histogram_tester, - "Previews.PreviewShown.NoScript", 1); -} - -IN_PROC_BROWSER_TEST_P( - PreviewsNoScriptBrowserTest, - DISABLE_ON_WIN_MAC_CHROMEOS(NoScriptPreviewsEnabled_Incognito)) { - GURL url = https_url(); - - // Whitelist NoScript for https_hint_setup_url()'s' host. - SetUpNoScriptWhitelist(https_hint_setup_url()); - - base::HistogramTester histogram_tester; - Browser* incognito = CreateIncognitoBrowser(); - ASSERT_FALSE(PreviewsServiceFactory::GetForProfile(incognito->profile())); - ASSERT_TRUE(PreviewsServiceFactory::GetForProfile(browser()->profile())); - - ui_test_utils::NavigateToURL(incognito, url); - - // Verify JS was loaded indicating that NoScript preview was not triggered. - EXPECT_FALSE(noscript_css_requested()); - EXPECT_TRUE(noscript_js_requested()); -} - -IN_PROC_BROWSER_TEST_P( - PreviewsNoScriptBrowserTest, - DISABLE_ON_WIN_MAC_CHROMEOS_LINUX(NoScriptPreviewsForHttp)) { - GURL url = http_url(); - - // Whitelist NoScript for http_hint_setup_url() host. - SetUpNoScriptWhitelist(http_hint_setup_url()); - - ui_test_utils::NavigateToURL(browser(), url); - - // Verify loaded noscript tag triggered css resource but not js one. - EXPECT_TRUE(noscript_css_requested()); - EXPECT_FALSE(noscript_js_requested()); -} IN_PROC_BROWSER_TEST_P(PreviewsNoScriptBrowserTest, DISABLE_ON_WIN_MAC_CHROMEOS( @@ -340,67 +285,7 @@ "Previews.CacheControlNoTransform.BlockedPreview", 5 /* NoScript */, 1); } -IN_PROC_BROWSER_TEST_P(PreviewsNoScriptBrowserTest, - DISABLE_ON_WIN_MAC_CHROMEOS_LINUX( - NoScriptPreviewsEnabledHttpRedirectToHttps)) { - GURL url = redirect_url(); - // Whitelist NoScript for http_hint_setup_url() host. - SetUpNoScriptWhitelist(http_hint_setup_url()); - - base::HistogramTester histogram_tester; - ui_test_utils::NavigateToURL(browser(), url); - - // Verify loaded noscript tag triggered css resource but not js one. - EXPECT_TRUE(noscript_css_requested()); - EXPECT_FALSE(noscript_js_requested()); - - // Verify info bar presented via histogram check. - RetryForHistogramUntilCountReached(&histogram_tester, - "Previews.PreviewShown.NoScript", 1); -} - -IN_PROC_BROWSER_TEST_P( - PreviewsNoScriptBrowserTest, - DISABLE_ON_WIN_MAC_CHROMEOS_LINUX(NoScriptPreviewsRecordsOptOut)) { - GURL url = redirect_url(); - - // Whitelist NoScript for http_hint_setup_url()'s' host. - SetUpNoScriptWhitelist(http_hint_setup_url()); - - base::HistogramTester histogram_tester; - - // Navigate to a NoScript Preview page. - ui_test_utils::NavigateToURL(browser(), url); - - // Terminate the previous page (non-opt out) and pull up a new NoScript page. - ui_test_utils::NavigateToURL(browser(), url); - histogram_tester.ExpectUniqueSample("Previews.OptOut.UserOptedOut.NoScript", - 0, 1); - - // Opt out of the NoScript Preview page. - PreviewsUITabHelper::FromWebContents( - browser()->tab_strip_model()->GetActiveWebContents()) - ->ReloadWithoutPreviews(); - - histogram_tester.ExpectBucketCount("Previews.OptOut.UserOptedOut.NoScript", 1, - 1); -} - -IN_PROC_BROWSER_TEST_P( - PreviewsNoScriptBrowserTest, - DISABLE_ON_WIN_MAC_CHROMEOS_LINUX(NoScriptPreviewsEnabledByWhitelist)) { - GURL url = https_url(); - - // Whitelist NoScript for https_hint_setup_url()'s' host. - SetUpNoScriptWhitelist(https_hint_setup_url()); - - ui_test_utils::NavigateToURL(browser(), url); - - // Verify loaded noscript tag triggered css resource but not js one. - EXPECT_TRUE(noscript_css_requested()); - EXPECT_FALSE(noscript_js_requested()); -} IN_PROC_BROWSER_TEST_P( PreviewsNoScriptBrowserTest,
diff --git a/chrome/browser/previews/previews_test_util.h b/chrome/browser/previews/previews_test_util.h index 85052f11..fd272cf6 100644 --- a/chrome/browser/previews/previews_test_util.h +++ b/chrome/browser/previews/previews_test_util.h
@@ -42,14 +42,4 @@ #define DISABLE_ON_WIN_MAC_CHROMEOS(x) x #endif -// Previews InfoBar (which these tests trigger) does not work on Mac. -// See https://crbug.com/782322 for details. Also occasional flakes on win7 -// (https://crbug.com/789542) and linux (https://crbug.com/1095566). -#if defined(OS_WIN) || defined(OS_MAC) || defined(OS_CHROMEOS) || \ - defined(OS_LINUX) -#define DISABLE_ON_WIN_MAC_CHROMEOS_LINUX(x) DISABLED_##x -#else -#define DISABLE_ON_WIN_MAC_CHROMEOS_LINUX(x) x -#endif - #endif // CHROME_BROWSER_PREVIEWS_PREVIEWS_TEST_UTIL_H_
diff --git a/chrome/browser/resources/optimize_webui.py b/chrome/browser/resources/optimize_webui.py index 00da924..ced44401 100755 --- a/chrome/browser/resources/optimize_webui.py +++ b/chrome/browser/resources/optimize_webui.py
@@ -359,7 +359,7 @@ # Pass the JS files through Uglify and write the output to its final # destination. for index, js_out_file in enumerate(args.js_out_files): - node.RunNode([node_modules.PathToUglify(), + node.RunNode([node_modules.PathToTerser(), os.path.join(tmp_out_dir, js_out_file), '--comments', '/Copyright|license|LICENSE|\<\/?if/', '--output', os.path.join(out_path, js_out_file)])
diff --git a/chrome/browser/ui/ash/holding_space/holding_space_util.cc b/chrome/browser/ui/ash/holding_space/holding_space_util.cc index fa97c04d..1d03b4d 100644 --- a/chrome/browser/ui/ash/holding_space/holding_space_util.cc +++ b/chrome/browser/ui/ash/holding_space/holding_space_util.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/ui/ash/holding_space/holding_space_util.h" #include "ash/public/cpp/file_icon_util.h" +#include "ash/public/cpp/holding_space/holding_space_color_provider.h" #include "ash/public/cpp/holding_space/holding_space_constants.h" #include "ash/public/cpp/holding_space/holding_space_image.h" #include "base/barrier_closure.h" @@ -39,12 +40,15 @@ break; } + const SkColor color = HoldingSpaceColorProvider::Get()->GetFileIconColor(); + // NOTE: We superimpose the file type icon for `file_path` over a transparent // bitmap in order to center it within the placeholder image at a fixed size. SkBitmap bitmap; bitmap.allocN32Pixels(size.width(), size.height()); return gfx::ImageSkiaOperations::CreateSuperimposedImage( - gfx::ImageSkia::CreateFrom1xBitmap(bitmap), GetIconForPath(file_path)); + gfx::ImageSkia::CreateFrom1xBitmap(bitmap), + GetIconForPath(file_path, color)); } } // namespace
diff --git a/chrome/browser/ui/cocoa/task_manager_mac.mm b/chrome/browser/ui/cocoa/task_manager_mac.mm index b9d67711..f8824ce 100644 --- a/chrome/browser/ui/cocoa/task_manager_mac.mm +++ b/chrome/browser/ui/cocoa/task_manager_mac.mm
@@ -287,9 +287,12 @@ [[NSTableView alloc] initWithFrame:NSMakeRect(0, 0, 400, 200)]); [tableView setAllowsColumnReordering:NO]; [tableView setAllowsMultipleSelection:YES]; + // No autosaving, since column identifiers are IDS_ values which are not + // stable. TODO(avi): Would it be worth it to find stable identifiers so that + // we could use autosaving? [tableView setAutosaveTableColumns:NO]; [tableView - setColumnAutoresizingStyle:NSTableViewSequentialColumnAutoresizingStyle]; + setColumnAutoresizingStyle:NSTableViewUniformColumnAutoresizingStyle]; [tableView setDoubleAction:@selector(tableWasDoubleClicked:)]; [tableView setFocusRingType:NSFocusRingTypeNone]; [tableView setIntercellSpacing:NSMakeSize(0, 0)]; @@ -308,14 +311,17 @@ base::scoped_nsobject<NSTableColumn> column([[NSTableColumn alloc] initWithIdentifier:ColumnIdentifier(columnData.id)]); + NSTableHeaderCell* headerCell = [column.get() headerCell]; + id dataCell = [column.get() dataCell]; + NSTextAlignment textAlignment = (columnData.align == ui::TableColumn::LEFT) ? NSLeftTextAlignment : NSRightTextAlignment; - [[column.get() headerCell] - setStringValue:l10n_util::GetNSStringWithFixup(columnData.id)]; - [[column.get() headerCell] setAlignment:textAlignment]; - [[column.get() dataCell] setAlignment:textAlignment]; + NSString* columnTitle = l10n_util::GetNSStringWithFixup(columnData.id); + [headerCell setStringValue:columnTitle]; + [headerCell setAlignment:textAlignment]; + [dataCell setAlignment:textAlignment]; const CGFloat smallSystemFontSize = [NSFont smallSystemFontSize]; NSFont* font = nil; @@ -325,7 +331,7 @@ } else { font = [NSFont systemFontOfSize:smallSystemFontSize]; } - [[column.get() dataCell] setFont:font]; + [dataCell setFont:font]; [column.get() setHidden:!columnData.default_visibility]; [column.get() setEditable:NO]; @@ -337,8 +343,20 @@ [column.get() setSortDescriptorPrototype:sortDescriptor.get()]; [column.get() setMinWidth:columnData.min_width]; - if (columnData.max_width > 0) - [column.get() setMaxWidth:columnData.max_width]; + // If there is no specified max width, use a reasonable value of 1.5x the min + // width, but make sure that the max width is big enough to actually show the + // entire column title. + const int kTitleMargin = 40; // Space for the arrow, etc. + int maxWidth = columnData.max_width; + if (maxWidth <= 0) + maxWidth = 3 * columnData.min_width / 2; + int columnTitleWidth = + [columnTitle + sizeWithAttributes:@{NSFontAttributeName : [headerCell font]}] + .width + + kTitleMargin; + maxWidth = std::max(maxWidth, columnTitleWidth); + [column.get() setMaxWidth:maxWidth]; [column.get() setResizingMask:NSTableColumnAutoresizingMask | NSTableColumnUserResizingMask];
diff --git a/chrome/browser/ui/exclusive_access/flash_fullscreen_interactive_browsertest.cc b/chrome/browser/ui/exclusive_access/flash_fullscreen_interactive_browsertest.cc deleted file mode 100644 index 19513680..0000000 --- a/chrome/browser/ui/exclusive_access/flash_fullscreen_interactive_browsertest.cc +++ /dev/null
@@ -1,423 +0,0 @@ -// Copyright 2014 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/bind.h" -#include "base/bind_helpers.h" -#include "base/location.h" -#include "base/macros.h" -#include "base/run_loop.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" -#include "base/time/time.h" -#include "build/build_config.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/test/base/interactive_test_utils.h" -#include "chrome/test/base/ui_test_utils.h" -#include "chrome/test/ppapi/ppapi_test.h" -#include "content/public/browser/render_process_host.h" -#include "content/public/browser/render_widget_host.h" -#include "content/public/browser/render_widget_host_view.h" -#include "content/public/browser/web_contents.h" -#include "content/public/test/browser_test.h" -#include "content/public/test/browser_test_utils.h" -#include "content/public/test/test_utils.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "third_party/skia/include/core/SkColor.h" - -namespace { - -#if defined(OS_MAC) -const bool kIsMacUI = true; -#else -const bool kIsMacUI = false; -#endif - -// Runs the current MessageLoop until |condition| is true or timeout. -bool RunLoopUntil(const base::Callback<bool()>& condition) { - const base::TimeTicks start_time = base::TimeTicks::Now(); - while (!condition.Run()) { - const base::TimeTicks current_time = base::TimeTicks::Now(); - if (current_time - start_time > base::TimeDelta::FromSeconds(10)) { - ADD_FAILURE() << "Condition not met within ten seconds."; - return false; - } - - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(), - base::TimeDelta::FromMilliseconds(20)); - content::RunMessageLoop(); - } - return true; -} - -} // namespace - -// A BrowserTest that opens a test page that launches a simulated fullscreen -// Flash plugin. The plugin responds to mouse clicks and key presses by -// changing color. Once launched, the browser UI can be tested to confirm the -// desired interactive behaviors. -class FlashFullscreenInteractiveBrowserTest : public OutOfProcessPPAPITest { - public: - FlashFullscreenInteractiveBrowserTest() {} - ~FlashFullscreenInteractiveBrowserTest() override {} - - protected: - content::WebContents* GetActiveWebContents() const { - return browser()->tab_strip_model()->GetActiveWebContents(); - } - - // A simple way to convince libcontent and the browser UI that a tab is being - // screen captured. During tab capture, Flash fullscreen remains embedded - // within the tab content area of a non-fullscreened browser window. - void StartFakingTabCapture() { - GetActiveWebContents()->IncrementCapturerCount(gfx::Size(360, 240), - /* stay_hidden */ false); - } - - bool LaunchFlashFullscreen() { - // This navigates to a page that runs the simulated fullscreen Flash - // plugin. It will block until the plugin has completed an attempt to enter - // Flash fullscreen mode. - OutOfProcessPPAPITest::RunTest("FlashFullscreenForBrowserUI"); - - if (::testing::Test::HasFailure()) { - ADD_FAILURE() << ("Failed to launch simulated fullscreen Flash plugin. " - "Interactive UI testing cannot proceed."); - return false; - } - - EXPECT_TRUE(ObserveTabIsInFullscreen(true)); - - return !::testing::Test::HasFailure(); - } - - bool LaunchFlashFullscreenInSubframe() { - // Load a page with an <iframe> that points to the test case URL, which - // runs the simulated fullscreen Flash plugin. In OOPIF modes, the frame - // will render in a separate process. Block until the plugin has completed - // an attempt to enter Flash fullscreen mode. - GURL test_url = GetTestURL(*embedded_test_server(), - "FlashFullscreenForBrowserUI", std::string()); - GURL main_url("data:text/html,<iframe src='" + test_url.spec() + - "'></iframe>"); - OutOfProcessPPAPITest::RunTestURL(main_url); - - if (::testing::Test::HasFailure()) { - ADD_FAILURE() << ("Failed to launch simulated fullscreen Flash plugin. " - "Interactive UI testing cannot proceed."); - return false; - } - - EXPECT_TRUE(ObserveTabIsInFullscreen(true)); - - return !::testing::Test::HasFailure(); - } - - void UseAcceleratorToOpenNewTab() { - content::WebContents* const old_tab_contents = GetActiveWebContents(); - EXPECT_TRUE(ui_test_utils::SendKeyPressSync( - browser(), ui::VKEY_T, !kIsMacUI, false, false, kIsMacUI)); - EXPECT_TRUE(RunLoopUntil(base::Bind( - &FlashFullscreenInteractiveBrowserTest::IsObservingActiveWebContents, - base::Unretained(this), - old_tab_contents, - false))); - } - - void UseAcceleratorToSwitchToTab(int tab_index) { - content::WebContents* const old_tab_contents = GetActiveWebContents(); - const ui::KeyboardCode key_code = - static_cast<ui::KeyboardCode>(ui::VKEY_1 + tab_index); - EXPECT_TRUE(ui_test_utils::SendKeyPressSync( - browser(), key_code, !kIsMacUI, false, false, kIsMacUI)); - EXPECT_TRUE(RunLoopUntil(base::Bind( - &FlashFullscreenInteractiveBrowserTest::IsObservingActiveWebContents, - base::Unretained(this), - old_tab_contents, - false))); - } - - void PressEscape() { - EXPECT_TRUE(ui_test_utils::SendKeyPressSync( - browser(), ui::VKEY_ESCAPE, false, false, false, false)); - } - - void PressSpacebar() { - EXPECT_TRUE(ui_test_utils::SendKeyPressSync( - browser(), ui::VKEY_SPACE, false, false, false, false)); - } - - void SpamSpacebar() { - for (int i = 0; i < 11; ++i) - PressSpacebar(); - } - - void ClickOnTabContainer() { - ui_test_utils::ClickOnView(browser(), VIEW_ID_TAB_CONTAINER); - } - - void ClickOnOmnibox() { - ui_test_utils::ClickOnView(browser(), VIEW_ID_OMNIBOX); - } - - bool ObserveTabIsInFullscreen(bool expected_in_fullscreen) const { - if (!RunLoopUntil(base::Bind( - &FlashFullscreenInteractiveBrowserTest::IsObservingTabInFullscreen, - base::Unretained(this), - GetActiveWebContents(), - expected_in_fullscreen))) - return false; - - if (expected_in_fullscreen) { - if (!GetActiveWebContents()->GetFullscreenRenderWidgetHostView()) { - ADD_FAILURE() - << "WebContents should have a fullscreen RenderWidgetHostView."; - return false; - } - EXPECT_EQ(GetActiveWebContents()->IsBeingCaptured(), - !browser() - ->exclusive_access_manager() - ->fullscreen_controller() - ->IsWindowFullscreenForTabOrPending()); - } - - return true; - } - - bool ObserveFlashHasFocus(content::WebContents* contents, - bool expected_to_have_focus) const { - if (!RunLoopUntil(base::Bind( - &FlashFullscreenInteractiveBrowserTest::IsObservingFlashHasFocus, - base::Unretained(this), - contents, - expected_to_have_focus))) - return false; - - if (expected_to_have_focus) { - content::RenderWidgetHostView* const web_page_view = - contents->GetRenderWidgetHostView(); - EXPECT_FALSE(web_page_view && web_page_view->HasFocus()) - << "Both RenderWidgetHostViews cannot have focus at the same time."; - - if (contents == GetActiveWebContents()) - EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), - VIEW_ID_TAB_CONTAINER)); - } - - return true; - } - - bool ObserveFlashFillColor(SkColor expected_color) const { - return RunLoopUntil(base::Bind( - &FlashFullscreenInteractiveBrowserTest::IsObservingFlashFillColor, - base::Unretained(this), - expected_color)); - } - - private: - bool IsObservingTabInFullscreen(content::WebContents* contents, - bool expected_in_fullscreen) const { - return expected_in_fullscreen == - browser() - ->exclusive_access_manager() - ->fullscreen_controller() - ->IsFullscreenForTabOrPending(contents); - } - - bool IsObservingFlashHasFocus(content::WebContents* contents, - bool expected_to_have_focus) const { - content::RenderWidgetHostView* const flash_fs_view = - contents->GetFullscreenRenderWidgetHostView(); - const bool flash_has_focus = flash_fs_view && flash_fs_view->HasFocus(); - return flash_has_focus == expected_to_have_focus; - } - - bool IsObservingActiveWebContents(content::WebContents* contents, - bool expected_active_contents) const { - return (contents == GetActiveWebContents()) == expected_active_contents; - } - - bool IsObservingFlashFillColor(SkColor expected_color) const { - content::RenderWidgetHostView* const flash_fs_view = - GetActiveWebContents()->GetFullscreenRenderWidgetHostView(); - if (!flash_fs_view) { - ADD_FAILURE() << "Flash fullscreen RenderWidgetHostView is gone."; - return false; - } - - // When a widget is first shown, it can take some time before it is ready - // for copying from its backing store. This is a transient condition, and - // so it is not being treated as a test failure. - if (!flash_fs_view->IsSurfaceAvailableForCopy()) - return false; - - // Copy and examine the upper-left pixel of the widget and compare it to the - // |expected_color|. - bool is_expected_color = false; - base::RunLoop run_loop; - flash_fs_view->CopyFromSurface( - gfx::Rect(0, 0, 1, 1), gfx::Size(1, 1), - base::BindOnce( - &FlashFullscreenInteractiveBrowserTest::CheckBitmapForFillColor, - expected_color, &is_expected_color, run_loop.QuitClosure())); - run_loop.Run(); - - return is_expected_color; - } - - static void CheckBitmapForFillColor(SkColor expected_color, - bool* is_expected_color, - const base::Closure& done_cb, - const SkBitmap& bitmap) { - if (!bitmap.drawsNothing()) - *is_expected_color = (bitmap.getColor(0, 0) == expected_color); - done_cb.Run(); - } - - DISALLOW_COPY_AND_ASSIGN(FlashFullscreenInteractiveBrowserTest); -}; - -// Tests that launching and exiting fullscreen-within-tab works. -IN_PROC_BROWSER_TEST_F(FlashFullscreenInteractiveBrowserTest, - FullscreenWithinTab_EscapeKeyExitsFullscreen) { - ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); - StartFakingTabCapture(); - ASSERT_TRUE(LaunchFlashFullscreen()); - content::WebContents* const first_tab_contents = GetActiveWebContents(); - EXPECT_TRUE(ObserveFlashHasFocus(first_tab_contents, true)); - PressEscape(); - EXPECT_TRUE(ObserveTabIsInFullscreen(false)); -} - -IN_PROC_BROWSER_TEST_F(FlashFullscreenInteractiveBrowserTest, - FullscreenFromSubframe) { - ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); - StartFakingTabCapture(); - ASSERT_TRUE(LaunchFlashFullscreenInSubframe()); - content::WebContents* const first_tab_contents = GetActiveWebContents(); - EXPECT_TRUE(ObserveFlashHasFocus(first_tab_contents, true)); - PressEscape(); - EXPECT_TRUE(ObserveTabIsInFullscreen(false)); -} - -// This tests that browser UI focus behavior is correct when switching between -// tabs; particularly, that that focus between the omnibox and tab contents is -// stored/restored correctly. Mouse and keyboard events are used to confirm -// that the widget the UI thinks is focused is the one that responds to these -// input events. -// -// Flaky, see http://crbug.com/444476 -IN_PROC_BROWSER_TEST_F(FlashFullscreenInteractiveBrowserTest, - DISABLED_FullscreenWithinTab_FocusWhenSwitchingTabs) { - ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); - StartFakingTabCapture(); - ASSERT_TRUE(LaunchFlashFullscreen()); - - // Upon entering fullscreen, the Flash widget should have focus and be filled - // with green. - content::WebContents* const first_tab_contents = GetActiveWebContents(); - EXPECT_TRUE(ObserveFlashHasFocus(first_tab_contents, true)); - ASSERT_TRUE(ObserveFlashFillColor(SK_ColorGREEN)); - - // Pressing the spacebar on the keyboard should change the fill color to red - // to indicate the plugin truly does have the keyboard focus. Clicking on the - // view should change the fill color to blue. - PressSpacebar(); - ASSERT_TRUE(ObserveFlashFillColor(SK_ColorRED)); - ClickOnTabContainer(); - ASSERT_TRUE(ObserveFlashFillColor(SK_ColorBLUE)); - - // Launch a new tab. The Flash widget should have lost focus. - UseAcceleratorToOpenNewTab(); - content::WebContents* const second_tab_contents = GetActiveWebContents(); - ASSERT_NE(first_tab_contents, second_tab_contents); - EXPECT_TRUE(ObserveFlashHasFocus(first_tab_contents, false)); - ClickOnOmnibox(); - EXPECT_TRUE(ObserveFlashHasFocus(first_tab_contents, false)); - SpamSpacebar(); - - // Switch back to first tab. The plugin should not have responded to the key - // presses above (while the omnibox was focused), and should regain focus only - // now. Poke it with key and mouse events to confirm. - UseAcceleratorToSwitchToTab(0); - EXPECT_TRUE(ObserveFlashHasFocus(first_tab_contents, true)); - ASSERT_TRUE(ObserveFlashFillColor(SK_ColorBLUE)); - PressSpacebar(); - ASSERT_TRUE(ObserveFlashFillColor(SK_ColorRED)); - ClickOnTabContainer(); - ASSERT_TRUE(ObserveFlashFillColor(SK_ColorBLUE)); - - // Click on the omnibox while still in the first tab, and the Flash widget - // should lose focus. Key presses should not affect the color of the Flash - // widget. - ClickOnOmnibox(); - EXPECT_TRUE(ObserveFlashHasFocus(first_tab_contents, false)); - ASSERT_TRUE(ObserveFlashFillColor(SK_ColorBLUE)); - SpamSpacebar(); - ASSERT_TRUE(ObserveFlashFillColor(SK_ColorBLUE)); - - // Switch to the second tab, click on the web page content, and then go back - // to the first tab. Focus should have been restored to the omnibox when - // going back to the first tab, and so key presses should not change the color - // of the Flash widget. - UseAcceleratorToSwitchToTab(1); - EXPECT_TRUE(ObserveFlashHasFocus(first_tab_contents, false)); - ClickOnTabContainer(); - EXPECT_TRUE(ObserveFlashHasFocus(first_tab_contents, false)); - UseAcceleratorToSwitchToTab(0); - EXPECT_TRUE(ObserveFlashHasFocus(first_tab_contents, false)); - ASSERT_TRUE(ObserveFlashFillColor(SK_ColorBLUE)); - SpamSpacebar(); - ASSERT_TRUE(ObserveFlashFillColor(SK_ColorBLUE)); - - // Clicking on the Flash widget should give it focus again. - ClickOnTabContainer(); - EXPECT_TRUE(ObserveFlashHasFocus(first_tab_contents, true)); - ASSERT_TRUE(ObserveFlashFillColor(SK_ColorRED)); - PressSpacebar(); - ASSERT_TRUE(ObserveFlashFillColor(SK_ColorBLUE)); - - // Test that the Escape key is handled as an exit fullscreen command while the - // Flash widget has the focus. - EXPECT_TRUE(ObserveFlashHasFocus(first_tab_contents, true)); - PressEscape(); - EXPECT_TRUE(ObserveTabIsInFullscreen(false)); -} - -// Tests that a fullscreen flash plugin can lock the mouse, and that it'll be -// unlocked when the plugin exits fullscreen. -// Flaky on Linux. See https://crbug.com/706148. -#if defined(OS_LINUX) || defined(OS_CHROMEOS) -#define MAYBE_Fullscreen_LockMouse DISABLED_Fullscreen_LockMouse -#else -#define MAYBE_Fullscreen_LockMouse Fullscreen_LockMouse -#endif -IN_PROC_BROWSER_TEST_F(FlashFullscreenInteractiveBrowserTest, - MAYBE_Fullscreen_LockMouse) { - ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); - StartFakingTabCapture(); - ASSERT_TRUE(LaunchFlashFullscreen()); - content::WebContents* web_contents = GetActiveWebContents(); - EXPECT_TRUE(ObserveFlashHasFocus(web_contents, true)); - - // Try to lock the mouse. - content::RenderWidgetHostView* fullscreen_view = - web_contents->GetFullscreenRenderWidgetHostView(); - content::RenderWidgetHost* fullscreen_widget = - fullscreen_view->GetRenderWidgetHost(); - content::RequestMouseLock(fullscreen_widget, /*from_user_gesture=*/true, - /*privileged=*/true, /*unadjusted_movement=*/false); - - // Make sure that the fullscreen widget got the mouse lock. - EXPECT_TRUE(fullscreen_view->IsMouseLocked()); - EXPECT_EQ(fullscreen_widget, content::GetMouseLockWidget(web_contents)); - - PressEscape(); - EXPECT_TRUE(ObserveTabIsInFullscreen(false)); - - // Mouse should be unlocked. - EXPECT_EQ(nullptr, content::GetMouseLockWidget(web_contents)); -}
diff --git a/chrome/browser/ui/hats/hats_service.cc b/chrome/browser/ui/hats/hats_service.cc index 76df263..79993c6 100644 --- a/chrome/browser/ui/hats/hats_service.cc +++ b/chrome/browser/ui/hats/hats_service.cc
@@ -62,6 +62,9 @@ constexpr base::TimeDelta kMinimumTimeBetweenSurveyStarts = base::TimeDelta::FromDays(60); +constexpr base::TimeDelta kMinimumTimeBetweenAnySurveyStarts = + base::TimeDelta::FromDays(7); + constexpr base::TimeDelta kMinimumTimeBetweenSurveyChecks = base::TimeDelta::FromDays(1); @@ -72,6 +75,9 @@ // The valid keys and value types for this dictionary are as follows: // [trigger].last_major_version ---> Integer // [trigger].last_survey_started_time ---> Time +// [trigger].is_survey_full ---> Bool +// [trigger].last_survey_check_time ---> Time +// any_last_survey_started_time ---> Time std::string GetMajorVersionPath(const std::string& trigger) { return trigger + ".last_major_version"; @@ -89,6 +95,8 @@ return trigger + ".last_survey_check_time"; } +constexpr char kAnyLastSurveyStartedTimePath[] = "any_last_survey_started_time"; + } // namespace HatsService::SurveyMetadata::SurveyMetadata() = default; @@ -214,6 +222,8 @@ version_info::GetVersion().components()[0]); pref_data->SetPath(GetLastSurveyStartedTime(trigger), util::TimeToValue(base::Time::Now())); + pref_data->SetPath(kAnyLastSurveyStartedTimePath, + util::TimeToValue(base::Time::Now())); } void HatsService::HatsNextDialogClosed() { @@ -246,6 +256,14 @@ pref_data->RemovePath(GetLastSurveyStartedTime(trigger)); } + if (metadata.any_last_survey_started_time.has_value()) { + pref_data->SetPath( + kAnyLastSurveyStartedTimePath, + util::TimeToValue(*metadata.any_last_survey_started_time)); + } else { + pref_data->RemovePath(kAnyLastSurveyStartedTimePath); + } + if (metadata.is_survey_full.has_value()) { pref_data->SetBoolPath(GetIsSurveyFull(trigger), *metadata.is_survey_full); } else { @@ -276,6 +294,11 @@ if (last_survey_started_time.has_value()) metadata->last_survey_started_time = last_survey_started_time; + base::Optional<base::Time> any_last_survey_started_time = + util::ValueToTime(pref_data->FindPath(kAnyLastSurveyStartedTimePath)); + if (any_last_survey_started_time.has_value()) + metadata->any_last_survey_started_time = any_last_survey_started_time; + base::Optional<bool> is_survey_full = pref_data->FindBoolPath(GetIsSurveyFull(trigger)); if (is_survey_full.has_value()) @@ -409,6 +432,21 @@ } } + // The time any survey was started will always be equal or more recent than + // the time a particular survey was started, so it is checked afterwards to + // improve UMA logging. + base::Optional<base::Time> last_any_started_time = + util::ValueToTime(pref_data->FindPath(kAnyLastSurveyStartedTimePath)); + if (last_any_started_time.has_value()) { + base::TimeDelta elapsed_time_any_started = now - *last_any_started_time; + if (elapsed_time_any_started < kMinimumTimeBetweenAnySurveyStarts) { + UMA_HISTOGRAM_ENUMERATION( + kHatsShouldShowSurveyReasonHistogram, + ShouldShowSurveyReasons::kNoAnyLastSurveyTooRecent); + return false; + } + } + auto probability_ = survey_configs_by_triggers_.at(trigger).probability_; bool should_show_survey = base::RandDouble() < probability_; if (!should_show_survey) {
diff --git a/chrome/browser/ui/hats/hats_service.h b/chrome/browser/ui/hats/hats_service.h index 8cdfc72..bae175c 100644 --- a/chrome/browser/ui/hats/hats_service.h +++ b/chrome/browser/ui/hats/hats_service.h
@@ -62,10 +62,14 @@ SurveyMetadata(); ~SurveyMetadata(); + // Trigger specific metadata. base::Optional<int> last_major_version; base::Optional<base::Time> last_survey_started_time; base::Optional<bool> is_survey_full; base::Optional<base::Time> last_survey_check_time; + + // Metadata affecting all triggers. + base::Optional<base::Time> any_last_survey_started_time; }; class DelayedSurveyTask : public content::WebContentsObserver { @@ -119,7 +123,8 @@ kNoSurveyUnreachable = 12, kNoSurveyOverCapacity = 13, kNoSurveyAlreadyInProgress = 14, - kMaxValue = kNoSurveyAlreadyInProgress, + kNoAnyLastSurveyTooRecent = 15, + kMaxValue = kNoAnyLastSurveyTooRecent, }; ~HatsService() override;
diff --git a/chrome/browser/ui/hats/hats_service_browsertest.cc b/chrome/browser/ui/hats/hats_service_browsertest.cc index 89176da8..b0a192d3 100644 --- a/chrome/browser/ui/hats/hats_service_browsertest.cc +++ b/chrome/browser/ui/hats/hats_service_browsertest.cc
@@ -8,6 +8,7 @@ #include "base/metrics/user_metrics.h" #include "base/optional.h" #include "base/run_loop.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" @@ -311,6 +312,20 @@ EXPECT_FALSE(HatsBubbleShown()); } +IN_PROC_BROWSER_TEST_F(HatsServiceProbabilityOne, + SurveyStartedBeforeElapsedTimeBetweenAnySurveys) { + SetMetricsConsent(true); + base::HistogramTester histogram_tester; + HatsService::SurveyMetadata metadata; + metadata.any_last_survey_started_time = base::Time::Now(); + GetHatsService()->SetSurveyMetadataForTesting(metadata); + GetHatsService()->LaunchSurvey(kHatsSurveyTriggerSatisfaction); + EXPECT_FALSE(HatsBubbleShown()); + histogram_tester.ExpectUniqueSample( + kHatsShouldShowSurveyReasonHistogram, + HatsService::ShouldShowSurveyReasons::kNoAnyLastSurveyTooRecent, 1); +} + IN_PROC_BROWSER_TEST_F(HatsServiceProbabilityOne, ProfileTooYoungToShow) { SetMetricsConsent(true); // Set creation time to only 15 days.
diff --git a/chrome/browser/ui/managed_ui.cc b/chrome/browser/ui/managed_ui.cc index 5c803f9..bdbb289d 100644 --- a/chrome/browser/ui/managed_ui.cc +++ b/chrome/browser/ui/managed_ui.cc
@@ -12,7 +12,10 @@ #include "ui/base/l10n/l10n_util.h" #if defined(OS_CHROMEOS) +#include "chrome/browser/browser_process.h" +#include "chrome/browser/browser_process_platform_part.h" #include "chrome/browser/chromeos/login/demo_mode/demo_session.h" +#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" #include "ui/chromeos/devicetype_utils.h" #endif @@ -33,48 +36,50 @@ } base::string16 GetManagedUiMenuItemLabel(Profile* profile) { - std::string management_domain = - ManagementUIHandler::GetAccountDomain(profile); + std::string account_manager = ManagementUIHandler::GetAccountManager(profile); int string_id = IDS_MANAGED; std::vector<base::string16> replacements; - if (!management_domain.empty()) { + if (!account_manager.empty()) { string_id = IDS_MANAGED_BY; - replacements.push_back(base::UTF8ToUTF16(management_domain)); + replacements.push_back(base::UTF8ToUTF16(account_manager)); } return l10n_util::GetStringFUTF16(string_id, replacements, nullptr); } base::string16 GetManagedUiWebUILabel(Profile* profile) { - std::string management_domain = - ManagementUIHandler::GetAccountDomain(profile); + std::string account_manager = ManagementUIHandler::GetAccountManager(profile); int string_id = IDS_MANAGED_WITH_HYPERLINK; std::vector<base::string16> replacements; replacements.push_back(base::UTF8ToUTF16(chrome::kChromeUIManagementURL)); - if (!management_domain.empty()) { + if (!account_manager.empty()) { string_id = IDS_MANAGED_BY_WITH_HYPERLINK; - replacements.push_back(base::UTF8ToUTF16(management_domain)); + replacements.push_back(base::UTF8ToUTF16(account_manager)); } return l10n_util::GetStringFUTF16(string_id, replacements, nullptr); } #if defined(OS_CHROMEOS) -base::string16 GetDeviceManagedUiWebUILabel(Profile* profile) { - std::string management_domain = - ManagementUIHandler::GetAccountDomain(profile); +base::string16 GetDeviceManagedUiWebUILabel() { + policy::BrowserPolicyConnectorChromeOS* connector = + g_browser_process->platform_part()->browser_policy_connector_chromeos(); + const std::string device_manager = + connector->IsActiveDirectoryManaged() + ? connector->GetRealm() + : connector->GetEnterpriseDomainManager(); int string_id = IDS_DEVICE_MANAGED_WITH_HYPERLINK; std::vector<base::string16> replacements; replacements.push_back(base::UTF8ToUTF16(chrome::kChromeUIManagementURL)); replacements.push_back(ui::GetChromeOSDeviceName()); - if (!management_domain.empty()) { + if (!device_manager.empty()) { string_id = IDS_DEVICE_MANAGED_BY_WITH_HYPERLINK; - replacements.push_back(base::UTF8ToUTF16(management_domain)); + replacements.push_back(base::UTF8ToUTF16(device_manager)); } return l10n_util::GetStringFUTF16(string_id, replacements, nullptr);
diff --git a/chrome/browser/ui/managed_ui.h b/chrome/browser/ui/managed_ui.h index 7943559..f4a85cbd 100644 --- a/chrome/browser/ui/managed_ui.h +++ b/chrome/browser/ui/managed_ui.h
@@ -33,7 +33,7 @@ #if defined(OS_CHROMEOS) // The label for the WebUI footnote for Managed UI indicating that the device // is mananged. These strings contain HTML for an <a> element. -base::string16 GetDeviceManagedUiWebUILabel(Profile* profile); +base::string16 GetDeviceManagedUiWebUILabel(); #endif } // namespace chrome
diff --git a/chrome/browser/ui/managed_ui_browsertest.cc b/chrome/browser/ui/managed_ui_browsertest.cc index 5b2a80b5..dd6e188a 100644 --- a/chrome/browser/ui/managed_ui_browsertest.cc +++ b/chrome/browser/ui/managed_ui_browsertest.cc
@@ -16,6 +16,10 @@ #include "content/public/test/browser_test.h" #include "testing/gmock/include/gmock/gmock.h" +#if defined(OS_CHROMEOS) +#include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h" +#endif + class ManagedUiTest : public InProcessBrowserTest { public: ManagedUiTest() = default; @@ -87,14 +91,14 @@ "Your <a href=\"chrome://management\">browser is managed</a> by " "example.com"), chrome::GetManagedUiWebUILabel(profile_with_domain.get())); +} + #if defined(OS_CHROMEOS) - EXPECT_EQ(base::ASCIIToUTF16("Your <a target=\"_blank\" " - "href=\"chrome://management\">Chrome device is " - "managed</a> by your organization"), - chrome::GetDeviceManagedUiWebUILabel(profile.get())); +using ManagedUiTestCros = policy::DevicePolicyCrosBrowserTest; +IN_PROC_BROWSER_TEST_F(ManagedUiTestCros, GetManagedUiWebUILabel) { EXPECT_EQ(base::ASCIIToUTF16("Your <a target=\"_blank\" " "href=\"chrome://management\">Chrome device is " "managed</a> by example.com"), - chrome::GetDeviceManagedUiWebUILabel(profile_with_domain.get())); -#endif + chrome::GetDeviceManagedUiWebUILabel()); } +#endif
diff --git a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc index 6c256b8..ac307fd5 100644 --- a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc +++ b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
@@ -67,7 +67,6 @@ #include "components/policy/core/common/mock_configuration_policy_provider.h" #include "components/policy/policy_constants.h" #include "components/prefs/pref_service.h" -#include "components/version_info/version_info.h" #include "content/public/browser/web_contents.h" #include "content/public/common/content_switches.h" #include "content/public/test/browser_test.h" @@ -1189,34 +1188,6 @@ #endif // !defined(OS_CHROMEOS) -#if defined(OS_WIN) -IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorTest, - PRE_ShortcutsAreMigratedOnce) { - content::RunAllTasksUntilIdle(); - - // Confirm that shortcuts were migrated. - const std::string last_version_migrated = - g_browser_process->local_state()->GetString( - prefs::kShortcutMigrationVersion); - EXPECT_EQ(last_version_migrated, version_info::GetVersionNumber()); - - // Set the version back as far as kLastVersionNeedingMigration and ensure it's - // not migrated again. - g_browser_process->local_state()->SetString(prefs::kShortcutMigrationVersion, - "86.0.4231.0"); -} -IN_PROC_BROWSER_TEST_F(StartupBrowserCreatorTest, ShortcutsAreMigratedOnce) { - content::RunAllTasksUntilIdle(); - - // Confirm that shortcuts weren't migrated when marked as having last been - // migrated in kLastVersionNeedingMigration+. - const std::string last_version_migrated = - g_browser_process->local_state()->GetString( - prefs::kShortcutMigrationVersion); - EXPECT_EQ(last_version_migrated, "86.0.4231.0"); -} -#endif // defined(OS_WIN) - class StartupBrowserCreatorExtensionsCheckupExperimentTest : public extensions::ExtensionBrowserTest { public:
diff --git a/chrome/browser/ui/startup/startup_browser_creator_impl.cc b/chrome/browser/ui/startup/startup_browser_creator_impl.cc index 393a018..87cd846 100644 --- a/chrome/browser/ui/startup/startup_browser_creator_impl.cc +++ b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
@@ -15,7 +15,6 @@ #include "base/bind.h" #include "base/command_line.h" #include "base/values.h" -#include "base/version.h" #include "build/branding_buildflags.h" #include "build/build_config.h" #include "chrome/browser/apps/app_service/app_service_proxy.h" @@ -59,7 +58,6 @@ #include "chrome/common/url_constants.h" #include "components/prefs/pref_service.h" #include "components/services/app_service/public/mojom/types.mojom.h" -#include "components/version_info/version_info.h" #include "content/public/browser/child_process_security_policy.h" #include "content/public/browser/dom_storage_context.h" #include "content/public/browser/storage_partition.h" @@ -79,7 +77,6 @@ #include "chrome/browser/win/conflicts/incompatible_applications_updater.h" #endif // BUILDFLAG(GOOGLE_CHROME_BRANDING) #include "chrome/browser/notifications/notification_platform_bridge_win.h" -#include "chrome/browser/shell_integration_win.h" #include "chrome/browser/ui/startup/credential_provider_signin_dialog_win.h" #include "chrome/credential_provider/common/gcp_strings.h" #endif // defined(OS_WIN) @@ -297,32 +294,6 @@ MaybeToggleFullscreen(browser); } -#if defined(OS_WIN) - if (process_startup) { - // Update this number when users should go through a taskbar shortcut - // migration again. The last reason to do this was crrev.com/2285399 @ - // 86.0.4231.0. - // - // Note: If shortcut updates need to be done once after a future OS upgrade, - // that should be done by re-versioning Active Setup (see //chrome/installer - // and http://crbug.com/577697 for details). - const base::Version kLastVersionNeedingMigration({86U, 0U, 4231U, 0U}); - - PrefService* local_state = g_browser_process->local_state(); - if (local_state) { - const base::Version last_version_migrated( - local_state->GetString(prefs::kShortcutMigrationVersion)); - if (!last_version_migrated.IsValid() || - last_version_migrated < kLastVersionNeedingMigration) { - shell_integration::win::MigrateTaskbarPins(base::BindOnce( - &PrefService::SetString, base::Unretained(local_state), - prefs::kShortcutMigrationVersion, - version_info::GetVersionNumber())); - } - } - } -#endif // defined(OS_WIN) - return true; }
diff --git a/chrome/browser/ui/task_manager/task_manager_columns.h b/chrome/browser/ui/task_manager/task_manager_columns.h index 30c5669..833a9091 100644 --- a/chrome/browser/ui/task_manager/task_manager_columns.h +++ b/chrome/browser/ui/task_manager/task_manager_columns.h
@@ -27,7 +27,7 @@ float percent; // min and max widths used for Mac's implementation and are ignored on Views. - // If |max_width| is -1, it is unset. + // If |max_width| is -1, a value of 1.5 * |min_width| will be used. int min_width; int max_width;
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc index fae120b..ff0d6eea 100644 --- a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc +++ b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc
@@ -1163,7 +1163,8 @@ } scroll_view_ = new views::ScrollView(); - scroll_view_->SetHideHorizontalScrollBar(true); + scroll_view_->SetHorizontalScrollBarMode( + views::ScrollView::ScrollBarMode::kDisabled); body_container_ = scroll_view_->SetContents(std::move(body_container)); scroll_view_->SetDrawOverflowIndicator(false); scroll_view_->ClipHeightTo(0, body_container_->GetPreferredSize().height());
diff --git a/chrome/browser/ui/views/autofill/payments/local_card_migration_dialog_view.cc b/chrome/browser/ui/views/autofill/payments/local_card_migration_dialog_view.cc index 98b4fe8..7da8f5a3 100644 --- a/chrome/browser/ui/views/autofill/payments/local_card_migration_dialog_view.cc +++ b/chrome/browser/ui/views/autofill/payments/local_card_migration_dialog_view.cc
@@ -160,7 +160,8 @@ } auto card_list_scroll_view = std::make_unique<views::ScrollView>(); - card_list_scroll_view->SetHideHorizontalScrollBar(true); + card_list_scroll_view->SetHorizontalScrollBarMode( + views::ScrollView::ScrollBarMode::kDisabled); card_list_scroll_view->SetContents(std::move(card_list_view)); card_list_scroll_view->SetDrawOverflowIndicator(false); constexpr int kCardListScrollViewHeight = 140;
diff --git a/chrome/browser/ui/views/commander_frontend_views.cc b/chrome/browser/ui/views/commander_frontend_views.cc index 7eac887..a832c6d 100644 --- a/chrome/browser/ui/views/commander_frontend_views.cc +++ b/chrome/browser/ui/views/commander_frontend_views.cc
@@ -101,7 +101,7 @@ web_view_->LoadInitialURL(GURL(chrome::kChromeUICommanderURL)); CommanderUI* controller = static_cast<CommanderUI*>( web_view_->GetWebContents()->GetWebUI()->GetController()); - controller->handler()->set_delegate(this); + controller->handler()->PrepareToShow(this); web_view_ptr_ = widget_->SetContentsView(std::move(web_view_));
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc index 7c2006a..33361e37 100644 --- a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc +++ b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc
@@ -126,7 +126,8 @@ screen_scroll_view->ClipHeightTo( kGenericScreenStyle.item_size.height(), kGenericScreenStyle.item_size.height() * 2); - screen_scroll_view->SetHideHorizontalScrollBar(true); + screen_scroll_view->SetHorizontalScrollBarMode( + views::ScrollView::ScrollBarMode::kDisabled); panes.push_back( std::make_pair(screen_title_text, std::move(screen_scroll_view))); @@ -156,7 +157,8 @@ window_scroll_view->ClipHeightTo(kWindowStyle.item_size.height(), kWindowStyle.item_size.height() * 2); - window_scroll_view->SetHideHorizontalScrollBar(true); + window_scroll_view->SetHorizontalScrollBarMode( + views::ScrollView::ScrollBarMode::kDisabled); panes.push_back( std::make_pair(window_title_text, std::move(window_scroll_view)));
diff --git a/chrome/browser/ui/views/extensions/extension_install_blocked_dialog_view.cc b/chrome/browser/ui/views/extensions/extension_install_blocked_dialog_view.cc index 6201252..2b97a6c 100644 --- a/chrome/browser/ui/views/extensions/extension_install_blocked_dialog_view.cc +++ b/chrome/browser/ui/views/extensions/extension_install_blocked_dialog_view.cc
@@ -121,7 +121,8 @@ header_label->SizeToFit(content_width); auto* scroll_view = AddChildView(std::make_unique<views::ScrollView>()); - scroll_view->SetHideHorizontalScrollBar(true); + scroll_view->SetHorizontalScrollBarMode( + views::ScrollView::ScrollBarMode::kDisabled); scroll_view->SetContents(std::move(extension_info_container)); scroll_view->ClipHeightTo( 0, provider->GetDistanceMetric(
diff --git a/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc b/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc index b8d244c1..081b19d 100644 --- a/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc +++ b/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc
@@ -520,7 +520,8 @@ } scroll_view_ = new views::ScrollView(); - scroll_view_->SetHideHorizontalScrollBar(true); + scroll_view_->SetHorizontalScrollBarMode( + views::ScrollView::ScrollBarMode::kDisabled); scroll_view_->SetContents(std::move(extension_info_container)); scroll_view_->ClipHeightTo( 0, provider->GetDistanceMetric(
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_view.cc b/chrome/browser/ui/views/extensions/extensions_menu_view.cc index 719846c..f9fcc3f 100644 --- a/chrome/browser/ui/views/extensions/extensions_menu_view.cc +++ b/chrome/browser/ui/views/extensions/extensions_menu_view.cc
@@ -132,7 +132,8 @@ auto scroll_view = std::make_unique<views::ScrollView>(); scroll_view->ClipHeightTo(0, kMaxExtensionButtonsHeightDp); scroll_view->SetDrawOverflowIndicator(false); - scroll_view->SetHideHorizontalScrollBar(true); + scroll_view->SetHorizontalScrollBarMode( + views::ScrollView::ScrollBarMode::kDisabled); scroll_view->SetContents(std::move(extension_buttons)); AddChildView(std::move(scroll_view));
diff --git a/chrome/browser/ui/views/frame/browser_root_view.cc b/chrome/browser/ui/views/frame/browser_root_view.cc index f64e2a94..88fa7da 100644 --- a/chrome/browser/ui/views/frame/browser_root_view.cc +++ b/chrome/browser/ui/views/frame/browser_root_view.cc
@@ -17,6 +17,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/views/frame/browser_frame.h" #include "chrome/browser/ui/views/tabs/tab_strip.h" #include "chrome/browser/ui/views/tabs/tab_strip_controller.h" @@ -259,7 +260,13 @@ } bool BrowserRootView::OnMouseWheel(const ui::MouseWheelEvent& event) { - if (browser_defaults::kScrollEventChangesTab) { + // TODO(dfried): See if it's possible to move this logic deeper into the view + // hierarchy - ideally to TabStripRegionView. + + // Scroll-event-changes-tab is incompatible with scrolling tabstrip, so + // disable it if the latter feature is enabled. + if (browser_defaults::kScrollEventChangesTab && + !base::FeatureList::IsEnabled(features::kScrollableTabStrip)) { // Switch to the left/right tab if the wheel-scroll happens over the // tabstrip, or the empty space beside the tabstrip. views::View* hit_view = GetEventHandlerForPoint(event.location());
diff --git a/chrome/browser/ui/views/frame/tab_strip_region_view.cc b/chrome/browser/ui/views/frame/tab_strip_region_view.cc index 54dbdfa..0ca3c12c 100644 --- a/chrome/browser/ui/views/frame/tab_strip_region_view.cc +++ b/chrome/browser/ui/views/frame/tab_strip_region_view.cc
@@ -31,7 +31,8 @@ AddChildView(std::make_unique<views::ScrollView>( views::ScrollView::ScrollWithLayers::kEnabled)); tab_strip_scroll_container->SetBackgroundColor(base::nullopt); - tab_strip_scroll_container->SetHideHorizontalScrollBar(true); + tab_strip_scroll_container->SetHorizontalScrollBarMode( + views::ScrollView::ScrollBarMode::kDisabled); tab_strip_container_ = tab_strip_scroll_container; tab_strip_scroll_container->SetContents(std::move(tab_strip)); } else {
diff --git a/chrome/browser/ui/views/payments/payment_request_sheet_controller.cc b/chrome/browser/ui/views/payments/payment_request_sheet_controller.cc index a937b193..bd42178 100644 --- a/chrome/browser/ui/views/payments/payment_request_sheet_controller.cc +++ b/chrome/browser/ui/views/payments/payment_request_sheet_controller.cc
@@ -253,7 +253,8 @@ scroll_ = layout->AddView(DisplayDynamicBorderForHiddenContents() ? std::make_unique<BorderedScrollView>() : std::make_unique<views::ScrollView>()); - scroll_->SetHideHorizontalScrollBar(true); + scroll_->SetHorizontalScrollBarMode( + views::ScrollView::ScrollBarMode::kDisabled); pane_ = scroll_->SetContents(std::make_unique<views::View>()); views::GridLayout* pane_layout = pane_->SetLayoutManager(std::make_unique<views::GridLayout>());
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 bac3c572..0f950b7a 100644 --- a/chrome/browser/ui/views/profiles/profile_menu_view_base.cc +++ b/chrome/browser/ui/views/profiles/profile_menu_view_base.cc
@@ -913,7 +913,8 @@ // Create a scroll view to hold the components. auto scroll_view = std::make_unique<views::ScrollView>(); - scroll_view->SetHideHorizontalScrollBar(true); + scroll_view->SetHorizontalScrollBarMode( + views::ScrollView::ScrollBarMode::kDisabled); // TODO(https://crbug.com/871762): it's a workaround for the crash. scroll_view->SetDrawOverflowIndicator(false); scroll_view->ClipHeightTo(0, GetMaxHeight());
diff --git a/chrome/browser/ui/views/supervised_user/parent_permission_dialog_view.cc b/chrome/browser/ui/views/supervised_user/parent_permission_dialog_view.cc index fd9495e1..d66915d 100644 --- a/chrome/browser/ui/views/supervised_user/parent_permission_dialog_view.cc +++ b/chrome/browser/ui/views/supervised_user/parent_permission_dialog_view.cc
@@ -460,7 +460,8 @@ // Add section container to an enclosing scroll view. auto scroll_view = std::make_unique<views::ScrollView>(); - scroll_view->SetHideHorizontalScrollBar(true); + scroll_view->SetHorizontalScrollBarMode( + views::ScrollView::ScrollBarMode::kDisabled); scroll_view->SetContents(std::move(install_permissions_section_container)); scroll_view->ClipHeightTo( 0, provider->GetDistanceMetric(
diff --git a/chrome/browser/ui/webui/commander/commander_handler.cc b/chrome/browser/ui/webui/commander/commander_handler.cc index 6b6173e..c6932ad6 100644 --- a/chrome/browser/ui/webui/commander/commander_handler.cc +++ b/chrome/browser/ui/webui/commander/commander_handler.cc
@@ -8,24 +8,42 @@ #include "base/strings/utf_string_conversions.h" #include "chrome/browser/ui/commander/commander_view_model.h" -const char CommanderHandler::Delegate::kKey[] = - "CommanderHandler::Delegate::kKey"; +namespace { +// Message handler keys. +constexpr char kTextChangedMessage[] = "textChanged"; +constexpr char kOptionSelectedMessage[] = "optionSelected"; +constexpr char kDismissMessage[] = "dismiss"; +constexpr char kHeightChangedMessage[] = "heightChanged"; +// WebUI event keys. +constexpr char kViewModelUpdatedEvent[] = "view-model-updated"; +constexpr char kInitializeEvent[] = "initialize"; +// View model dictionary keys +constexpr char kActionKey[] = "action"; +constexpr char kResultSetIdKey[] = "result_set_id"; +constexpr char kTitleKey[] = "title"; +constexpr char kEntityKey[] = "entity"; +constexpr char kAnnotationKey[] = "annotations"; +constexpr char kMatchedRangesKey[] = "matched_ranges"; +constexpr char kOptionsKey[] = "options"; +} // namespace + CommanderHandler::CommanderHandler() = default; CommanderHandler::~CommanderHandler() = default; void CommanderHandler::RegisterMessages() { web_ui()->RegisterMessageCallback( - "textChanged", base::BindRepeating(&CommanderHandler::HandleTextChanged, - base::Unretained(this))); + kTextChangedMessage, + base::BindRepeating(&CommanderHandler::HandleTextChanged, + base::Unretained(this))); web_ui()->RegisterMessageCallback( - "optionSelected", + kOptionSelectedMessage, base::BindRepeating(&CommanderHandler::HandleOptionSelected, base::Unretained(this))); web_ui()->RegisterMessageCallback( - "dismiss", base::BindRepeating(&CommanderHandler::HandleDismiss, - base::Unretained(this))); + kDismissMessage, base::BindRepeating(&CommanderHandler::HandleDismiss, + base::Unretained(this))); web_ui()->RegisterMessageCallback( - "heightChanged", + kHeightChangedMessage, base::BindRepeating(&CommanderHandler::HandleHeightChanged, base::Unretained(this))); } @@ -73,17 +91,37 @@ commander::CommanderViewModel view_model) { if (view_model.action == commander::CommanderViewModel::Action::kDisplayResults) { - base::Value list(base::Value::Type::LIST); + base::DictionaryValue vm; + vm.SetIntKey(kActionKey, view_model.action); + vm.SetIntKey(kResultSetIdKey, view_model.result_set_id); + base::ListValue option_list; for (commander::CommandItemViewModel& item : view_model.items) { - // TODO(lgrey): This is temporary, just so we can display something. - // We will also need to pass on the result set id, and match ranges for - // each item. - list.Append(item.title); + base::DictionaryValue option; + option.SetStringKey(kTitleKey, item.title); + option.SetIntKey(kEntityKey, item.entity_type); + if (!item.annotation.empty()) + option.SetStringKey(kAnnotationKey, item.annotation); + base::ListValue ranges; + for (const gfx::Range& range : item.matched_ranges) { + base::ListValue range_value; + range_value.Append(static_cast<int>(range.start())); + range_value.Append(static_cast<int>(range.end())); + ranges.Append(std::move(range_value)); + } + option.SetKey(kMatchedRangesKey, std::move(ranges)); + option_list.Append(std::move(option)); } - FireWebUIListener("view-model-updated", list); + vm.SetKey(kOptionsKey, std::move(option_list)); + FireWebUIListener(kViewModelUpdatedEvent, vm); } else { DCHECK_EQ(view_model.action, commander::CommanderViewModel::Action::kPrompt); // TODO(lgrey): Handle kPrompt. kDismiss is handled higher up the stack. } } + +void CommanderHandler::PrepareToShow(Delegate* delegate) { + delegate_ = delegate; + if (IsJavascriptAllowed()) + FireWebUIListener(kInitializeEvent); +}
diff --git a/chrome/browser/ui/webui/commander/commander_handler.h b/chrome/browser/ui/webui/commander/commander_handler.h index ce89400..cfd70d8 100644 --- a/chrome/browser/ui/webui/commander/commander_handler.h +++ b/chrome/browser/ui/webui/commander/commander_handler.h
@@ -17,9 +17,6 @@ // browser-side commander system. class Delegate { public: - // The key under which the delegate is expected to be stashed in the - // containing web contents. - static const char kKey[]; // Called when the text is changed in the WebUI interface. virtual void OnTextChanged(const base::string16& text) = 0; // Called when an option is selected (clicked or enter pressed) in the WebUI @@ -39,7 +36,9 @@ // Called when a new view model should be displayed. void ViewModelUpdated(commander::CommanderViewModel view_model); - void set_delegate(Delegate* delegate) { delegate_ = delegate; } + // Called to reinitialize the UI (clear input, remove results, etc.) and + // attach the delegate. + void PrepareToShow(Delegate* delegate); // WebUIMessageHandler overrides. void RegisterMessages() override;
diff --git a/chrome/browser/ui/webui/commander/commander_ui_browsertest.cc b/chrome/browser/ui/webui/commander/commander_ui_browsertest.cc index 79922b9..275e082 100644 --- a/chrome/browser/ui/webui/commander/commander_ui_browsertest.cc +++ b/chrome/browser/ui/webui/commander/commander_ui_browsertest.cc
@@ -38,7 +38,7 @@ ui::PAGE_TRANSITION_AUTO_TOPLEVEL, std::string()); CommanderUI* controller = static_cast<CommanderUI*>(contents_->GetWebUI()->GetController()); - controller->handler()->set_delegate(this); + controller->handler()->PrepareToShow(this); ASSERT_TRUE(content::WaitForLoadStop(contents_.get())); EXPECT_EQ(contents_->GetLastCommittedURL().host(), @@ -122,16 +122,47 @@ TEST(CommanderHandlerTest, ViewModelPassed) { content::TestWebUI test_web_ui; auto handler = std::make_unique<TestCommanderHandler>(&test_web_ui); + commander::CommanderViewModel vm; vm.action = commander::CommanderViewModel::Action::kDisplayResults; base::string16 item_title = base::ASCIIToUTF16("Test item"); - std::vector<gfx::Range> item_ranges; + std::vector<gfx::Range> item_ranges = {gfx::Range(0, 4)}; vm.items.emplace_back(item_title, item_ranges); + vm.result_set_id = 42; + handler->AllowJavascriptForTesting(); handler->ViewModelUpdated(std::move(vm)); const content::TestWebUI::CallData& call_data = *test_web_ui.call_data().back(); EXPECT_EQ("cr.webUIListenerCallback", call_data.function_name()); EXPECT_EQ("view-model-updated", call_data.arg1()->GetString()); - EXPECT_EQ("Test item", call_data.arg2()->GetList()[0].GetString()); + + const base::Value* arg = call_data.arg2(); + EXPECT_EQ( + "Test item", + arg->FindPath("options")->GetList()[0].FindPath("title")->GetString()); + EXPECT_EQ(0, arg->FindPath("options") + ->GetList()[0] + .FindPath("matched_ranges") + ->GetList()[0] + .GetList()[0] + .GetInt()); + EXPECT_EQ(4, arg->FindPath("options") + ->GetList()[0] + .FindPath("matched_ranges") + ->GetList()[0] + .GetList()[1] + .GetInt()); + EXPECT_EQ(42, arg->FindPath("result_set_id")->GetInt()); +} + +TEST(CommanderHandlerTest, Initialize) { + content::TestWebUI test_web_ui; + auto handler = std::make_unique<TestCommanderHandler>(&test_web_ui); + handler->AllowJavascriptForTesting(); + handler->PrepareToShow(nullptr); + const content::TestWebUI::CallData& call_data = + *test_web_ui.call_data().back(); + EXPECT_EQ("cr.webUIListenerCallback", call_data.function_name()); + EXPECT_EQ("initialize", call_data.arg1()->GetString()); }
diff --git a/chrome/browser/ui/webui/managed_ui_handler.cc b/chrome/browser/ui/webui/managed_ui_handler.cc index 3d4e6125b..cee8309 100644 --- a/chrome/browser/ui/webui/managed_ui_handler.cc +++ b/chrome/browser/ui/webui/managed_ui_handler.cc
@@ -114,7 +114,7 @@ base::Value(chrome::GetManagedUiWebUILabel(profile_))); #if defined(OS_CHROMEOS) update->SetKey("deviceManagedByOrg", - base::Value(chrome::GetDeviceManagedUiWebUILabel(profile_))); + base::Value(chrome::GetDeviceManagedUiWebUILabel())); #endif update->SetKey("isManaged", base::Value(managed_)); return update;
diff --git a/chrome/browser/ui/webui/management_ui.cc b/chrome/browser/ui/webui/management_ui.cc index c3214cf..7db259e 100644 --- a/chrome/browser/ui/webui/management_ui.cc +++ b/chrome/browser/ui/webui/management_ui.cc
@@ -171,32 +171,32 @@ l10n_util::GetStringUTF16(device_type)); } - std::string display_domain = connector->GetEnterpriseDisplayDomain(); + std::string account_manager = connector->GetEnterpriseDomainManager(); - if (display_domain.empty()) - display_domain = connector->GetRealm(); - if (display_domain.empty()) - display_domain = ManagementUIHandler::GetAccountDomain(profile); - if (display_domain.empty()) { + if (account_manager.empty()) + account_manager = connector->GetRealm(); + if (account_manager.empty()) + account_manager = ManagementUIHandler::GetAccountManager(profile); + if (account_manager.empty()) { return l10n_util::GetStringFUTF16(IDS_MANAGEMENT_SUBTITLE_MANAGED, l10n_util::GetStringUTF16(device_type)); } return l10n_util::GetStringFUTF16(IDS_MANAGEMENT_SUBTITLE_MANAGED_BY, l10n_util::GetStringUTF16(device_type), - base::UTF8ToUTF16(display_domain)); + base::UTF8ToUTF16(account_manager)); #else // defined(OS_CHROMEOS) - const auto management_domain = ManagementUIHandler::GetAccountDomain(profile); + const auto account_manager = ManagementUIHandler::GetAccountManager(profile); const auto managed = profile->GetProfilePolicyConnector()->IsManaged() || g_browser_process->browser_policy_connector()->HasMachineLevelPolicies(); - if (management_domain.empty()) { + if (account_manager.empty()) { return l10n_util::GetStringUTF16(managed ? IDS_MANAGEMENT_SUBTITLE : IDS_MANAGEMENT_NOT_MANAGED_SUBTITLE); } if (managed) { return l10n_util::GetStringFUTF16(IDS_MANAGEMENT_SUBTITLE_MANAGED_BY, - base::UTF8ToUTF16(management_domain)); + base::UTF8ToUTF16(account_manager)); } return l10n_util::GetStringUTF16(IDS_MANAGEMENT_NOT_MANAGED_SUBTITLE); #endif // defined(OS_CHROMEOS)
diff --git a/chrome/browser/ui/webui/management_ui_handler.cc b/chrome/browser/ui/webui/management_ui_handler.cc index bb23c5a..7add4bb 100644 --- a/chrome/browser/ui/webui/management_ui_handler.cc +++ b/chrome/browser/ui/webui/management_ui_handler.cc
@@ -325,9 +325,7 @@ } // namespace -// TODO(raleksandov) Move to util class or smth similar. -// static -std::string ManagementUIHandler::GetAccountDomain(Profile* profile) { +std::string GetAccountDomain(Profile* profile) { if (!IsProfileManaged(profile)) return std::string(); auto username = profile->GetProfileUserName(); @@ -652,7 +650,7 @@ response->SetStringPath( "eolMessage", l10n_util::GetStringFUTF16(IDS_MANAGEMENT_UPDATE_REQUIRED_EOL_MESSAGE, - base::UTF8ToUTF16(GetDeviceDomain()), + base::UTF8ToUTF16(GetDeviceManager()), ui::GetChromeOSDeviceName())); std::string eol_admin_message; chromeos::CrosSettings::Get()->GetString( @@ -694,13 +692,13 @@ base::Value ManagementUIHandler::GetContextualManagedData(Profile* profile) { base::Value response(base::Value::Type::DICTIONARY); #if defined(OS_CHROMEOS) - std::string management_domain = GetDeviceDomain(); - if (management_domain.empty()) - management_domain = GetAccountDomain(profile); + std::string enterprise_manager = GetDeviceManager(); + if (enterprise_manager.empty()) + enterprise_manager = GetAccountManager(profile); AddUpdateRequiredEolInfo(&response); AddProxyServerPrivacyDisclosure(&response); #else - std::string management_domain = GetAccountDomain(profile); + std::string enterprise_manager = GetAccountManager(profile); response.SetStringPath( "browserManagementNotice", @@ -710,7 +708,7 @@ base::UTF8ToUTF16(chrome::kManagedUiLearnMoreUrl))); #endif - if (management_domain.empty()) { + if (enterprise_manager.empty()) { response.SetStringPath( "extensionReportingTitle", l10n_util::GetStringUTF16(IDS_MANAGEMENT_EXTENSIONS_INSTALLED)); @@ -736,14 +734,14 @@ response.SetStringPath( "extensionReportingTitle", l10n_util::GetStringFUTF16(IDS_MANAGEMENT_EXTENSIONS_INSTALLED_BY, - base::UTF8ToUTF16(management_domain))); + base::UTF8ToUTF16(enterprise_manager))); #if !defined(OS_CHROMEOS) response.SetStringPath( "pageSubtitle", managed_() ? l10n_util::GetStringFUTF16(IDS_MANAGEMENT_SUBTITLE_MANAGED_BY, - base::UTF8ToUTF16(management_domain)) + base::UTF8ToUTF16(enterprise_manager)) : l10n_util::GetStringUTF16(IDS_MANAGEMENT_NOT_MANAGED_SUBTITLE)); #else const auto device_type = ui::GetChromeOSDeviceTypeResourceId(); @@ -752,7 +750,7 @@ managed_() ? l10n_util::GetStringFUTF16(IDS_MANAGEMENT_SUBTITLE_MANAGED_BY, l10n_util::GetStringUTF16(device_type), - base::UTF8ToUTF16(management_domain)) + base::UTF8ToUTF16(enterprise_manager)) : l10n_util::GetStringFUTF16( IDS_MANAGEMENT_NOT_MANAGED_SUBTITLE, l10n_util::GetStringUTF16(device_type))); @@ -825,21 +823,21 @@ } #if defined(OS_CHROMEOS) - std::string management_domain = GetDeviceDomain(); - if (management_domain.empty()) - management_domain = GetAccountDomain(profile); + std::string enterprise_manager = GetDeviceManager(); + if (enterprise_manager.empty()) + enterprise_manager = GetAccountManager(profile); #else - std::string management_domain = GetAccountDomain(profile); + std::string enterprise_manager = GetAccountManager(profile); #endif // defined(OS_CHROMEOS) base::Value result(base::Value::Type::DICTIONARY); result.SetStringKey("description", - management_domain.empty() + enterprise_manager.empty() ? l10n_util::GetStringUTF16( IDS_MANAGEMENT_THREAT_PROTECTION_DESCRIPTION) : l10n_util::GetStringFUTF16( IDS_MANAGEMENT_THREAT_PROTECTION_DESCRIPTION_BY, - base::UTF8ToUTF16(management_domain))); + base::UTF8ToUTF16(enterprise_manager))); result.SetKey("info", std::move(info)); return result; } @@ -891,39 +889,39 @@ base::Value* status, bool device_managed, bool account_managed, - const std::string& device_domain, - const std::string& account_domain) { + const std::string& device_manager, + const std::string& account_manager) { if (device_managed && account_managed && - (account_domain.empty() || account_domain == device_domain)) { + (account_manager.empty() || account_manager == device_manager)) { status->SetKey(kOverview, base::Value(l10n_util::GetStringFUTF16( IDS_MANAGEMENT_DEVICE_AND_ACCOUNT_MANAGED_BY, - base::UTF8ToUTF16(device_domain)))); + base::UTF8ToUTF16(device_manager)))); return; } - if (account_managed && !account_domain.empty()) { + if (account_managed && !account_manager.empty()) { status->SetKey(kOverview, base::Value(l10n_util::GetStringFUTF16( IDS_MANAGEMENT_ACCOUNT_MANAGED_BY, - base::UTF8ToUTF16(account_domain)))); + base::UTF8ToUTF16(account_manager)))); } - if (account_managed && device_managed && !account_domain.empty() && - account_domain != device_domain) { + if (account_managed && device_managed && !account_manager.empty() && + account_manager != device_manager) { status->SetKey(kOverview, base::Value(l10n_util::GetStringFUTF16( IDS_MANAGEMENT_DEVICE_MANAGED_BY_ACCOUNT_MANAGED_BY, - base::UTF8ToUTF16(device_domain), - base::UTF8ToUTF16(account_domain)))); + base::UTF8ToUTF16(device_manager), + base::UTF8ToUTF16(account_manager)))); } } -const std::string ManagementUIHandler::GetDeviceDomain() const { +const std::string ManagementUIHandler::GetDeviceManager() const { std::string device_domain; policy::BrowserPolicyConnectorChromeOS* connector = g_browser_process->platform_part()->browser_policy_connector_chromeos(); if (device_managed_) - device_domain = connector->GetEnterpriseDisplayDomain(); + device_domain = connector->GetEnterpriseDomainManager(); if (device_domain.empty() && connector->IsActiveDirectoryManaged()) device_domain = connector->GetRealm(); return device_domain; @@ -942,7 +940,7 @@ IDS_MANAGEMENT_DEVICE_NOT_MANAGED))); return; } - std::string account_domain = GetAccountDomain(profile); + std::string account_manager = GetAccountManager(profile); auto* primary_user = user_manager::UserManager::Get()->GetPrimaryUser(); auto* primary_profile = primary_user @@ -952,13 +950,13 @@ primary_profile ? IsProfileManaged(primary_profile) : false; if (primary_user_managed) - account_domain = GetAccountDomain(primary_profile); + account_manager = GetAccountManager(primary_profile); - std::string device_domain = GetDeviceDomain(); + std::string device_manager = GetDeviceManager(); AddStatusOverviewManagedDeviceAndAccount( status, device_managed_, account_managed_ || primary_user_managed, - device_domain, account_domain); + device_manager, account_manager); #endif // defined(OS_CHROMEOS) }
diff --git a/chrome/browser/ui/webui/management_ui_handler.h b/chrome/browser/ui/webui/management_ui_handler.h index d45c33d..67baebf 100644 --- a/chrome/browser/ui/webui/management_ui_handler.h +++ b/chrome/browser/ui/webui/management_ui_handler.h
@@ -120,10 +120,6 @@ void SetAccountManagedForTesting(bool managed) { account_managed_ = managed; } void SetDeviceManagedForTesting(bool managed) { device_managed_ = managed; } - // This will return the domain (ie foo.com) that manages |profile|. If - // unmanaged, an empty string is returned. - static std::string GetAccountDomain(Profile* profile); - // This returns the entity that manages this |profile|. For standard dasher // domains, this will be a domain name (ie foo.com). For FlexOrgs, this will // be the email address of the admin of the FlexOrg (ie user@foo.com). If @@ -149,7 +145,7 @@ #if defined(OS_CHROMEOS) // Protected for testing. - virtual const std::string GetDeviceDomain() const; + virtual const std::string GetDeviceManager() const; virtual const policy::DeviceCloudPolicyManagerChromeOS* GetDeviceCloudPolicyManager() const; void AddDeviceReportingInfo(base::Value* report_sources,
diff --git a/chrome/browser/ui/webui/management_ui_handler_unittest.cc b/chrome/browser/ui/webui/management_ui_handler_unittest.cc index a5f0f1bf..e75c078 100644 --- a/chrome/browser/ui/webui/management_ui_handler_unittest.cc +++ b/chrome/browser/ui/webui/management_ui_handler_unittest.cc
@@ -239,7 +239,7 @@ return report_sources; } - const std::string GetDeviceDomain() const override { return device_domain; } + const std::string GetDeviceManager() const override { return device_domain; } void SetDeviceDomain(const std::string& domain) { device_domain = domain; } #endif // defined(OS_CHROMEOS) @@ -1270,20 +1270,6 @@ EXPECT_EQ(expected_info, *threat_protection_info->FindListKey("info")); } -TEST_F(ManagementUIHandlerTests, GetAccountDomain) { - TestingProfile::Builder builder_unmanaged_user; - builder_unmanaged_user.SetProfileName(kUser); - builder_unmanaged_user.OverridePolicyConnectorIsManagedForTesting(false); - auto unmanaged_user = builder_unmanaged_user.Build(); - EXPECT_EQ("", handler_.GetAccountDomain(unmanaged_user.get())); - - TestingProfile::Builder builder_managed_user; - builder_managed_user.SetProfileName(kUser); - builder_managed_user.OverridePolicyConnectorIsManagedForTesting(true); - auto managed_user = builder_managed_user.Build(); - EXPECT_EQ(kDomain, handler_.GetAccountDomain(managed_user.get())); -} - TEST_F(ManagementUIHandlerTests, GetAccountManager) { TestingProfile::Builder builder_managed_user; builder_managed_user.SetProfileName(kUser);
diff --git a/chrome/browser/uid/OWNERS b/chrome/browser/uid/OWNERS new file mode 100644 index 0000000..354d5ae --- /dev/null +++ b/chrome/browser/uid/OWNERS
@@ -0,0 +1,4 @@ +file://components/signin/OWNERS + +# TEAM: chrome-signin@chromium.org +# COMPONENT: Services>SignIn
diff --git a/chrome/browser/uid/android/BUILD.gn b/chrome/browser/uid/android/BUILD.gn new file mode 100644 index 0000000..632c1fc --- /dev/null +++ b/chrome/browser/uid/android/BUILD.gn
@@ -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. + +import("//build/config/android/rules.gni") + +android_library("java") { + sources = [ + "java/src/org/chromium/chrome/browser/uid/SettingsSecureBasedIdentificationGenerator.java", + "java/src/org/chromium/chrome/browser/uid/UniqueIdentificationGenerator.java", + "java/src/org/chromium/chrome/browser/uid/UniqueIdentificationGeneratorFactory.java", + "java/src/org/chromium/chrome/browser/uid/UuidBasedUniqueIdentificationGenerator.java", + ] + deps = [ + "//chrome/browser/preferences:java", + "//chrome/browser/util:java", + "//third_party/android_deps:androidx_annotation_annotation_java", + ] +} + +android_library("javatests") { + testonly = true + sources = [ + "javatests/src/org/chromium/chrome/browser/uid/SettingsSecureBasedIdentificationGeneratorTest.java", + "javatests/src/org/chromium/chrome/browser/uid/UniqueIdentificationGeneratorFactoryTest.java", + "javatests/src/org/chromium/chrome/browser/uid/UuidBasedUniqueIdentificationGeneratorTest.java", + ] + deps = [ + ":java", + "//base:base_java", + "//base:base_java_test_support", + "//base/test:test_support_java", + "//chrome/browser/preferences:java", + "//chrome/browser/util:java", + "//chrome/test/android:chrome_java_test_support", + "//third_party/android_deps:androidx_annotation_annotation_java", + "//third_party/android_deps:androidx_test_runner_java", + "//third_party/android_support_test_runner:runner_java", + "//third_party/junit:junit", + ] +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/identity/SettingsSecureBasedIdentificationGenerator.java b/chrome/browser/uid/android/java/src/org/chromium/chrome/browser/uid/SettingsSecureBasedIdentificationGenerator.java similarity index 90% rename from chrome/android/java/src/org/chromium/chrome/browser/identity/SettingsSecureBasedIdentificationGenerator.java rename to chrome/browser/uid/android/java/src/org/chromium/chrome/browser/uid/SettingsSecureBasedIdentificationGenerator.java index 6b932ee..83cfa14 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/identity/SettingsSecureBasedIdentificationGenerator.java +++ b/chrome/browser/uid/android/java/src/org/chromium/chrome/browser/uid/SettingsSecureBasedIdentificationGenerator.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.identity; +package org.chromium.chrome.browser.uid; import android.annotation.SuppressLint; import android.content.Context; @@ -35,8 +35,7 @@ return ""; } - String md5Hash = HashUtil.getMd5Hash( - new HashUtil.Params(androidId).withSalt(salt)); + String md5Hash = HashUtil.getMd5Hash(new HashUtil.Params(androidId).withSalt(salt)); return md5Hash == null ? "" : md5Hash; }
diff --git a/chrome/browser/uid/android/java/src/org/chromium/chrome/browser/uid/UniqueIdentificationGenerator.java b/chrome/browser/uid/android/java/src/org/chromium/chrome/browser/uid/UniqueIdentificationGenerator.java new file mode 100644 index 0000000..866d2c6c --- /dev/null +++ b/chrome/browser/uid/android/java/src/org/chromium/chrome/browser/uid/UniqueIdentificationGenerator.java
@@ -0,0 +1,23 @@ +// Copyright 2013 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. + +package org.chromium.chrome.browser.uid; + +import androidx.annotation.Nullable; + +/** + * Interface used for uniquely identifying an installation of Chrome. To get an instance you should + * use {@link UniqueIdentificationGeneratorFactory}. + */ +public interface UniqueIdentificationGenerator { + /** + * Creates a string that uniquely identifies this installation. + * <p/> + * If there is an error in generating the string, an empty string must be returned, not null. + * + * @param salt the salt to use for the unique ID. + * @return a unique ID. On failure to generate, it must return the empty string. + */ + String getUniqueId(@Nullable String salt); +}
diff --git a/chrome/browser/uid/android/java/src/org/chromium/chrome/browser/uid/UniqueIdentificationGeneratorFactory.java b/chrome/browser/uid/android/java/src/org/chromium/chrome/browser/uid/UniqueIdentificationGeneratorFactory.java new file mode 100644 index 0000000..a175042 --- /dev/null +++ b/chrome/browser/uid/android/java/src/org/chromium/chrome/browser/uid/UniqueIdentificationGeneratorFactory.java
@@ -0,0 +1,67 @@ +// Copyright 2013 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. + +package org.chromium.chrome.browser.uid; + +import androidx.annotation.VisibleForTesting; + +import java.util.HashMap; +import java.util.Map; + +/** + * Factory for setting and retrieving instances of {@link UniqueIdentificationGenerator}s. + * <p/> + * A generator must always be set for a generator type before it is asked for. A generator type + * is any string you want to use for your generator. It is typically defined as a public static + * field in the generator itself. + */ +public final class UniqueIdentificationGeneratorFactory { + private static final Object LOCK = new Object(); + private static final Map<String, UniqueIdentificationGenerator> GENERATOR_MAP = + new HashMap<String, UniqueIdentificationGenerator>(); + + private UniqueIdentificationGeneratorFactory() {} + + /** + * Returns a UniqueIdentificationGenerator if it exists, else throws IllegalArgumentException. + * + * @param generatorType the generator type you want + * @return a unique ID generator + */ + public static UniqueIdentificationGenerator getInstance(String generatorType) { + synchronized (LOCK) { + if (!GENERATOR_MAP.containsKey(generatorType)) { + throw new IllegalArgumentException("Unknown generator type " + generatorType); + } + return GENERATOR_MAP.get(generatorType); + } + } + + /** + * During startup of the application, and before any calls to + * {@link #getInstance(String)} you must add all supported generators + * to this factory. + * + * @param generatorType the type of generator this is. Must be a unique string. + * @param gen the generator. + * @param force if set to true, will override any existing generator for this type. Else + * discards calls where a generator exists. + */ + public static void registerGenerator( + String generatorType, UniqueIdentificationGenerator gen, boolean force) { + synchronized (LOCK) { + if (GENERATOR_MAP.containsKey(generatorType) && !force) { + return; + } + GENERATOR_MAP.put(generatorType, gen); + } + } + + @VisibleForTesting + public static void clearGeneratorMapForTest() { + synchronized (LOCK) { + GENERATOR_MAP.clear(); + } + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/identity/UuidBasedUniqueIdentificationGenerator.java b/chrome/browser/uid/android/java/src/org/chromium/chrome/browser/uid/UuidBasedUniqueIdentificationGenerator.java similarity index 96% rename from chrome/android/java/src/org/chromium/chrome/browser/identity/UuidBasedUniqueIdentificationGenerator.java rename to chrome/browser/uid/android/java/src/org/chromium/chrome/browser/uid/UuidBasedUniqueIdentificationGenerator.java index f0039d8..aed9cdb2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/identity/UuidBasedUniqueIdentificationGenerator.java +++ b/chrome/browser/uid/android/java/src/org/chromium/chrome/browser/uid/UuidBasedUniqueIdentificationGenerator.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.identity; +package org.chromium.chrome.browser.uid; import android.content.Context; @@ -40,7 +40,6 @@ // Store the field so we ensure we always return the same unique ID. preferences.writeString(mPreferenceKey, uniqueId); return uniqueId; - } @VisibleForTesting
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/identity/SettingsSecureBasedIdentificationGeneratorTest.java b/chrome/browser/uid/android/javatests/src/org/chromium/chrome/browser/uid/SettingsSecureBasedIdentificationGeneratorTest.java similarity index 95% rename from chrome/android/javatests/src/org/chromium/chrome/browser/identity/SettingsSecureBasedIdentificationGeneratorTest.java rename to chrome/browser/uid/android/javatests/src/org/chromium/chrome/browser/uid/SettingsSecureBasedIdentificationGeneratorTest.java index c2be4e3..45ac7caf 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/identity/SettingsSecureBasedIdentificationGeneratorTest.java +++ b/chrome/browser/uid/android/javatests/src/org/chromium/chrome/browser/uid/SettingsSecureBasedIdentificationGeneratorTest.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.identity; +package org.chromium.chrome.browser.uid; import androidx.test.filters.SmallTest; @@ -15,6 +15,7 @@ import org.chromium.chrome.browser.util.HashUtil; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +/** Unit tests for {@link SettingsSecureBasedIdentificationGenerator}. */ @RunWith(ChromeJUnit4ClassRunner.class) public class SettingsSecureBasedIdentificationGeneratorTest { private static final String FLAG_ANDROID_ID = "android_id";
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/identity/UniqueIdentificationGeneratorFactoryTest.java b/chrome/browser/uid/android/javatests/src/org/chromium/chrome/browser/uid/UniqueIdentificationGeneratorFactoryTest.java similarity index 95% rename from chrome/android/javatests/src/org/chromium/chrome/browser/identity/UniqueIdentificationGeneratorFactoryTest.java rename to chrome/browser/uid/android/javatests/src/org/chromium/chrome/browser/uid/UniqueIdentificationGeneratorFactoryTest.java index 1a33622..609d9f9 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/identity/UniqueIdentificationGeneratorFactoryTest.java +++ b/chrome/browser/uid/android/javatests/src/org/chromium/chrome/browser/uid/UniqueIdentificationGeneratorFactoryTest.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.identity; +package org.chromium.chrome.browser.uid; import androidx.annotation.Nullable; import androidx.test.filters.SmallTest; @@ -14,6 +14,7 @@ import org.chromium.base.test.util.Feature; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +/** Unit tests for {@link UniqueIdentificationGeneratorFactory}. */ @RunWith(ChromeJUnit4ClassRunner.class) public class UniqueIdentificationGeneratorFactoryTest { @Test
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/identity/UuidBasedUniqueIdentificationGeneratorTest.java b/chrome/browser/uid/android/javatests/src/org/chromium/chrome/browser/uid/UuidBasedUniqueIdentificationGeneratorTest.java similarity index 96% rename from chrome/android/javatests/src/org/chromium/chrome/browser/identity/UuidBasedUniqueIdentificationGeneratorTest.java rename to chrome/browser/uid/android/javatests/src/org/chromium/chrome/browser/uid/UuidBasedUniqueIdentificationGeneratorTest.java index c230beae..492e6fc 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/identity/UuidBasedUniqueIdentificationGeneratorTest.java +++ b/chrome/browser/uid/android/javatests/src/org/chromium/chrome/browser/uid/UuidBasedUniqueIdentificationGeneratorTest.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.identity; +package org.chromium.chrome.browser.uid; import android.support.test.InstrumentationRegistry; @@ -18,6 +18,7 @@ import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +/** Unit tests for {@link UuidBasedUniqueIdentificationGenerator}. */ @RunWith(ChromeJUnit4ClassRunner.class) public class UuidBasedUniqueIdentificationGeneratorTest { private static final String FLAG_UUID = "uuid";
diff --git a/chrome/common/profiler/thread_profiler_platform_configuration.cc b/chrome/common/profiler/thread_profiler_platform_configuration.cc index d37ae07c..35e6d35 100644 --- a/chrome/common/profiler/thread_profiler_platform_configuration.cc +++ b/chrome/common/profiler/thread_profiler_platform_configuration.cc
@@ -192,13 +192,6 @@ if (browser_test_mode_enabled()) return DefaultPlatformConfiguration::GetChildProcessEnableFraction(process); - // Enable just on renderer process for now. Enabling for 40% of renderer - // processes samples roughly one renderer process on average for every Chrome - // execution, based on early channel data in the - // Memory.RenderProcessHost.Count.InitializedAndNotDead histogram. - if (process == metrics::CallStackProfileParams::RENDERER_PROCESS) - return 0.4; - // TODO(https://crbug.com/1004855): Enable for all the default processes. return 0.0; } @@ -206,23 +199,15 @@ bool AndroidPlatformConfiguration::IsEnabledForThread( metrics::CallStackProfileParams::Process process, metrics::CallStackProfileParams::Thread thread) const { - // Enable on renderer process main thread in production, for now. - if (process == metrics::CallStackProfileParams::RENDERER_PROCESS && - thread == metrics::CallStackProfileParams::MAIN_THREAD) { - return true; - } - - // Otherwise enable in dedicated ThreadProfiler browser tests. + // Disable for all supported threads pending launch. Enable only for browser + // tests. return browser_test_mode_enabled(); } bool AndroidPlatformConfiguration::IsSupportedForChannel( base::Optional<version_info::Channel> release_channel) const { - // Enable on canary, for now. - if (release_channel && *release_channel == version_info::Channel::CANARY) - return true; - - // Otherwise enable in dedicated ThreadProfiler browser tests. + // On Android profiling is only enabled in its own dedicated browser tests + // in local builds and the CQ. // TODO(https://crbug.com/1004855): Enable across all browser tests. return browser_test_mode_enabled(); }
diff --git a/chrome/common/profiler/thread_profiler_platform_configuration_unittest.cc b/chrome/common/profiler/thread_profiler_platform_configuration_unittest.cc index f741215..5e51a51 100644 --- a/chrome/common/profiler/thread_profiler_platform_configuration_unittest.cc +++ b/chrome/common/profiler/thread_profiler_platform_configuration_unittest.cc
@@ -72,7 +72,7 @@ EXPECT_FALSE(config()->IsSupported(base::nullopt)); #elif defined(OS_ANDROID) EXPECT_FALSE(config()->IsSupported(version_info::Channel::UNKNOWN)); - EXPECT_TRUE(config()->IsSupported(version_info::Channel::CANARY)); + EXPECT_FALSE(config()->IsSupported(version_info::Channel::CANARY)); EXPECT_FALSE(config()->IsSupported(version_info::Channel::DEV)); EXPECT_FALSE(config()->IsSupported(version_info::Channel::BETA)); EXPECT_FALSE(config()->IsSupported(version_info::Channel::STABLE)); @@ -126,15 +126,14 @@ MAYBE_PLATFORM_CONFIG_TEST_F(ThreadProfilerPlatformConfigurationTest, GetEnableRates) { + // Note: death tests aren't supported on Android. Otherwise this test would + // check that all inputs result in CHECKs. +#if !defined(OS_ANDROID) using RelativePopulations = ThreadProfilerPlatformConfiguration::RelativePopulations; + EXPECT_CHECK_DEATH(config()->GetEnableRates(version_info::Channel::UNKNOWN)); EXPECT_EQ((RelativePopulations{80, 20}), config()->GetEnableRates(version_info::Channel::CANARY)); -#if defined(OS_ANDROID) - // Note: death tests aren't supported on Android. Otherwise this test would - // check that the other inputs result in CHECKs. -#else - EXPECT_CHECK_DEATH(config()->GetEnableRates(version_info::Channel::UNKNOWN)); EXPECT_EQ((RelativePopulations{80, 20}), config()->GetEnableRates(version_info::Channel::DEV)); EXPECT_CHECK_DEATH(config()->GetEnableRates(version_info::Channel::BETA)); @@ -150,7 +149,7 @@ #if defined(OS_ANDROID) EXPECT_EQ(0.0, config()->GetChildProcessEnableFraction( metrics::CallStackProfileParams::GPU_PROCESS)); - EXPECT_EQ(0.4, config()->GetChildProcessEnableFraction( + EXPECT_EQ(0.0, config()->GetChildProcessEnableFraction( metrics::CallStackProfileParams::RENDERER_PROCESS)); EXPECT_EQ(0.0, config()->GetChildProcessEnableFraction( metrics::CallStackProfileParams::NETWORK_SERVICE_PROCESS)); @@ -192,7 +191,7 @@ metrics::CallStackProfileParams::GPU_PROCESS, metrics::CallStackProfileParams::COMPOSITOR_THREAD)); - EXPECT_TRUE(config()->IsEnabledForThread( + EXPECT_FALSE(config()->IsEnabledForThread( metrics::CallStackProfileParams::RENDERER_PROCESS, metrics::CallStackProfileParams::MAIN_THREAD)); EXPECT_FALSE(config()->IsEnabledForThread(
diff --git a/chrome/renderer/pepper/pepper_flash_fullscreen_host.cc b/chrome/renderer/pepper/pepper_flash_fullscreen_host.cc index d590cde..fe9f2be 100644 --- a/chrome/renderer/pepper/pepper_flash_fullscreen_host.cc +++ b/chrome/renderer/pepper/pepper_flash_fullscreen_host.cc
@@ -16,28 +16,12 @@ content::RendererPpapiHost* host, PP_Instance instance, PP_Resource resource) - : ResourceHost(host->GetPpapiHost(), instance, resource), - renderer_ppapi_host_(host) {} + : ResourceHost(host->GetPpapiHost(), instance, resource) {} PepperFlashFullscreenHost::~PepperFlashFullscreenHost() {} int32_t PepperFlashFullscreenHost::OnResourceMessageReceived( const IPC::Message& msg, ppapi::host::HostMessageContext* context) { - PPAPI_BEGIN_MESSAGE_MAP(PepperFlashFullscreenHost, msg) - PPAPI_DISPATCH_HOST_RESOURCE_CALL( - PpapiHostMsg_FlashFullscreen_SetFullscreen, - OnSetFullscreen) - PPAPI_END_MESSAGE_MAP() - return PP_ERROR_FAILED; -} - -int32_t PepperFlashFullscreenHost::OnSetFullscreen( - ppapi::host::HostMessageContext* context, - bool fullscreen) { - content::PepperPluginInstance* plugin_instance = - renderer_ppapi_host_->GetPluginInstance(pp_instance()); - if (plugin_instance && plugin_instance->FlashSetFullscreen(fullscreen, true)) - return PP_OK; return PP_ERROR_FAILED; }
diff --git a/chrome/renderer/pepper/pepper_flash_fullscreen_host.h b/chrome/renderer/pepper/pepper_flash_fullscreen_host.h index 1cd5b39..867cea7 100644 --- a/chrome/renderer/pepper/pepper_flash_fullscreen_host.h +++ b/chrome/renderer/pepper/pepper_flash_fullscreen_host.h
@@ -27,12 +27,6 @@ ppapi::host::HostMessageContext* context) override; private: - int32_t OnSetFullscreen(ppapi::host::HostMessageContext* context, - bool fullscreen); - - // Non-owning pointer. - content::RendererPpapiHost* renderer_ppapi_host_; - DISALLOW_COPY_AND_ASSIGN(PepperFlashFullscreenHost); };
diff --git a/chrome/services/sharing/nearby/nearby_connections.cc b/chrome/services/sharing/nearby/nearby_connections.cc index 0007c57..e644842 100644 --- a/chrome/services/sharing/nearby/nearby_connections.cc +++ b/chrome/services/sharing/nearby/nearby_connections.cc
@@ -185,7 +185,9 @@ mojo::PendingRemote<mojom::EndpointDiscoveryListener> listener, StartDiscoveryCallback callback) { ConnectionOptions connection_options{ - .strategy = StrategyFromMojom(options->strategy)}; + .strategy = StrategyFromMojom(options->strategy), + .fast_advertisement_service_uuid = + options->fast_advertisement_service_uuid.canonical_value()}; mojo::SharedRemote<mojom::EndpointDiscoveryListener> remote( std::move(listener)); DiscoveryListener discovery_listener{
diff --git a/chrome/services/sharing/nearby/nearby_connections_unittest.cc b/chrome/services/sharing/nearby/nearby_connections_unittest.cc index e701f90..4dbaa88 100644 --- a/chrome/services/sharing/nearby/nearby_connections_unittest.cc +++ b/chrome/services/sharing/nearby/nearby_connections_unittest.cc
@@ -211,6 +211,8 @@ client_proxy = client; EXPECT_EQ(kServiceId, service_id); EXPECT_EQ(Strategy::kP2pPointToPoint, options.strategy); + EXPECT_EQ(kFastAdvertisementServiceUuid, + options.fast_advertisement_service_uuid); client->StartedDiscovery(service_id, options.strategy, listener, /*mediums=*/{}); return Status{Status::kAlreadyDiscovering}; @@ -219,7 +221,9 @@ base::RunLoop start_discovery_run_loop; nearby_connections_->StartDiscovery( kServiceId, - mojom::DiscoveryOptions::New(mojom::Strategy::kP2pPointToPoint), + mojom::DiscoveryOptions::New( + mojom::Strategy::kP2pPointToPoint, + device::BluetoothUUID(kFastAdvertisementServiceUuid)), fake_discovery_listener.receiver.BindNewPipeAndPassRemote(), base::BindLambdaForTesting([&](mojom::Status status) { EXPECT_EQ(mojom::Status::kAlreadyDiscovering, status);
diff --git a/chrome/services/sharing/public/mojom/nearby_connections_types.mojom b/chrome/services/sharing/public/mojom/nearby_connections_types.mojom index 8718fb1..9f6bb2b 100644 --- a/chrome/services/sharing/public/mojom/nearby_connections_types.mojom +++ b/chrome/services/sharing/public/mojom/nearby_connections_types.mojom
@@ -148,6 +148,8 @@ // The strategy to use for discovering. Must match the strategy used in // AdvertisingOptions in order to see advertisements. Strategy strategy; + // The fast advertisement service id to scan for in BLE. + bluetooth.mojom.UUID fast_advertisement_service_uuid; }; // Options for a call to NearbyConnections::RequestConnection().
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 8ee3464..dd010a6 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -2369,13 +2369,13 @@ "../browser/chromeos/extensions/wallpaper_manager_browsertest.cc", "../browser/chromeos/extensions/wallpaper_private_apitest.cc", "../browser/chromeos/file_manager/audio_player_browsertest.cc", + "../browser/chromeos/file_manager/browser_test_devtools_listener.cc", + "../browser/chromeos/file_manager/browser_test_devtools_listener.h", "../browser/chromeos/file_manager/external_filesystem_apitest.cc", "../browser/chromeos/file_manager/file_manager_base_jstest.cc", "../browser/chromeos/file_manager/file_manager_browsertest.cc", "../browser/chromeos/file_manager/file_manager_browsertest_base.cc", "../browser/chromeos/file_manager/file_manager_browsertest_base.h", - "../browser/chromeos/file_manager/browser_test_devtools_listener.cc", - "../browser/chromeos/file_manager/browser_test_devtools_listener.h", "../browser/chromeos/file_manager/file_manager_jstest.cc", "../browser/chromeos/file_manager/file_manager_jstest_base.cc", "../browser/chromeos/file_manager/file_manager_jstest_base.h", @@ -2881,6 +2881,7 @@ } if (is_win) { sources += [ + "../browser/chrome_browser_main_win_browsertest.cc", "../browser/printing/pdf_to_emf_converter_browsertest.cc", "../browser/spellchecker/spell_check_host_chrome_impl_win_browsertest.cc", "../browser/ui/startup/credential_provider_signin_dialog_win_browsertest.cc", @@ -6201,7 +6202,6 @@ "../browser/ui/cocoa/apps/quit_with_apps_controller_mac_interactive_uitest.mm", "../browser/ui/cocoa/status_bubble_mac_interactive_uitest.mm", "../browser/ui/cocoa/tab_contents/web_contents_view_mac_interactive_uitest.mm", - "../browser/ui/exclusive_access/flash_fullscreen_interactive_browsertest.cc", "../browser/ui/exclusive_access/fullscreen_controller_interactive_browsertest.cc", "../browser/ui/exclusive_access/fullscreen_controller_state_interactive_browsertest.cc", "../browser/ui/exclusive_access/fullscreen_interactive_browsertest.cc",
diff --git a/chrome/test/android/BUILD.gn b/chrome/test/android/BUILD.gn index 7bdec0a..a315416 100644 --- a/chrome/test/android/BUILD.gn +++ b/chrome/test/android/BUILD.gn
@@ -277,6 +277,7 @@ "//chrome/browser/ui/android/favicon:java", "//chrome/browser/ui/messages/android:java", "//chrome/browser/util:java", + "//chrome/browser/version:java", "//components/bookmarks/common/android:bookmarks_java", "//components/browser_ui/notifications/android:test_support_java", "//components/browser_ui/widget/android:java",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeJUnit4ClassRunner.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeJUnit4ClassRunner.java index a51dd03..19c937f 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeJUnit4ClassRunner.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeJUnit4ClassRunner.java
@@ -20,7 +20,7 @@ import org.chromium.base.StrictModeContext; import org.chromium.base.test.util.RestrictionSkipCheck; import org.chromium.base.test.util.SkipCheck; -import org.chromium.chrome.browser.ChromeVersionInfo; +import org.chromium.chrome.browser.version.ChromeVersionInfo; import org.chromium.chrome.test.util.ChromeRestriction; import org.chromium.chrome.test.util.browser.Features; import org.chromium.components.policy.test.annotations.Policies;
diff --git a/chrome/updater/util.h b/chrome/updater/util.h index fa34992..b84eae05 100644 --- a/chrome/updater/util.h +++ b/chrome/updater/util.h
@@ -56,13 +56,11 @@ // Provides a way to safely convert numeric types to enumerated values. // To use this facility, the enum definition must be annotated with traits to -// specify the range of the enum values. Due to how the specialization of -// class template work in C++, the |EnumTraits| specialization must be -// defined in the |updater| namespace. That means that traits for enum types -// defined inside other scopes, such as nested classes or other namespaces -// may not work if the traits type is define inside the that scope instead of -// the |updater| namespace where the primary template is defined. - +// specify the range of the enum values. Due to how specialization of class +// templates works in C++14, the |EnumTraits| specialization of the primary +// template must be defined inside the |updater| namespace, where the +// primary template is defined. Traits for enum types defined inside +// other scopes, such as nested classes or other namespaces, may not work. // // enum class MyEnum { // kVal1 = -1,
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index 3d92acb..b6350df 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -13510.0.0 \ No newline at end of file +13511.0.0 \ No newline at end of file
diff --git a/chromeos/components/diagnostics_ui/resources/battery_status_card.html b/chromeos/components/diagnostics_ui/resources/battery_status_card.html index f607659..583cbbd7 100644 --- a/chromeos/components/diagnostics_ui/resources/battery_status_card.html +++ b/chromeos/components/diagnostics_ui/resources/battery_status_card.html
@@ -3,6 +3,11 @@ <diagnostics-card> <div id="cardTitle" slot="title">[[i18n('batteryTitle')]]</div> + <!-- TODO(joonbug): Localize once strings are confirmed --> + <percent-bar-chart slot="left-panel" title="Remaining charge" + value="[[batteryChargeStatus_.charge_now_milliamp_hours]]" + max="[[batteryChargeStatus_.charge_full_now_milliamp_hours]]"> + </percent-bar-chart> <data-point slot="body" id="currentNow" value="[[batteryChargeStatus_.current_now_milliamps]]"> </data-point> @@ -24,9 +29,4 @@ <data-point slot="body" id="cycleCount" value="[[batteryHealth_.cycle_count]]"> </data-point> - <!-- TODO(joonbug): Localize once strings are confirmed --> - <percent-bar-chart slot="body" title="Remaining charge" - value="[[batteryChargeStatus_.charge_now_milliamp_hours]]" - max="[[batteryChargeStatus_.charge_full_now_milliamp_hours]]"> - </percent-bar-chart> </diagnostics-card>
diff --git a/chromeos/components/diagnostics_ui/resources/memory_card.html b/chromeos/components/diagnostics_ui/resources/memory_card.html index ad4c17d..c0bdd42 100644 --- a/chromeos/components/diagnostics_ui/resources/memory_card.html +++ b/chromeos/components/diagnostics_ui/resources/memory_card.html
@@ -3,15 +3,15 @@ <diagnostics-card> <div id="cardTitle" slot="title">[[i18n('memoryTitle')]]</div> + <!-- TODO(joonbug): Localize once strings are confirmed --> + <percent-bar-chart slot="left-panel" title="Used memory" + value="[[getTotalUsedMemory_(memoryUsage_)]]" + max="[[memoryUsage_.total_memory_kib]]"> + </percent-bar-chart> <data-point slot="body" id="memoryTotal" value="[[memoryUsage_.total_memory_kib]]"> </data-point> <data-point slot="body" id="memoryAvailable" value="[[memoryUsage_.available_memory_kib]]"> </data-point> - <!-- TODO(joonbug): Localize once strings are confirmed --> - <percent-bar-chart slot="body" title="Used memory" - value="[[getTotalUsedMemory_(memoryUsage_)]]" - max="[[memoryUsage_.total_memory_kib]]"> - </percent-bar-chart> </diagnostics-card>
diff --git a/chromeos/components/phonehub/fake_do_not_disturb_controller.cc b/chromeos/components/phonehub/fake_do_not_disturb_controller.cc index bfe586c0..b1bb3fc 100644 --- a/chromeos/components/phonehub/fake_do_not_disturb_controller.cc +++ b/chromeos/components/phonehub/fake_do_not_disturb_controller.cc
@@ -25,7 +25,13 @@ } void FakeDoNotDisturbController::RequestNewDoNotDisturbState(bool enabled) { - SetDoNotDisturbStateInternal(enabled); + if (!should_request_fail_) + SetDoNotDisturbStateInternal(enabled); +} + +void FakeDoNotDisturbController::SetShouldRequestFail( + bool should_request_fail) { + should_request_fail_ = should_request_fail; } } // namespace phonehub
diff --git a/chromeos/components/phonehub/fake_do_not_disturb_controller.h b/chromeos/components/phonehub/fake_do_not_disturb_controller.h index 6d9de37..1a252938e 100644 --- a/chromeos/components/phonehub/fake_do_not_disturb_controller.h +++ b/chromeos/components/phonehub/fake_do_not_disturb_controller.h
@@ -20,8 +20,14 @@ void SetDoNotDisturbStateInternal(bool is_dnd_enabled) override; void RequestNewDoNotDisturbState(bool enabled) override; + void SetShouldRequestFail(bool should_request_fail); + private: bool is_dnd_enabled_ = false; + + // Indicates if the connection to the phone is working correctly. If it is + // true, there is a problem and the phone cannot change its state. + bool should_request_fail_ = false; }; } // namespace phonehub
diff --git a/chromeos/dbus/fake_lorgnette_manager_client.cc b/chromeos/dbus/fake_lorgnette_manager_client.cc index 52dcd811..af1b968 100644 --- a/chromeos/dbus/fake_lorgnette_manager_client.cc +++ b/chromeos/dbus/fake_lorgnette_manager_client.cc
@@ -37,9 +37,10 @@ const std::string& device_name, const lorgnette::ScanSettings& settings, VoidDBusMethodCallback completion_callback, - base::RepeatingCallback<void(std::string)> page_callback, + base::RepeatingCallback<void(std::string, uint32_t)> page_callback, base::RepeatingCallback<void(int)> progress_callback) { if (scan_response_.has_value()) { + uint32_t page_number = 0; for (const std::string& page_data : scan_response_.value()) { // Simulate progress reporting for the scan job. if (progress_callback) { @@ -50,7 +51,7 @@ } base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(page_callback, page_data)); + FROM_HERE, base::BindOnce(page_callback, page_data, ++page_number)); } }
diff --git a/chromeos/dbus/fake_lorgnette_manager_client.h b/chromeos/dbus/fake_lorgnette_manager_client.h index 5977a8a0..c074597 100644 --- a/chromeos/dbus/fake_lorgnette_manager_client.h +++ b/chromeos/dbus/fake_lorgnette_manager_client.h
@@ -5,6 +5,7 @@ #ifndef CHROMEOS_DBUS_FAKE_LORGNETTE_MANAGER_CLIENT_H_ #define CHROMEOS_DBUS_FAKE_LORGNETTE_MANAGER_CLIENT_H_ +#include <cstdint> #include <string> #include <vector> @@ -30,11 +31,12 @@ void GetScannerCapabilities( const std::string& device_name, DBusMethodCallback<lorgnette::ScannerCapabilities> callback) override; - void StartScan(const std::string& device_name, - const lorgnette::ScanSettings& settings, - VoidDBusMethodCallback completion_callback, - base::RepeatingCallback<void(std::string)> page_callback, - base::RepeatingCallback<void(int)> progress_callback) override; + void StartScan( + const std::string& device_name, + const lorgnette::ScanSettings& settings, + VoidDBusMethodCallback completion_callback, + base::RepeatingCallback<void(std::string, uint32_t)> page_callback, + base::RepeatingCallback<void(int)> progress_callback) override; // Sets the response returned by ListScanners(). void SetListScannersResponse(
diff --git a/chromeos/dbus/lorgnette_manager_client.cc b/chromeos/dbus/lorgnette_manager_client.cc index f49a3fe..e8fdca06 100644 --- a/chromeos/dbus/lorgnette_manager_client.cc +++ b/chromeos/dbus/lorgnette_manager_client.cc
@@ -70,7 +70,7 @@ const std::string& device_name, const lorgnette::ScanSettings& settings, VoidDBusMethodCallback completion_callback, - base::RepeatingCallback<void(std::string)> page_callback, + base::RepeatingCallback<void(std::string, uint32_t)> page_callback, base::RepeatingCallback<void(int)> progress_callback) override { lorgnette::StartScanRequest request; request.set_device_name(device_name); @@ -185,7 +185,7 @@ struct ScanJobState { VoidDBusMethodCallback completion_callback; base::RepeatingCallback<void(int)> progress_callback; - base::RepeatingCallback<void(std::string)> page_callback; + base::RepeatingCallback<void(std::string, uint32_t)> page_callback; std::unique_ptr<ScanDataReader> scan_data_reader; }; @@ -267,6 +267,7 @@ // Called when scan data read is completed. void OnScanDataCompleted(const std::string& uuid, + uint32_t page_number, bool more_pages, base::Optional<std::string> data) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -284,7 +285,7 @@ return; } - state.page_callback.Run(std::move(data.value())); + state.page_callback.Run(std::move(data.value()), page_number); if (more_pages) { GetNextImage(uuid); @@ -375,10 +376,10 @@ VLOG(1) << "Scan job " << signal_proto.scan_uuid() << " page " << signal_proto.page() << " completed successfully"; ScanDataReader* reader = state.scan_data_reader.get(); - reader->Wait( - base::BindOnce(&LorgnetteManagerClientImpl::OnScanDataCompleted, - weak_ptr_factory_.GetWeakPtr(), - signal_proto.scan_uuid(), signal_proto.more_pages())); + reader->Wait(base::BindOnce( + &LorgnetteManagerClientImpl::OnScanDataCompleted, + weak_ptr_factory_.GetWeakPtr(), signal_proto.scan_uuid(), + signal_proto.page(), signal_proto.more_pages())); } else if (signal_proto.state() == lorgnette::SCAN_STATE_COMPLETED) { VLOG(1) << "Scan job " << signal_proto.scan_uuid() << " completed successfully";
diff --git a/chromeos/dbus/lorgnette_manager_client.h b/chromeos/dbus/lorgnette_manager_client.h index 3e6fc2ae..6d78917 100644 --- a/chromeos/dbus/lorgnette_manager_client.h +++ b/chromeos/dbus/lorgnette_manager_client.h
@@ -5,6 +5,7 @@ #ifndef CHROMEOS_DBUS_LORGNETTE_MANAGER_CLIENT_H_ #define CHROMEOS_DBUS_LORGNETTE_MANAGER_CLIENT_H_ +#include <cstdint> #include <map> #include <memory> #include <string> @@ -43,9 +44,9 @@ DBusMethodCallback<lorgnette::ScannerCapabilities> callback) = 0; // Request a scanned image using lorgnette's StartScan API. As each page is - // completed, calls |page_callback| with a string containing the image data. - // Calls |completion_callback| when the scan has completed. Image data will - // be stored in the .png format. + // completed, calls |page_callback| with the page number and a string + // containing the image data. Calls |completion_callback| when the scan has + // completed. Image data will be stored in the .png format. // // If |progress_callback| is provided, it will be called as scan progress // increases. The progress will be passed as a value from 0-100. @@ -53,7 +54,7 @@ const std::string& device_name, const lorgnette::ScanSettings& settings, VoidDBusMethodCallback completion_callback, - base::RepeatingCallback<void(std::string)> page_callback, + base::RepeatingCallback<void(std::string, uint32_t)> page_callback, base::RepeatingCallback<void(int)> progress_callback) = 0; // Factory function, creates a new instance and returns ownership.
diff --git a/chromeos/profiles/airmont.afdo.newest.txt b/chromeos/profiles/airmont.afdo.newest.txt index adbd799..6f0e92e 100644 --- a/chromeos/profiles/airmont.afdo.newest.txt +++ b/chromeos/profiles/airmont.afdo.newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-airmont-87-4265.0-1601286022-benchmark-87.0.4280.7-r1-redacted.afdo.xz +chromeos-chrome-amd64-airmont-87-4265.0-1601895675-benchmark-87.0.4280.7-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/broadwell.afdo.newest.txt b/chromeos/profiles/broadwell.afdo.newest.txt index 85bcbe1..42597249 100644 --- a/chromeos/profiles/broadwell.afdo.newest.txt +++ b/chromeos/profiles/broadwell.afdo.newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-broadwell-87-4258.0-1601290734-benchmark-87.0.4280.7-r1-redacted.afdo.xz +chromeos-chrome-amd64-broadwell-87-4265.0-1601892862-benchmark-87.0.4280.7-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/silvermont.afdo.newest.txt b/chromeos/profiles/silvermont.afdo.newest.txt index e676c08..b2f1cfd 100644 --- a/chromeos/profiles/silvermont.afdo.newest.txt +++ b/chromeos/profiles/silvermont.afdo.newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-silvermont-87-4265.0-1601289755-benchmark-87.0.4280.7-r1-redacted.afdo.xz +chromeos-chrome-amd64-silvermont-87-4265.0-1601890590-benchmark-87.0.4280.7-r1-redacted.afdo.xz
diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc index be64d5f3..1f49b84 100644 --- a/components/autofill/core/common/autofill_features.cc +++ b/components/autofill/core/common/autofill_features.cc
@@ -24,6 +24,13 @@ const base::Feature kAutofillAddressEnhancementVotes{ "kAutofillAddressEnhancementVotes", base::FEATURE_DISABLED_BY_DEFAULT}; +// TODO(crbug.com/1135188): Remove this feature flag after the explicit save +// prompts for address profiles is complete. +// When enabled, a save prompt will be shown to user upon form submission before +// storing any detected address profile. +const base::Feature kAutofillAddressProfileSavePrompt{ + "kAutofillAddressProfileSavePrompt", base::FEATURE_DISABLED_BY_DEFAULT}; + // By default, AutofillAgent and, if |kAutofillProbableFormSubmissionInBrowser| // is enabled, also ContentAutofillDriver omit duplicate form submissions, even // though the form's data may have changed substantially. If enabled, the
diff --git a/components/autofill/core/common/autofill_features.h b/components/autofill/core/common/autofill_features.h index 6fd7f20..d29a713 100644 --- a/components/autofill/core/common/autofill_features.h +++ b/components/autofill/core/common/autofill_features.h
@@ -22,6 +22,7 @@ // All features in alphabetical order. extern const base::Feature kAutofillAddressEnhancementVotes; +extern const base::Feature kAutofillAddressProfileSavePrompt; extern const base::Feature kAutofillAllowDuplicateFormSubmissions; extern const base::Feature kAutofillAllowHtmlTypeCountryCodesWithFullNames; extern const base::Feature kAutofillAllowNonHttpActivation;
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java index 9dd0a7f..544cce98 100644 --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java
@@ -1038,12 +1038,12 @@ int confirmationResId = mHideNonPermissionPreferences ? R.string.page_info_permissions_reset_confirmation : R.string.website_reset_confirmation; - preference.setTitle(titleResId); + int buttonResId = mHideNonPermissionPreferences ? R.string.reset : titleResId; // Handle the Clear & Reset preference click by showing a confirmation. new AlertDialog.Builder(getActivity(), R.style.Theme_Chromium_AlertDialog) .setTitle(titleResId) .setMessage(confirmationResId) - .setPositiveButton(titleResId, + .setPositiveButton(buttonResId, (dialog, which) -> { if (mHideNonPermissionPreferences) { mSiteDataCleaner.resetPermissions(
diff --git a/components/page_info/android/java/res/layout/page_info_container.xml b/components/page_info/android/java/res/layout/page_info_container.xml index 04a505a..f97a0ef 100644 --- a/components/page_info/android/java/res/layout/page_info_container.xml +++ b/components/page_info/android/java/res/layout/page_info_container.xml
@@ -14,28 +14,38 @@ android:background="@color/sheet_bg_color" android:orientation="vertical"> - <TextView - android:id="@+id/page_info_truncated_url" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_horizontal" - android:layout_marginVertical="16dp" - android:ellipsize="end" - android:lineSpacingExtra="6dp" - android:textAlignment="center" - android:textAppearance="@style/TextAppearance.TextLarge.Primary" /> - - <view - android:id="@+id/page_info_url" - class="org.chromium.components.page_info.PageInfoView$ElidedUrlTextView" + <LinearLayout + android:id="@+id/page_info_url_wrapper" android:layout_width="match_parent" android:layout_height="wrap_content" - android:ellipsize="end" - android:lineSpacingExtra="6dp" - android:paddingVertical="16dp" - android:textAlignment="center" - android:textAppearance="@style/TextAppearance.TextLarge.Primary" - android:visibility="gone" /> + android:minHeight="48dp" + android:gravity="center" + android:paddingVertical="@dimen/page_info_popup_padding_vertical" + android:paddingHorizontal="@dimen/page_info_popup_padding_sides"> + + <org.chromium.components.browser_ui.widget.text.TextViewWithCompoundDrawables + android:id="@+id/page_info_truncated_url" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:drawablePadding="@dimen/page_info_popup_button_padding_sides" + android:includeFontPadding="false" + android:lineSpacingExtra="6dp" + android:textAppearance="@style/TextAppearance.TextLarge.Primary" + app:drawableHeight="@dimen/page_info_favicon_size" + app:drawableWidth="@dimen/page_info_favicon_size" /> + + <view + android:id="@+id/page_info_url" + class="org.chromium.components.page_info.PageInfoView$ElidedUrlTextView" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:ellipsize="end" + android:includeFontPadding="false" + android:lineSpacingExtra="6dp" + android:textAlignment="center" + android:textAppearance="@style/TextAppearance.TextLarge.Primary" + android:visibility="gone" /> + </LinearLayout> <LinearLayout android:id="@+id/page_info_wrapper" @@ -49,7 +59,7 @@ android:layout_height="wrap_content" android:gravity="center_vertical" android:orientation="horizontal" - android:paddingHorizontal="16dp"> + android:paddingHorizontal="@dimen/page_info_popup_padding_sides"> <org.chromium.ui.widget.ChromeImageButton android:id="@+id/subpage_back_button" @@ -67,7 +77,7 @@ android:id="@+id/page_info_subpage_title" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginVertical="12dp" + android:layout_marginVertical="@dimen/page_info_popup_padding_vertical" android:textAppearance="@style/TextAppearance.TextLarge.Primary" /> </LinearLayout>
diff --git a/components/page_info/android/java/res/layout/page_info_row.xml b/components/page_info/android/java/res/layout/page_info_row.xml index a1cf416..25cb7c8 100644 --- a/components/page_info/android/java/res/layout/page_info_row.xml +++ b/components/page_info/android/java/res/layout/page_info_row.xml
@@ -14,9 +14,9 @@ android:layout_height="wrap_content" android:background="?attr/selectableItemBackground" android:paddingHorizontal="@dimen/page_info_popup_padding_sides" - android:paddingVertical="12dp"> + android:paddingVertical="@dimen/page_info_popup_padding_vertical"> - <ImageView + <org.chromium.ui.widget.ChromeImageView android:id="@+id/page_info_row_icon" android:layout_width="wrap_content" android:layout_height="wrap_content"
diff --git a/components/page_info/android/java/res/layout/page_info_v2.xml b/components/page_info/android/java/res/layout/page_info_v2.xml index 8fdf5d1..a6c6e98 100644 --- a/components/page_info/android/java/res/layout/page_info_v2.xml +++ b/components/page_info/android/java/res/layout/page_info_v2.xml
@@ -12,7 +12,7 @@ android:layout_height="match_parent" android:background="@color/sheet_bg_color" android:orientation="vertical" - android:layout_marginBottom="8dp"> + android:paddingBottom="8dp"> <LinearLayout android:id="@+id/page_info_row_wrapper" @@ -50,7 +50,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginHorizontal="@dimen/page_info_popup_padding_sides" - android:layout_marginTop="12dp" + android:layout_marginTop="@dimen/page_info_popup_padding_vertical" android:textAppearance="@style/TextAppearance.TextLarge.Primary" android:text="@string/page_info_preview_message" android:visibility="gone" /> @@ -59,7 +59,7 @@ android:id="@+id/page_info_preview_load_original" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginVertical="12dp" + android:layout_marginVertical="@dimen/page_info_popup_padding_vertical" android:layout_marginHorizontal="@dimen/page_info_popup_padding_sides" android:textAppearance="@style/TextAppearance.TextLarge.Primary" android:visibility="gone" /> @@ -68,7 +68,7 @@ android:id="@+id/page_info_lite_mode_https_image_compression_message" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginVertical="12dp" + android:layout_marginVertical="@dimen/page_info_popup_padding_vertical" android:layout_marginHorizontal="@dimen/page_info_popup_padding_sides" android:text="@string/page_info_lite_mode_https_image_compression" android:textAppearance="@style/TextAppearance.TextMedium.Primary"
diff --git a/components/page_info/android/java/res/values/dimens.xml b/components/page_info/android/java/res/values/dimens.xml index 691979b..e42de84 100644 --- a/components/page_info/android/java/res/values/dimens.xml +++ b/components/page_info/android/java/res/values/dimens.xml
@@ -11,6 +11,7 @@ <!-- Page Info Popup Dimensions --> <dimen name="page_info_popup_padding_sides">16dp</dimen> + <dimen name="page_info_popup_padding_vertical">12dp</dimen> <dimen name="page_info_popup_button_padding_sides">8dp</dimen> <dimen name="page_info_popup_permission_icon_size">24dp</dimen> </resources> \ No newline at end of file
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoConnectionController.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoConnectionController.java index d9d3f64..7aa99ea 100644 --- a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoConnectionController.java +++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoConnectionController.java
@@ -8,7 +8,10 @@ import android.view.ViewGroup; import android.widget.FrameLayout; +import androidx.annotation.ColorRes; + import org.chromium.components.omnibox.SecurityStatusIcon; +import org.chromium.components.security_state.ConnectionSecurityLevel; import org.chromium.components.security_state.SecurityStateModel; import org.chromium.content_public.browser.WebContents; @@ -57,17 +60,37 @@ mInfoView.onDismiss(); } + private static @ColorRes int getSecurityIconColor( + @ConnectionSecurityLevel int securityLevel, boolean showDangerTriangleForWarningLevel) { + switch (securityLevel) { + case ConnectionSecurityLevel.DANGEROUS: + return R.color.default_text_color_error; + case ConnectionSecurityLevel.WARNING: + return showDangerTriangleForWarningLevel ? R.color.default_text_color_error : 0; + case ConnectionSecurityLevel.NONE: + case ConnectionSecurityLevel.SECURE_WITH_POLICY_INSTALLED_CERT: + case ConnectionSecurityLevel.SECURE: + return 0; + default: + assert false; + return 0; + } + } + public void setConnectionInfo(PageInfoView.ConnectionInfoParams params) { PageInfoRowView.ViewParams rowParams = new PageInfoRowView.ViewParams(); mTitle = params.summary != null ? params.summary.toString() : null; rowParams.title = mTitle; - rowParams.subtitle = params.message != null ? params.message.toString() : null; + rowParams.subtitle = params.message; rowParams.visible = rowParams.title != null || rowParams.subtitle != null; int securityLevel = SecurityStateModel.getSecurityLevelForWebContents(mWebContents); - rowParams.iconResId = SecurityStatusIcon.getSecurityIconResource(securityLevel, - SecurityStateModel.shouldShowDangerTriangleForWarningLevel(), - /*isSmallDevice=*/false, - /*skipIconForNeutralState=*/false); + boolean showTriangleForWarning = + SecurityStateModel.shouldShowDangerTriangleForWarningLevel(); + rowParams.iconResId = + SecurityStatusIcon.getSecurityIconResource(securityLevel, showTriangleForWarning, + /*isSmallDevice=*/false, + /*skipIconForNeutralState=*/false); + rowParams.iconTint = getSecurityIconColor(securityLevel, showTriangleForWarning); if (params.clickCallback != null) rowParams.clickCallback = this::launchSubpage; mRowView.setParams(rowParams); }
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoContainer.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoContainer.java index bcd1657f..3efe1e6 100644 --- a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoContainer.java +++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoContainer.java
@@ -69,14 +69,14 @@ mTruncatedUrlTitle = findViewById(R.id.page_info_truncated_url); mTruncatedUrlTitle.setText(params.truncatedUrl); + View urlWrapper = findViewById(R.id.page_info_url_wrapper); + urlWrapper.setVisibility(params.urlTitleShown ? VISIBLE : GONE); + ChromeImageButton backButton = findViewById(R.id.subpage_back_button); backButton.setOnClickListener(v -> params.backButtonClickCallback.run()); } private void initializeUrlView(View view, Params params) { - if (!params.urlTitleShown) { - view.setVisibility(GONE); - } if (params.urlTitleClickCallback != null) { view.setOnClickListener(v -> { params.urlTitleClickCallback.run(); }); } @@ -94,12 +94,6 @@ } public void setFavicon(Drawable favicon) { - int padding = - getResources().getDimensionPixelSize(R.dimen.page_info_popup_button_padding_sides); - int size = getResources().getDimensionPixelSize(R.dimen.page_info_favicon_size); - - favicon.setBounds(0, 0, size, size); - mTruncatedUrlTitle.setCompoundDrawablePadding(padding); mTruncatedUrlTitle.setCompoundDrawablesRelative(favicon, null, null, null); }
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoController.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoController.java index 600b8cc..6bc0b018 100644 --- a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoController.java +++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoController.java
@@ -413,7 +413,7 @@ messageBuilder.append(details); } - if (!mIsV2Enabled && isConnectionDetailsLinkVisible()) { + if (isConnectionDetailsLinkVisible() && messageBuilder.length() > 0) { messageBuilder.append(" "); SpannableString detailsText = new SpannableString(mContext.getString(R.string.details_link));
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoRowView.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoRowView.java index 5797a3a..0344628 100644 --- a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoRowView.java +++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoRowView.java
@@ -5,16 +5,20 @@ package org.chromium.components.page_info; import android.content.Context; +import android.content.res.ColorStateList; import android.util.AttributeSet; import android.view.LayoutInflater; import android.widget.FrameLayout; -import android.widget.ImageView; import android.widget.TextView; +import androidx.annotation.ColorRes; import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import org.chromium.base.ApiCompatibilityUtils; +import org.chromium.ui.widget.ChromeImageView; + /** * View showing an icon, title and subtitle for a page info row. */ @@ -23,12 +27,13 @@ public static class ViewParams { public boolean visible; public @DrawableRes int iconResId; - public String title; - public String subtitle; + public @ColorRes int iconTint; + public CharSequence title; + public CharSequence subtitle; public Runnable clickCallback; } - private final ImageView mIcon; + private final ChromeImageView mIcon; private final TextView mTitle; private final TextView mSubtitle; @@ -43,6 +48,10 @@ public void setParams(ViewParams params) { setVisibility(params.visible ? VISIBLE : GONE); mIcon.setImageResource(params.iconResId); + ApiCompatibilityUtils.setImageTintList(mIcon, + ColorStateList.valueOf(getResources().getColor( + params.iconTint != 0 ? params.iconTint : R.color.default_icon_color))); + mTitle.setText(params.title); mTitle.setVisibility(params.title != null ? VISIBLE : GONE); updateSubtitle(params.subtitle); @@ -53,7 +62,7 @@ } } - public void updateSubtitle(String subtitle) { + public void updateSubtitle(CharSequence subtitle) { mSubtitle.setText(subtitle); mSubtitle.setVisibility(subtitle != null ? VISIBLE : GONE); }
diff --git a/components/test/data/payments/create_many_requests.js b/components/test/data/payments/create_many_requests.js index 90f2240..7ff435f 100644 --- a/components/test/data/payments/create_many_requests.js +++ b/components/test/data/payments/create_many_requests.js
@@ -17,6 +17,6 @@ total: {label: 'Total', amount: {currency: 'USD', value: '55.00'}}, }; -for (let i = 0; i < 0x1000; i++) { +for (let i = 0; i < 0x400; i++) { new PaymentRequest(supportedInstruments, details); }
diff --git a/components/viz/common/features.cc b/components/viz/common/features.cc index 53957212..5cb13e5b 100644 --- a/components/viz/common/features.cc +++ b/components/viz/common/features.cc
@@ -111,14 +111,6 @@ if (IsUsingVizForWebView()) return true; -#if defined(OS_ANDROID) - // https://crbug.com/1126490 Mali-400 with <= 512 MB is currently broken. - // Must be checked after IsUsingVizForWebView because it requires - // SkiaRenderer. - if (base::SysInfo::AmountOfPhysicalMemoryMB() <= 512) - return false; -#endif - return base::FeatureList::IsEnabled(kUseSkiaRenderer) || base::FeatureList::IsEnabled(kVulkan); }
diff --git a/components/viz/service/display_embedder/skia_output_device_gl.cc b/components/viz/service/display_embedder/skia_output_device_gl.cc index 9e4ce61..3dd38d85 100644 --- a/components/viz/service/display_embedder/skia_output_device_gl.cc +++ b/components/viz/service/display_embedder/skia_output_device_gl.cc
@@ -125,8 +125,22 @@ } CHECK_GL_ERROR(); - auto color_type = - (alpha_bits > 0) ? kRGBA_8888_SkColorType : kRGB_888x_SkColorType; + auto color_type = kRGBA_8888_SkColorType; + + if (!alpha_bits) { + color_type = gl_surface_->GetFormat().GetBufferSize() == 16 + ? kRGB_565_SkColorType + : kRGB_888x_SkColorType; + // Skia disables RGBx on some GPUs, fallback to RGBA if it's the + // case. This doesn't change framebuffer itself, as we already allocated it, + // but will change any temporary buffer Skia needs to allocate. + if (!context_state_->gr_context() + ->defaultBackendFormat(color_type, GrRenderable::kYes) + .isValid()) { + color_type = kRGBA_8888_SkColorType; + } + } + capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::RGBA_8888)] = color_type; capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::RGBX_8888)] = @@ -175,6 +189,9 @@ case kRGB_888x_SkColorType: framebuffer_info.fFormat = GL_RGB8; break; + case kRGB_565_SkColorType: + framebuffer_info.fFormat = GL_RGB565; + break; case kRGBA_F16_SkColorType: framebuffer_info.fFormat = GL_RGBA16F; break;
diff --git a/content/browser/accessibility/accessibility_ipc_error_browsertest.cc b/content/browser/accessibility/accessibility_ipc_error_browsertest.cc index 75ed16d1..1dff9e7 100644 --- a/content/browser/accessibility/accessibility_ipc_error_browsertest.cc +++ b/content/browser/accessibility/accessibility_ipc_error_browsertest.cc
@@ -186,7 +186,7 @@ bad_accessibility_event.updates[0].root_id = 1; bad_accessibility_event.updates[0].nodes.resize(1); bad_accessibility_event.updates[0].nodes[0].id = 1; - bad_accessibility_event.updates[0].nodes[0].child_ids.push_back(2); + bad_accessibility_event.updates[0].nodes[0].child_ids.push_back(999); for (int iteration = 0; iteration < max_iterations; iteration++) { // Make sure the manager has been created.
diff --git a/content/browser/renderer_host/overscroll_controller.cc b/content/browser/renderer_host/overscroll_controller.cc index 112ec65..616f9d2 100644 --- a/content/browser/renderer_host/overscroll_controller.cc +++ b/content/browser/renderer_host/overscroll_controller.cc
@@ -175,6 +175,10 @@ // In overscrolling state, consume scroll-update and fling-start events when // they do not contribute to overscroll in order to prevent content scroll. + // TODO(bokan): This needs to account for behavior_ somehow since if the page + // declares that it doesn't want an overscroll effect, we should allow + // sending the scroll update events to generate DOM overscroll events. + // https://crbug.com/1112183. return scroll_state_ == ScrollState::OVERSCROLLING && (event.GetType() == blink::WebInputEvent::Type::kGestureScrollUpdate || event.GetType() == blink::WebInputEvent::Type::kGestureFlingStart);
diff --git a/content/browser/renderer_host/render_frame_host_impl.h b/content/browser/renderer_host/render_frame_host_impl.h index f1ac18ef..bc353236 100644 --- a/content/browser/renderer_host/render_frame_host_impl.h +++ b/content/browser/renderer_host/render_frame_host_impl.h
@@ -290,6 +290,7 @@ ui::AXTreeID GetAXTreeID() override; SiteInstanceImpl* GetSiteInstance() override; RenderProcessHost* GetProcess() override; + GlobalFrameRoutingId GetGlobalFrameRoutingId() override; RenderWidgetHostView* GetView() override; RenderFrameHostImpl* GetParent() override; RenderFrameHostImpl* GetMainFrame() override; @@ -664,8 +665,6 @@ // typically mean that the frame has been detached from the frame tree. virtual RenderWidgetHostImpl* GetRenderWidgetHost(); - GlobalFrameRoutingId GetGlobalFrameRoutingId(); - media::MediaMetricsProvider::RecordAggregateWatchTimeCallback GetRecordAggregateWatchTimeCallback();
diff --git a/content/browser/webauth/authenticator_impl_unittest.cc b/content/browser/webauth/authenticator_impl_unittest.cc index 4512f3f..e21c226 100644 --- a/content/browser/webauth/authenticator_impl_unittest.cc +++ b/content/browser/webauth/authenticator_impl_unittest.cc
@@ -60,6 +60,7 @@ #include "device/fido/fido_types.h" #include "device/fido/hid/fake_hid_impl_for_testing.h" #include "device/fido/mock_fido_device.h" +#include "device/fido/pin.h" #include "device/fido/public_key.h" #include "device/fido/test_callback_receiver.h" #include "device/fido/virtual_fido_device_factory.h" @@ -3644,8 +3645,11 @@ kUsePIN, }; - void ConfigureVirtualDevice(bool pin_uv_auth_token, int support_level) { + void ConfigureVirtualDevice(device::PINUVAuthProtocol pin_protocol, + bool pin_uv_auth_token, + int support_level) { device::VirtualCtap2Device::Config config; + config.pin_protocol = pin_protocol; config.pin_uv_auth_token_support = pin_uv_auth_token; config.ctap2_versions = {device::Ctap2Version::kCtap2_0, device::Ctap2Version::kCtap2_1}; @@ -3738,57 +3742,65 @@ test_client_.supports_pin = ui_support; for (int support_level = 0; support_level <= 2; support_level++) { - SCOPED_TRACE(kPINSupportDescription[support_level]); - ConfigureVirtualDevice(pin_uv_auth_token, support_level); + for (const auto pin_protocol : + {device::PINUVAuthProtocol::kV1, device::PINUVAuthProtocol::kV2}) { + SCOPED_TRACE(testing::Message() + << "support_level=" + << kPINSupportDescription[support_level] + << ", pin_protocol=" << static_cast<int>(pin_protocol)); + ConfigureVirtualDevice(pin_protocol, pin_uv_auth_token, + support_level); - for (int uv_level = 0; uv_level <= 2; uv_level++) { - SCOPED_TRACE(kUVDescription[uv_level]); + for (int uv_level = 0; uv_level <= 2; uv_level++) { + SCOPED_TRACE(kUVDescription[uv_level]); - switch (expected[support_level][uv_level]) { - case kNoPIN: - case kFailure: - // There shouldn't be any PIN prompts. - test_client_.expected.clear(); - break; + switch (expected[support_level][uv_level]) { + case kNoPIN: + case kFailure: + // There shouldn't be any PIN prompts. + test_client_.expected.clear(); + break; - case kSetPIN: - // A single PIN prompt to set a PIN is expected. - test_client_.expected = {{base::nullopt, kTestPIN}}; - break; + case kSetPIN: + // A single PIN prompt to set a PIN is expected. + test_client_.expected = {{base::nullopt, kTestPIN}}; + break; - case kUsePIN: - // A single PIN prompt to get the PIN is expected. - test_client_.expected = {{8, kTestPIN}}; - break; + case kUsePIN: + // A single PIN prompt to get the PIN is expected. + test_client_.expected = {{8, kTestPIN}}; + break; - default: - NOTREACHED(); - } + default: + NOTREACHED(); + } - MakeCredentialResult result = AuthenticatorMakeCredential( - make_credential_options(kUVLevel[uv_level])); + MakeCredentialResult result = AuthenticatorMakeCredential( + make_credential_options(kUVLevel[uv_level])); - switch (expected[support_level][uv_level]) { - case kFailure: - EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, result.status); - break; + switch (expected[support_level][uv_level]) { + case kFailure: + EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, + result.status); + break; - case kNoPIN: - EXPECT_EQ(AuthenticatorStatus::SUCCESS, result.status); - EXPECT_EQ("", virtual_device_factory_->mutable_state()->pin); - EXPECT_FALSE(HasUV(result.response)); - break; + case kNoPIN: + EXPECT_EQ(AuthenticatorStatus::SUCCESS, result.status); + EXPECT_EQ("", virtual_device_factory_->mutable_state()->pin); + EXPECT_FALSE(HasUV(result.response)); + break; - case kSetPIN: - case kUsePIN: - EXPECT_EQ(AuthenticatorStatus::SUCCESS, result.status); - EXPECT_EQ(kTestPIN, - virtual_device_factory_->mutable_state()->pin); - EXPECT_TRUE(HasUV(result.response)); - break; + case kSetPIN: + case kUsePIN: + EXPECT_EQ(AuthenticatorStatus::SUCCESS, result.status); + EXPECT_EQ(kTestPIN, + virtual_device_factory_->mutable_state()->pin); + EXPECT_TRUE(HasUV(result.response)); + break; - default: - NOTREACHED(); + default: + NOTREACHED(); + } } } } @@ -3873,49 +3885,58 @@ for (int support_level = 0; support_level <= 2; support_level++) { SCOPED_TRACE(kPINSupportDescription[support_level]); - ConfigureVirtualDevice(pin_uv_auth_token, support_level); + for (const auto pin_protocol : + {device::PINUVAuthProtocol::kV1, device::PINUVAuthProtocol::kV2}) { + SCOPED_TRACE(testing::Message() + << "support_level=" + << kPINSupportDescription[support_level] + << ", pin_protocol=" << static_cast<int>(pin_protocol)); + ConfigureVirtualDevice(pin_protocol, pin_uv_auth_token, + support_level); - for (int uv_level = 0; uv_level <= 2; uv_level++) { - SCOPED_TRACE(kUVDescription[uv_level]); + for (int uv_level = 0; uv_level <= 2; uv_level++) { + SCOPED_TRACE(kUVDescription[uv_level]); - switch (expected[support_level][uv_level]) { - case kNoPIN: - case kFailure: - // No PIN prompts are expected. - test_client_.expected.clear(); - break; + switch (expected[support_level][uv_level]) { + case kNoPIN: + case kFailure: + // No PIN prompts are expected. + test_client_.expected.clear(); + break; - case kUsePIN: - // A single prompt to get the PIN is expected. - test_client_.expected = {{8, kTestPIN}}; - break; + case kUsePIN: + // A single prompt to get the PIN is expected. + test_client_.expected = {{8, kTestPIN}}; + break; - default: - NOTREACHED(); - } + default: + NOTREACHED(); + } - GetAssertionResult result = AuthenticatorGetAssertion( - get_credential_options(kUVLevel[uv_level])); + GetAssertionResult result = AuthenticatorGetAssertion( + get_credential_options(kUVLevel[uv_level])); - switch (expected[support_level][uv_level]) { - case kFailure: - EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, result.status); - break; + switch (expected[support_level][uv_level]) { + case kFailure: + EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, + result.status); + break; - case kNoPIN: - EXPECT_EQ(AuthenticatorStatus::SUCCESS, result.status); - EXPECT_FALSE(HasUV(result.response)); - break; + case kNoPIN: + EXPECT_EQ(AuthenticatorStatus::SUCCESS, result.status); + EXPECT_FALSE(HasUV(result.response)); + break; - case kUsePIN: - EXPECT_EQ(AuthenticatorStatus::SUCCESS, result.status); - EXPECT_EQ(kTestPIN, - virtual_device_factory_->mutable_state()->pin); - EXPECT_TRUE(HasUV(result.response)); - break; + case kUsePIN: + EXPECT_EQ(AuthenticatorStatus::SUCCESS, result.status); + EXPECT_EQ(kTestPIN, + virtual_device_factory_->mutable_state()->pin); + EXPECT_TRUE(HasUV(result.response)); + break; - default: - NOTREACHED(); + default: + NOTREACHED(); + } } } }
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc index ff3e49c..9d93c4f 100644 --- a/content/child/runtime_features.cc +++ b/content/child/runtime_features.cc
@@ -261,8 +261,6 @@ {wf::EnableAutoplayIgnoresWebAudio, media::kAutoplayIgnoreWebAudio}, {wf::EnablePortals, blink::features::kPortals, kSetOnlyIfOverridden}, {wf::EnableImplicitRootScroller, blink::features::kImplicitRootScroller}, - {wf::EnableCSSOMViewScrollCoordinates, - blink::features::kCSSOMViewScrollCoordinates}, {wf::EnableTextFragmentAnchor, blink::features::kTextFragmentAnchor}, {wf::EnableBackgroundFetch, features::kBackgroundFetch}, {wf::EnableForcedColors, features::kForcedColors},
diff --git a/content/public/browser/render_frame_host.h b/content/public/browser/render_frame_host.h index 5f81954..8d9d112 100644 --- a/content/public/browser/render_frame_host.h +++ b/content/public/browser/render_frame_host.h
@@ -148,6 +148,10 @@ // Associated RenderProcessHost never changes. virtual RenderProcessHost* GetProcess() = 0; + // Returns the GlobalFrameRoutingId for this frame. Embedders should store + // this instead of a raw RenderFrameHost pointer. + virtual GlobalFrameRoutingId GetGlobalFrameRoutingId() = 0; + // Returns a StoragePartition associated with this RenderFrameHost. // Associated StoragePartition never changes. virtual StoragePartition* GetStoragePartition() = 0;
diff --git a/content/public/renderer/pepper_plugin_instance.h b/content/public/renderer/pepper_plugin_instance.h index e3bef985..d346ac65 100644 --- a/content/public/renderer/pepper_plugin_instance.h +++ b/content/public/renderer/pepper_plugin_instance.h
@@ -93,15 +93,6 @@ // or embedded in a page). virtual bool IsFullPagePlugin() = 0; - // Switches between fullscreen and normal mode. If |delay_report| is set to - // false, it may report the new state through DidChangeView immediately. If - // true, it will delay it. When called from the plugin, delay_report should - // be true to avoid re-entrancy. Returns true if the switch will be carried - // out, because of this call or because a switch was pending already anyway. - // Returns false if the switch will not be carried out because fullscreen mode - // is disallowed by a preference. - virtual bool FlashSetFullscreen(bool fullscreen, bool delay_report) = 0; - virtual bool IsRectTopmost(const gfx::Rect& rect) = 0; virtual int32_t Navigate(const ppapi::URLRequestInfoData& request,
diff --git a/content/public/test/fake_pepper_plugin_instance.cc b/content/public/test/fake_pepper_plugin_instance.cc index 5492c90..49e35c49 100644 --- a/content/public/test/fake_pepper_plugin_instance.cc +++ b/content/public/test/fake_pepper_plugin_instance.cc
@@ -55,11 +55,6 @@ return false; } -bool FakePepperPluginInstance::FlashSetFullscreen(bool fullscreen, - bool delay_report) { - return false; -} - bool FakePepperPluginInstance::IsRectTopmost(const gfx::Rect& rect) { return false; }
diff --git a/content/public/test/fake_pepper_plugin_instance.h b/content/public/test/fake_pepper_plugin_instance.h index 877d3691..c75baa28 100644 --- a/content/public/test/fake_pepper_plugin_instance.h +++ b/content/public/test/fake_pepper_plugin_instance.h
@@ -34,7 +34,6 @@ int plugin_child_id) override; void SetAlwaysOnTop(bool on_top) override; bool IsFullPagePlugin() override; - bool FlashSetFullscreen(bool fullscreen, bool delay_report) override; bool IsRectTopmost(const gfx::Rect& rect) override; int32_t Navigate(const ppapi::URLRequestInfoData& request, const char* target,
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn index 6434741..6a5a043 100644 --- a/content/renderer/BUILD.gn +++ b/content/renderer/BUILD.gn
@@ -457,7 +457,6 @@ "pepper/content_renderer_pepper_host_factory.h", "pepper/event_conversion.cc", "pepper/event_conversion.h", - "pepper/fullscreen_container.h", "pepper/gfx_conversion.h", "pepper/host_array_buffer_var.cc", "pepper/host_array_buffer_var.h", @@ -580,8 +579,6 @@ "pepper/video_decoder_shim.h", "pepper/video_encoder_shim.cc", "pepper/video_encoder_shim.h", - "render_widget_fullscreen_pepper.cc", - "render_widget_fullscreen_pepper.h", ] deps += [
diff --git a/content/renderer/pepper/fullscreen_container.h b/content/renderer/pepper/fullscreen_container.h deleted file mode 100644 index 4e8614d..0000000 --- a/content/renderer/pepper/fullscreen_container.h +++ /dev/null
@@ -1,39 +0,0 @@ -// Copyright (c) 2012 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_RENDERER_PEPPER_FULLSCREEN_CONTAINER_H_ -#define CONTENT_RENDERER_PEPPER_FULLSCREEN_CONTAINER_H_ - -#include "base/memory/ref_counted.h" - -namespace cc { -class Layer; -} - -namespace ui { -class Cursor; -} - -namespace content { - -// This class is like a lightweight WebPluginContainer for fullscreen PPAPI -// plugins, that only handles painting. -class FullscreenContainer { - public: - // Destroys the fullscreen window. This also destroys the FullscreenContainer - // instance. - virtual void Destroy() = 0; - - // Notifies the container that the mouse cursor has changed. - virtual void PepperDidChangeCursor(const ui::Cursor& cursor) = 0; - - virtual void SetLayer(scoped_refptr<cc::Layer> layer) = 0; - - protected: - virtual ~FullscreenContainer() {} -}; - -} // namespace content - -#endif // CONTENT_RENDERER_PEPPER_FULLSCREEN_CONTAINER_H_
diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.cc b/content/renderer/pepper/pepper_plugin_instance_impl.cc index b827ec2..9277824 100644 --- a/content/renderer/pepper/pepper_plugin_instance_impl.cc +++ b/content/renderer/pepper/pepper_plugin_instance_impl.cc
@@ -29,7 +29,6 @@ #include "content/public/common/use_zoom_for_dsf_policy.h" #include "content/public/renderer/content_renderer_client.h" #include "content/renderer/pepper/event_conversion.h" -#include "content/renderer/pepper/fullscreen_container.h" #include "content/renderer/pepper/gfx_conversion.h" #include "content/renderer/pepper/host_dispatcher_wrapper.h" #include "content/renderer/pepper/host_globals.h" @@ -55,7 +54,6 @@ #include "content/renderer/render_thread_impl.h" #include "content/renderer/render_view_impl.h" #include "content/renderer/render_widget.h" -#include "content/renderer/render_widget_fullscreen_pepper.h" #include "content/renderer/sad_plugin.h" #include "device/gamepad/public/cpp/gamepads.h" #include "ppapi/c/dev/ppp_text_input_dev.h" @@ -504,7 +502,6 @@ graphics2d_translation_(0, 0), graphics2d_scale_(1.f), container_(container), - layer_bound_to_fullscreen_(false), layer_is_hardware_(false), plugin_url_(plugin_url), document_url_(container ? GURL(container->GetDocument().Url()) : GURL()), @@ -529,8 +526,6 @@ uma_private_impl_(nullptr), plugin_print_interface_(nullptr), always_on_top_(false), - fullscreen_container_(nullptr), - flash_fullscreen_(false), desired_fullscreen_state_(false), message_channel_(nullptr), input_event_mask_(0), @@ -576,8 +571,6 @@ } PepperPluginInstanceImpl::~PepperPluginInstanceImpl() { - DCHECK(!fullscreen_container_); - // Notify all the plugin objects of deletion. This will prevent blink from // calling into the plugin any more. // @@ -687,11 +680,6 @@ original_instance_interface_.reset(); instance_interface_.reset(); - if (fullscreen_container_) { - fullscreen_container_->Destroy(); - fullscreen_container_ = nullptr; - } - // Force-unbind any Graphics. In the case of Graphics2D, if the plugin // leaks the graphics 2D, it may actually get cleaned up after our // destruction, so we need its pointers to be up to date. @@ -724,18 +712,13 @@ } void PepperPluginInstanceImpl::InvalidateRect(const gfx::Rect& rect) { - if (fullscreen_container_) { - // The fullscreen container uses a composited layer, which we invalidate - // directly below via SetNeedsDisplay(). - } else { - if (!container_ || view_data_.rect.size.width == 0 || - view_data_.rect.size.height == 0) - return; // Nothing to do. - if (rect.IsEmpty()) - container_->Invalidate(); - else - container_->InvalidateRect(rect); - } + if (!container_ || view_data_.rect.size.width == 0 || + view_data_.rect.size.height == 0) + return; // Nothing to do. + if (rect.IsEmpty()) + container_->Invalidate(); + else + container_->InvalidateRect(rect); if (texture_layer_) { if (rect.IsEmpty()) { @@ -811,7 +794,6 @@ // Free any associated graphics. SetFullscreen(false); - FlashSetFullscreen(false, false); // Unbind current 2D or 3D graphics context. BindGraphics(pp_instance(), 0); InvalidateRect(gfx::Rect()); @@ -1303,8 +1285,6 @@ } } - UpdateFlashFullscreenState(fullscreen_container_ != nullptr); - // During plugin initialization, there are often re-layouts. Avoid sending // intermediate sizes the plugin and throttler. if (sent_initial_did_change_view_) @@ -1717,7 +1697,7 @@ } bool PepperPluginInstanceImpl::PluginHasFocus() const { - return flash_fullscreen_ || has_webkit_focus_; + return has_webkit_focus_; } void PepperPluginInstanceImpl::SendFocusChangeNotification() { @@ -1859,7 +1839,7 @@ // If this call was delayed, we may have transitioned back to fullscreen in // the mean time, so only report the geometry if we are actually in normal // mode. - if (container_ && !fullscreen_container_ && !flash_fullscreen_) + if (container_) container_->ReportGeometry(); } @@ -2049,10 +2029,6 @@ // NOTE: plugin instance may have been deleted. } -bool PepperPluginInstanceImpl::FlashIsFullscreenOrPending() { - return fullscreen_container_ != nullptr; -} - bool PepperPluginInstanceImpl::IsFullscreenOrPending() { return desired_fullscreen_state_; } @@ -2067,9 +2043,20 @@ if (fullscreen == IsFullscreenOrPending()) return false; - if (!SetFullscreenCommon(fullscreen)) + if (!render_frame_) return false; + if (fullscreen) { + if (!render_frame_->render_view() + ->renderer_preferences() + .plugin_fullscreen_allowed) { + return false; + } + + if (!HasTransientUserActivation()) + return false; + } + // Check whether we are trying to switch while the state is in transition. // The 2nd request gets dropped while messing up the internal state, so // disallow this. @@ -2091,36 +2078,6 @@ return true; } -void PepperPluginInstanceImpl::UpdateFlashFullscreenState( - bool flash_fullscreen) { - bool is_mouselock_pending = TrackedCallback::IsPending(lock_mouse_callback_); - - if (flash_fullscreen == flash_fullscreen_) { - // Manually clear callback when fullscreen fails with mouselock pending. - if (!flash_fullscreen && is_mouselock_pending) - lock_mouse_callback_->Run(PP_ERROR_FAILED); - return; - } - - UpdateLayer(false); - - bool old_plugin_focus = PluginHasFocus(); - flash_fullscreen_ = flash_fullscreen; - if (is_mouselock_pending && !IsMouseLocked()) { - if (!HasTransientUserActivation() && - !module_->permissions().HasPermission( - ppapi::PERMISSION_BYPASS_USER_GESTURE)) { - lock_mouse_callback_->Run(PP_ERROR_NO_USER_GESTURE); - } else { - if (!LockMouse(/*request_unadjusted_movement=*/false)) - lock_mouse_callback_->Run(PP_ERROR_FAILED); - } - } - - if (PluginHasFocus() != old_plugin_focus) - SendFocusChangeNotification(); -} - void PepperPluginInstanceImpl::UpdateLayer(bool force_creation) { if (!container_) return; @@ -2136,17 +2093,13 @@ } if (!force_creation && (want_texture_layer == !!texture_layer_) && - (want_3d_layer == layer_is_hardware_) && - layer_bound_to_fullscreen_ == !!fullscreen_container_) { + (want_3d_layer == layer_is_hardware_)) { UpdateLayerTransform(); return; } if (texture_layer_) { - if (!layer_bound_to_fullscreen_) - container_->SetCcLayer(nullptr, false); - else if (fullscreen_container_) - fullscreen_container_->SetLayer(nullptr); + container_->SetCcLayer(nullptr, false); texture_layer_->ClearClient(); texture_layer_ = nullptr; } @@ -2170,20 +2123,15 @@ // Ignore transparency in fullscreen, since that's what Flash always // wants to do, and that lets it not recreate a context if // wmode=transparent was specified. - opaque = opaque || fullscreen_container_; texture_layer_->SetContentsOpaque(opaque); } if (texture_layer_) { - if (fullscreen_container_) - fullscreen_container_->SetLayer(texture_layer_); - else - container_->SetCcLayer(texture_layer_.get(), true); + container_->SetCcLayer(texture_layer_.get(), true); if (is_flash_plugin_) texture_layer_->SetMayContainVideo(true); } - layer_bound_to_fullscreen_ = !!fullscreen_container_; layer_is_hardware_ = want_3d_layer; UpdateLayerTransform(); } @@ -2364,10 +2312,8 @@ return PP_TRUE; } - // Refuse to bind if in transition to fullscreen with PPB_FlashFullscreen or - // to/from fullscreen with PPB_Fullscreen. - if ((fullscreen_container_ && !flash_fullscreen_) || - desired_fullscreen_state_ != view_data_.is_fullscreen) + // Refuse to bind if in transition to/from fullscreen with PPB_Fullscreen. + if (desired_fullscreen_state_ != view_data_.is_fullscreen) return PP_FALSE; const ppapi::host::PpapiHost* ppapi_host = @@ -2420,10 +2366,6 @@ return &view_data_; } -PP_Bool PepperPluginInstanceImpl::FlashIsFullscreen(PP_Instance instance) { - return PP_FromBool(flash_fullscreen_); -} - PP_Var PepperPluginInstanceImpl::GetWindowObject(PP_Instance instance) { if (!container_) return PP_MakeUndefined(); @@ -2595,23 +2537,13 @@ PP_Bool PepperPluginInstanceImpl::GetScreenSize(PP_Instance instance, PP_Size* size) { - if (flash_fullscreen_) { - // Workaround for Flash rendering bug: Flash is assuming the fullscreen view - // size will be equal to the physical screen size. However, the fullscreen - // view is sized by the browser UI, and may not be the same size as the - // screen or the desktop. Therefore, report the view size as the screen - // size when in fullscreen mode. http://crbug.com/506016 - // TODO(miu): Remove this workaround once Flash has been fixed. - *size = view_data_.rect.size; - } else { - // All other cases: Report the screen size. - if (!render_frame_) - return PP_FALSE; - blink::ScreenInfo info = render_frame_->GetLocalRootRenderWidget() - ->GetWebWidget() - ->GetScreenInfo(); - *size = PP_MakeSize(info.rect.width(), info.rect.height()); - } + // All other cases: Report the screen size. + if (!render_frame_) + return PP_FALSE; + blink::ScreenInfo info = render_frame_->GetLocalRootRenderWidget() + ->GetWebWidget() + ->GetScreenInfo(); + *size = PP_MakeSize(info.rect.width(), info.rect.height()); return PP_TRUE; } @@ -2736,13 +2668,6 @@ if (!HasTransientUserActivation()) return PP_ERROR_NO_USER_GESTURE; - // Attempt mouselock only if Flash isn't waiting on fullscreen, otherwise - // we wait and call LockMouse() in UpdateFlashFullscreenState(). - if (!FlashIsFullscreenOrPending() || flash_fullscreen_) { - if (!LockMouse(false)) - return PP_ERROR_FAILED; - } - // Either mouselock succeeded or a Flash fullscreen is pending. lock_mouse_callback_ = callback; return PP_OK_COMPLETIONPENDING; @@ -3037,9 +2962,7 @@ return; cursor_ = std::move(cursor); - if (fullscreen_container_) { - fullscreen_container_->PepperDidChangeCursor(*cursor_); - } else if (render_frame_) { + if (render_frame_) { // Update the cursor appearance immediately if the requesting plugin is the // one which receives the last mouse event. Otherwise, the new cursor won't // be picked up until the plugin gets the next input event. That is bad if, @@ -3062,49 +2985,7 @@ .IsPluginDocument(); } -bool PepperPluginInstanceImpl::FlashSetFullscreen(bool fullscreen, - bool delay_report) { - TRACE_EVENT0("ppapi", "PepperPluginInstanceImpl::FlashSetFullscreen"); - // Keep a reference on the stack. See NOTE above. - scoped_refptr<PepperPluginInstanceImpl> ref(this); - - // We check whether we are trying to switch to the state we're already going - // to (i.e. if we're already switching to fullscreen but the fullscreen - // container isn't ready yet, don't do anything more). - if (fullscreen == FlashIsFullscreenOrPending()) - return true; - - if (!SetFullscreenCommon(fullscreen)) - return false; - - // Unbind current 2D or 3D graphics context. - DVLOG(1) << "Setting fullscreen to " << (fullscreen ? "on" : "off"); - if (fullscreen) { - DCHECK(!fullscreen_container_); - fullscreen_container_ = - render_frame_->CreatePepperFullscreenContainer(this); - UpdateLayer(false); - } else { - DCHECK(fullscreen_container_); - fullscreen_container_->Destroy(); - fullscreen_container_ = nullptr; - UpdateFlashFullscreenState(false); - if (!delay_report) { - ReportGeometry(); - } else { - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::BindOnce(&PepperPluginInstanceImpl::ReportGeometry, this)); - } - } - - return true; -} - bool PepperPluginInstanceImpl::IsRectTopmost(const gfx::Rect& rect) { - if (flash_fullscreen_) - return true; - return container_->IsRectTopmost(rect); } @@ -3239,23 +3120,6 @@ element.SetAttribute(WebString::FromUTF8(kStyle), style_before_fullscreen_); } -bool PepperPluginInstanceImpl::SetFullscreenCommon(bool fullscreen) const { - if (!render_frame_) - return false; - - if (fullscreen) { - if (!render_frame_->render_view() - ->renderer_preferences() - .plugin_fullscreen_allowed) { - return false; - } - - if (!HasTransientUserActivation()) - return false; - } - return true; -} - bool PepperPluginInstanceImpl::IsMouseLocked() { return GetMouseLockDispatcher()->IsMouseLockedTo( GetOrCreateLockTargetAdapter()); @@ -3277,11 +3141,6 @@ } MouseLockDispatcher* PepperPluginInstanceImpl::GetMouseLockDispatcher() { - if (flash_fullscreen_) { - RenderWidgetFullscreenPepper* container = - static_cast<RenderWidgetFullscreenPepper*>(fullscreen_container_); - return container->mouse_lock_dispatcher(); - } if (render_frame_) return render_frame_->GetLocalRootRenderWidget()->mouse_lock_dispatcher(); return nullptr;
diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.h b/content/renderer/pepper/pepper_plugin_instance_impl.h index fbd7512..04715d77b 100644 --- a/content/renderer/pepper/pepper_plugin_instance_impl.h +++ b/content/renderer/pepper/pepper_plugin_instance_impl.h
@@ -104,7 +104,6 @@ namespace content { -class FullscreenContainer; class MessageChannel; class PepperAudioController; class PepperGraphics2DHost; @@ -279,38 +278,6 @@ bool CanRotateView(); void RotateView(blink::WebPlugin::RotationType type); - // There are 2 implementations of the fullscreen interface - // PPB_FlashFullscreen is used by Pepper Flash. - // PPB_Fullscreen is intended for other applications including NaCl. - // The two interface are mutually exclusive. - - // Implementation of PPB_FlashFullscreen. - - // Because going to fullscreen is asynchronous (but going out is not), there - // are 3 states: - // - normal : fullscreen_container_ == NULL - // flash_fullscreen_ == false - // - fullscreen pending: fullscreen_container_ != NULL - // flash_fullscreen_ == false - // - fullscreen : fullscreen_container_ != NULL - // flash_fullscreen_ == true - // - // In normal state, events come from webkit and painting goes back to it. - // In fullscreen state, events come from the fullscreen container, and - // painting goes back to it. - // In pending state, events from webkit are ignored, and as soon as we - // receive events from the fullscreen container, we go to the fullscreen - // state. - bool FlashIsFullscreenOrPending(); - - // Updates |flash_fullscreen_| and sends focus change notification if - // necessary. - void UpdateFlashFullscreenState(bool flash_fullscreen); - - FullscreenContainer* fullscreen_container() const { - return fullscreen_container_; - } - // Implementation of PPB_Fullscreen. // Because going to/from fullscreen is asynchronous, there are 4 states: @@ -324,8 +291,6 @@ // view_data_.is_fullscreen = true bool IsFullscreenOrPending(); - bool flash_fullscreen() const { return flash_fullscreen_; } - // Switches between fullscreen and normal mode. The transition is // asynchronous. WebKit will trigger corresponding ViewChanged calls. Returns // true on success, false on failure (e.g. trying to enter fullscreen without @@ -391,7 +356,6 @@ int plugin_child_id) override; void SetAlwaysOnTop(bool on_top) override; bool IsFullPagePlugin() override; - bool FlashSetFullscreen(bool fullscreen, bool delay_report) override; bool IsRectTopmost(const gfx::Rect& rect) override; int32_t Navigate(const ppapi::URLRequestInfoData& request, const char* target, @@ -421,7 +385,6 @@ PP_Bool BindGraphics(PP_Instance instance, PP_Resource device) override; PP_Bool IsFullFrame(PP_Instance instance) override; const ppapi::ViewData* GetViewData(PP_Instance instance) override; - PP_Bool FlashIsFullscreen(PP_Instance instance) override; PP_Var GetWindowObject(PP_Instance instance) override; PP_Var GetOwnerElementObject(PP_Instance instance) override; PP_Var ExecuteScript(PP_Instance instance, @@ -645,9 +608,6 @@ void SetSizeAttributesForFullscreen(); void ResetSizeAttributesAfterFullscreen(); - // Shared code between SetFullscreen() and FlashSetFullscreen(). - bool SetFullscreenCommon(bool fullscreen) const; - bool IsMouseLocked(); bool LockMouse(bool request_unadjusted_movement); MouseLockDispatcher* GetMouseLockDispatcher(); @@ -704,7 +664,6 @@ // NULL until we have been initialized. blink::WebPluginContainer* container_; scoped_refptr<cc::TextureLayer> texture_layer_; - bool layer_bound_to_fullscreen_; bool layer_is_hardware_; // Plugin URL. @@ -801,18 +760,6 @@ // to use a more optimized painting path in some cases. bool always_on_top_; - // Implementation of PPB_FlashFullscreen. - - // Plugin container for fullscreen mode. NULL if not in fullscreen mode. Note: - // there is a transition state where fullscreen_container_ is non-NULL but - // flash_fullscreen_ is false (see above). - FullscreenContainer* fullscreen_container_; - - // True if we are in "flash" fullscreen mode. False if we are in normal mode - // or in transition to fullscreen. Normal fullscreen mode is indicated in - // the ViewData. - bool flash_fullscreen_; - // Implementation of PPB_Fullscreen. // Since entering fullscreen mode is an asynchronous operation, we set this
diff --git a/content/renderer/pepper/pepper_webplugin_impl.cc b/content/renderer/pepper/pepper_webplugin_impl.cc index 3306935..7da0d05 100644 --- a/content/renderer/pepper/pepper_webplugin_impl.cc +++ b/content/renderer/pepper/pepper_webplugin_impl.cc
@@ -199,7 +199,7 @@ void PepperWebPluginImpl::Paint(cc::PaintCanvas* canvas, const WebRect& rect) { // Re-entrancy may cause JS to try to execute script on the plugin before it // is fully initialized. See: crbug.com/715747. - if (instance_ && !instance_->FlashIsFullscreenOrPending()) + if (instance_) instance_->Paint(canvas, plugin_rect_, rect); } @@ -209,7 +209,7 @@ const WebRect& unobscured_rect, bool is_visible) { plugin_rect_ = window_rect; - if (instance_ && !instance_->FlashIsFullscreenOrPending()) + if (instance_) instance_->ViewChanged(plugin_rect_, clip_rect, unobscured_rect); } @@ -253,7 +253,7 @@ ui::Cursor* cursor) { // Re-entrancy may cause JS to try to execute script on the plugin before it // is fully initialized. See: crbug.com/715747. - if (!instance_ || instance_->FlashIsFullscreenOrPending()) + if (!instance_) return blink::WebInputEventResult::kNotHandled; return instance_->HandleCoalescedInputEvent(coalesced_event, cursor) ? blink::WebInputEventResult::kHandledApplication
diff --git a/content/renderer/pepper/renderer_ppapi_host_impl.cc b/content/renderer/pepper/renderer_ppapi_host_impl.cc index c01b42d..db3962ac 100644 --- a/content/renderer/pepper/renderer_ppapi_host_impl.cc +++ b/content/renderer/pepper/renderer_ppapi_host_impl.cc
@@ -11,7 +11,6 @@ #include "base/process/process_handle.h" #include "base/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" -#include "content/renderer/pepper/fullscreen_container.h" #include "content/renderer/pepper/host_globals.h" #include "content/renderer/pepper/pepper_browser_connection.h" #include "content/renderer/pepper/pepper_graphics_2d_host.h" @@ -20,7 +19,6 @@ #include "content/renderer/pepper/pepper_plugin_instance_impl.h" #include "content/renderer/pepper/plugin_module.h" #include "content/renderer/render_view_impl.h" -#include "content/renderer/render_widget_fullscreen_pepper.h" #include "ipc/ipc_message.h" #include "ipc/ipc_platform_file.h" #include "ppapi/host/ppapi_host.h" @@ -192,10 +190,6 @@ PepperPluginInstanceImpl* plugin_instance = GetAndValidateInstance(instance); if (!plugin_instance) return 0; - if (plugin_instance->flash_fullscreen()) { - FullscreenContainer* container = plugin_instance->fullscreen_container(); - return static_cast<RenderWidgetFullscreenPepper*>(container)->routing_id(); - } return GetRenderViewForInstance(instance)->GetRoutingID(); } @@ -203,11 +197,8 @@ PP_Instance instance, const gfx::Point& pt) { PepperPluginInstanceImpl* plugin_instance = GetAndValidateInstance(instance); - if (!plugin_instance || plugin_instance->flash_fullscreen()) { - // Flash fullscreen is special in that it renders into its own separate, - // dedicated window. So, do not offset the point. + if (!plugin_instance) return pt; - } return gfx::Point((pt.x() + plugin_instance->view_data().rect.point.x) / viewport_to_dip_scale_, (pt.y() + plugin_instance->view_data().rect.point.y) /
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 3b2626c..b0a4392 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -119,7 +119,6 @@ #include "content/renderer/render_process.h" #include "content/renderer/render_thread_impl.h" #include "content/renderer/render_view_impl.h" -#include "content/renderer/render_widget_fullscreen_pepper.h" #include "content/renderer/renderer_blink_platform_impl.h" #include "content/renderer/service_worker/service_worker_network_provider_for_frame.h" #include "content/renderer/service_worker/web_service_worker_provider_impl.h" @@ -2176,49 +2175,6 @@ SyncSelectionIfRequired(); } -RenderWidgetFullscreenPepper* RenderFrameImpl::CreatePepperFullscreenContainer( - PepperPluginInstanceImpl* plugin) { - // Get the URL of the main frame if possible. - blink::WebURL main_frame_url; - WebFrame* main_frame = render_view()->GetWebView()->MainFrame(); - if (main_frame->IsWebLocalFrame()) - main_frame_url = main_frame->ToWebLocalFrame()->GetDocument().Url(); - - mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget; - mojo::PendingAssociatedReceiver<blink::mojom::Widget> blink_widget_receiver = - blink_widget.InitWithNewEndpointAndPassReceiver(); - - mojo::PendingAssociatedRemote<blink::mojom::WidgetHost> blink_widget_host; - mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost> - blink_widget_host_receiver = - blink_widget_host.InitWithNewEndpointAndPassReceiver(); - - // Synchronous IPC to obtain a routing id for the fullscreen widget. - int32_t fullscreen_widget_routing_id = MSG_ROUTING_NONE; - if (!GetFrameHost()->CreateNewFullscreenWidget( - std::move(blink_widget_host_receiver), std::move(blink_widget), - &fullscreen_widget_routing_id)) { - return nullptr; - } - RenderWidget::ShowCallback show_callback = - base::BindOnce(&RenderViewImpl::ShowCreatedFullscreenWidget, - render_view()->GetWeakPtr()); - - RenderWidgetFullscreenPepper* widget = RenderWidgetFullscreenPepper::Create( - agent_scheduling_group_, fullscreen_widget_routing_id, - std::move(show_callback), GetLocalRootRenderWidget()->compositor_deps(), - GetLocalRootRenderWidget()->GetWebWidget()->GetOriginalScreenInfo(), - plugin, std::move(main_frame_url), std::move(blink_widget_host), - std::move(blink_widget_receiver)); - // TODO(nick): The show() handshake seems like unnecessary complexity here, - // since there's no real delay between CreateFullscreenWidget and - // ShowCreatedFullscreenWidget. Would it be simpler to have the - // CreateFullscreenWidget mojo method implicitly show the window, and skip the - // subsequent step? - widget->Show(blink::kWebNavigationPolicyCurrentTab); - return widget; -} - bool RenderFrameImpl::IsPepperAcceptingCompositionEvents() const { if (!focused_pepper_plugin_) return false;
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index 7c18f07..c8620c02 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h
@@ -161,7 +161,6 @@ class RenderFrameObserver; class RenderViewImpl; class RenderWidget; -class RenderWidgetFullscreenPepper; struct CustomContextMenuContext; struct FrameReplicationState; @@ -353,10 +352,6 @@ // Informs the render view that a PPAPI plugin has changed selection. void PepperSelectionChanged(PepperPluginInstanceImpl* instance); - // Creates a fullscreen container for a pepper plugin instance. - RenderWidgetFullscreenPepper* CreatePepperFullscreenContainer( - PepperPluginInstanceImpl* plugin); - bool IsPepperAcceptingCompositionEvents() const; // Notification that the given plugin has crashed.
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index fec5e231..e74bd8f 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc
@@ -70,7 +70,6 @@ #include "content/renderer/render_frame_proxy.h" #include "content/renderer/render_process.h" #include "content/renderer/render_thread_impl.h" -#include "content/renderer/render_widget_fullscreen_pepper.h" #include "content/renderer/renderer_blink_platform_impl.h" #include "content/renderer/v8_value_converter_impl.h" #include "content/renderer/web_ui_extension_data.h"
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index 1e83fdb..bdd9dfa0 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -264,14 +264,6 @@ Initialize(std::move(show_callback), web_page_popup, screen_info); } -void RenderWidget::InitForPepperFullscreen( - ShowCallback show_callback, - blink::WebWidget* web_widget, - const blink::ScreenInfo& screen_info) { - for_pepper_fullscreen_ = true; - Initialize(std::move(show_callback), web_widget, screen_info); -} - void RenderWidget::InitForMainFrame(ShowCallback show_callback, blink::WebFrameWidget* web_frame_widget, const blink::ScreenInfo& screen_info, @@ -357,7 +349,7 @@ } void RenderWidget::OnClose() { - DCHECK(for_popup_ || for_pepper_fullscreen_); + DCHECK(for_popup_); Close(base::WrapUnique(this)); }
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h index 493b515..30f7c2c 100644 --- a/content/renderer/render_widget.h +++ b/content/renderer/render_widget.h
@@ -89,7 +89,6 @@ // // RenderWidget is used to implement: // - RenderViewImpl (deprecated) -// - Fullscreen mode (RenderWidgetFullScreen) // - Popup "menus" (like the color chooser and date picker) // - Widgets for frames (the main frame, and subframes due to out-of-process // iframe support) @@ -161,12 +160,6 @@ blink::WebPagePopup* web_page_popup, const blink::ScreenInfo& screen_info); - // Initialize a new RenderWidget for pepper fullscreen. The |show_callback| is - // called when RenderWidget::Show() happens. - void InitForPepperFullscreen(ShowCallback show_callback, - blink::WebWidget* web_widget, - const blink::ScreenInfo& screen_info); - // Initialize a new RenderWidget that will be attached to a RenderFrame (via // the WebFrameWidget), for a frame that is a main frame. void InitForMainFrame(ShowCallback show_callback, @@ -335,8 +328,7 @@ // Returns the WebFrameWidget associated with this RenderWidget if any. // Returns nullptr if GetWebWidget() returns nullptr or returns a WebWidget // that is not a WebFrameWidget. A WebFrameWidget only makes sense when there - // a local root associated with it. RenderWidgetFullscreenPepper and a swapped - // out RenderWidgets are amongst the cases where this method returns nullptr. + // a local root associated with it. blink::WebFrameWidget* GetFrameWidget() const; #if BUILDFLAG(ENABLE_PLUGINS) @@ -401,13 +393,12 @@ // that are not for a frame (eg popups) and excludes the widget for the main // frame (which is attached to the RenderViewImpl). bool for_child_local_root_frame_ = false; - // RenderWidgets are created for frames, popups and pepper fullscreen. In the + // RenderWidgets are created for frames and popups. In the // former case, the caller frame takes ownership and eventually passes the // unique_ptr back in Close(). In the latter cases, the browser process takes // ownership via IPC. These booleans exist to allow us to confirm than an IPC - // message to kill the render widget is coming for a popup or fullscreen. + // message to kill the render widget is coming for a popup. bool for_popup_ = false; - bool for_pepper_fullscreen_ = false; // A callback into the creator/opener of this widget, to be executed when // WebWidgetClient::Show() occurs.
diff --git a/content/renderer/render_widget_fullscreen_pepper.cc b/content/renderer/render_widget_fullscreen_pepper.cc deleted file mode 100644 index eb8e7fa..0000000 --- a/content/renderer/render_widget_fullscreen_pepper.cc +++ /dev/null
@@ -1,370 +0,0 @@ -// Copyright (c) 2012 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 "content/renderer/render_widget_fullscreen_pepper.h" - -#include <vector> - -#include "base/bind.h" -#include "base/command_line.h" -#include "base/macros.h" -#include "build/build_config.h" -#include "cc/paint/paint_canvas.h" -#include "content/common/view_messages.h" -#include "content/common/widget_messages.h" -#include "content/public/common/content_switches.h" -#include "content/public/common/use_zoom_for_dsf_policy.h" -#include "content/renderer/pepper/pepper_plugin_instance_impl.h" -#include "content/renderer/render_thread_impl.h" -#include "gpu/ipc/client/gpu_channel_host.h" -#include "skia/ext/platform_canvas.h" -#include "third_party/blink/public/common/input/web_gesture_event.h" -#include "third_party/blink/public/common/input/web_mouse_wheel_event.h" -#include "third_party/blink/public/platform/web_size.h" -#include "third_party/blink/public/web/web_local_frame.h" -#include "third_party/blink/public/web/web_widget.h" -#include "ui/base/cursor/cursor.h" -#include "ui/gfx/geometry/dip_util.h" -#include "ui/gfx/geometry/size_conversions.h" -#include "ui/gl/gpu_preference.h" - -using blink::WebCoalescedInputEvent; -using blink::WebGestureEvent; -using blink::WebInputEvent; -using blink::WebInputEventResult; -using blink::WebMouseEvent; -using blink::WebMouseWheelEvent; -using blink::WebRect; -using blink::WebSize; -using blink::WebString; -using blink::WebTextInputType; -using blink::WebVector; - -namespace content { - -namespace { - -class FullscreenMouseLockDispatcher : public MouseLockDispatcher { - public: - explicit FullscreenMouseLockDispatcher(RenderWidgetFullscreenPepper* widget); - ~FullscreenMouseLockDispatcher() override; - - private: - // MouseLockDispatcher implementation. - void SendLockMouseRequest(blink::WebLocalFrame* requester_frame, - bool request_unadjusted_movement) override; - - RenderWidgetFullscreenPepper* widget_; - - base::WeakPtrFactory<FullscreenMouseLockDispatcher> weak_ptr_factory_{this}; - - DISALLOW_COPY_AND_ASSIGN(FullscreenMouseLockDispatcher); -}; - -WebMouseEvent WebMouseEventFromGestureEvent(const WebGestureEvent& gesture) { - // Only convert touch screen gesture events, do not convert - // touchpad/mouse wheel gesture events. (crbug.com/620974) - if (gesture.SourceDevice() != blink::WebGestureDevice::kTouchscreen) - return WebMouseEvent(); - - WebInputEvent::Type type = WebInputEvent::Type::kUndefined; - switch (gesture.GetType()) { - case WebInputEvent::Type::kGestureScrollBegin: - type = WebInputEvent::Type::kMouseDown; - break; - case WebInputEvent::Type::kGestureScrollUpdate: - type = WebInputEvent::Type::kMouseMove; - break; - case WebInputEvent::Type::kGestureFlingStart: - // A scroll gesture on the touchscreen may end with a GestureScrollEnd - // when there is no velocity, or a GestureFlingStart when it has a - // velocity. In both cases, it should end the drag that was initiated by - // the GestureScrollBegin (and subsequent GestureScrollUpdate) events. - type = WebInputEvent::Type::kMouseUp; - break; - case WebInputEvent::Type::kGestureScrollEnd: - type = WebInputEvent::Type::kMouseUp; - break; - default: - return WebMouseEvent(); - } - - WebMouseEvent mouse(type, - gesture.GetModifiers() | WebInputEvent::kLeftButtonDown, - gesture.TimeStamp()); - mouse.button = WebMouseEvent::Button::kLeft; - mouse.click_count = (mouse.GetType() == WebInputEvent::Type::kMouseDown || - mouse.GetType() == WebInputEvent::Type::kMouseUp); - - mouse.SetPositionInWidget(gesture.PositionInWidget()); - mouse.SetPositionInScreen(gesture.PositionInScreen()); - - return mouse; -} - -FullscreenMouseLockDispatcher::FullscreenMouseLockDispatcher( - RenderWidgetFullscreenPepper* widget) - : widget_(widget) {} - -FullscreenMouseLockDispatcher::~FullscreenMouseLockDispatcher() = default; - -void FullscreenMouseLockDispatcher::SendLockMouseRequest( - blink::WebLocalFrame* requester_frame, - bool request_unadjusted_movement) { - bool has_transient_user_activation = - requester_frame ? requester_frame->HasTransientUserActivation() : false; - - widget_->GetWebWidget()->RequestMouseLock( - has_transient_user_activation, /*privileged=*/true, - request_unadjusted_movement, - base::BindOnce(&MouseLockDispatcher::OnLockMouseACK, - weak_ptr_factory_.GetWeakPtr())); -} - -} // anonymous namespace - -// We place the WebExternalWidgetClient interface on a separate class because -// RenderWidget implements blink::WebWidgetClient, which is not used for -// WebExternalWidgets, but may have similar method definitions as this -// interface. -class PepperExternalWidgetClient : public blink::WebExternalWidgetClient { - public: - explicit PepperExternalWidgetClient(RenderWidgetFullscreenPepper* widget) - : widget_(widget) {} - ~PepperExternalWidgetClient() override = default; - - // blink::WebExternalWidgetClient overrides: - blink::WebInputEventResult HandleInputEvent( - const blink::WebCoalescedInputEvent& event) override { - return widget_->ProcessInputEvent(event); - } - - blink::WebInputEventResult DispatchBufferedTouchEvents() override { - return WebInputEventResult::kNotHandled; - } - - void DidResize(const gfx::Size& size) override { widget_->DidResize(size); } - - void RecordTimeToFirstActivePaint(base::TimeDelta duration) override { - widget_->RecordTimeToFirstActivePaint(duration); - } - - void DidCommitAndDrawCompositorFrame() override { - widget_->DidInitiatePaint(); - } - - void DidUpdateVisualProperties() override { widget_->UpdateLayerBounds(); } - - private: - RenderWidgetFullscreenPepper* widget_; -}; - -// static -RenderWidgetFullscreenPepper* RenderWidgetFullscreenPepper::Create( - AgentSchedulingGroup& agent_scheduling_group, - int32_t routing_id, - RenderWidget::ShowCallback show_callback, - CompositorDependencies* compositor_deps, - const blink::ScreenInfo& screen_info, - PepperPluginInstanceImpl* plugin, - const blink::WebURL& local_main_frame_url, - mojo::PendingAssociatedRemote<blink::mojom::WidgetHost> blink_widget_host, - mojo::PendingAssociatedReceiver<blink::mojom::Widget> blink_widget) { - DCHECK_NE(MSG_ROUTING_NONE, routing_id); - DCHECK(show_callback); - RenderWidgetFullscreenPepper* render_widget = - new RenderWidgetFullscreenPepper( - agent_scheduling_group, routing_id, compositor_deps, plugin, - std::move(blink_widget_host), std::move(blink_widget), - local_main_frame_url); - render_widget->InitForPepperFullscreen(std::move(show_callback), - render_widget->blink_widget_.get(), - screen_info); - return render_widget; -} - -RenderWidgetFullscreenPepper::RenderWidgetFullscreenPepper( - AgentSchedulingGroup& agent_scheduling_group, - int32_t routing_id, - CompositorDependencies* compositor_deps, - PepperPluginInstanceImpl* plugin, - mojo::PendingAssociatedRemote<blink::mojom::WidgetHost> mojo_widget_host, - mojo::PendingAssociatedReceiver<blink::mojom::Widget> mojo_widget, - blink::WebURL main_frame_url) - : RenderWidget(agent_scheduling_group, routing_id, compositor_deps), - plugin_(plugin), - mouse_lock_dispatcher_( - std::make_unique<FullscreenMouseLockDispatcher>(this)), - widget_client_(std::make_unique<PepperExternalWidgetClient>(this)) { - blink_widget_ = blink::WebExternalWidget::Create( - widget_client_.get(), main_frame_url, std::move(mojo_widget_host), - std::move(mojo_widget)); -} - -RenderWidgetFullscreenPepper::~RenderWidgetFullscreenPepper() = default; - -void RenderWidgetFullscreenPepper::Destroy() { - // The plugin instance is going away reset any lock target that is set - // on the dispatcher since this object can still live and receive IPC - // responses and may call a dangling lock_target. - mouse_lock_dispatcher_->ClearLockTarget(); - - // This function is called by the plugin instance as it's going away, so reset - // plugin_ to NULL to avoid calling into a dangling pointer e.g. on Close(). - plugin_ = nullptr; - - // After calling Destroy(), the plugin instance assumes that the layer is not - // used by us anymore, so it may destroy the layer before this object goes - // away. - SetLayer(nullptr); - - // This instructs the browser process, which owns this object, to send back a - // WidgetMsg_Close to destroy this object. - Send(new WidgetHostMsg_Close(routing_id())); -} - -void RenderWidgetFullscreenPepper::PepperDidChangeCursor( - const ui::Cursor& cursor) { - blink_widget_->SetCursor(cursor); -} - -void RenderWidgetFullscreenPepper::SetLayer(scoped_refptr<cc::Layer> layer) { - layer_ = layer.get(); - if (!layer_) { - blink_widget_->SetRootLayer(nullptr); - return; - } - UpdateLayerBounds(); - layer_->SetIsDrawable(true); - layer_->SetHitTestable(true); - blink_widget_->SetRootLayer(std::move(layer)); -} - -void RenderWidgetFullscreenPepper::DidInitiatePaint() { - if (plugin_) - plugin_->ViewInitiatedPaint(); -} - -void RenderWidgetFullscreenPepper::Close(std::unique_ptr<RenderWidget> widget) { - // If the fullscreen window is closed (e.g. user pressed escape), reset to - // normal mode. - if (plugin_) - plugin_->FlashSetFullscreen(false, false); - - // Call Close on the base class to destroy the WebWidget instance. - RenderWidget::Close(std::move(widget)); -} - -void RenderWidgetFullscreenPepper::UpdateLayerBounds() { - if (!layer_) - return; - - // The |layer_| is sized here to cover the entire renderer's compositor - // viewport. - gfx::Size layer_size = gfx::Rect(GetWebWidget()->ViewRect()).size(); - // When IsUseZoomForDSFEnabled() is true, layout and compositor layer sizes - // given by blink are all in physical pixels, and the compositor does not do - // any scaling. But the ViewRect() is always in DIP so we must scale the layer - // here as the compositor won't. - if (compositor_deps()->IsUseZoomForDSFEnabled()) { - layer_size = gfx::ScaleToCeiledSize( - layer_size, - GetWebWidget()->GetOriginalScreenInfo().device_scale_factor); - } - layer_->SetBounds(layer_size); -} - -WebInputEventResult RenderWidgetFullscreenPepper::ProcessInputEvent( - const WebCoalescedInputEvent& coalesced_event) { - if (!plugin()) - return WebInputEventResult::kNotHandled; - - const WebInputEvent& event = coalesced_event.Event(); - - // This cursor is ignored, we always set the cursor directly from - // RenderWidgetFullscreenPepper::DidChangeCursor. - ui::Cursor cursor; - - // Pepper plugins do not accept gesture events. So do not send the gesture - // events directly to the plugin. Instead, try to convert them to equivalent - // mouse events, and then send to the plugin. - if (blink::WebInputEvent::IsGestureEventType(event.GetType())) { - bool result = false; - const WebGestureEvent* gesture_event = - static_cast<const WebGestureEvent*>(&event); - switch (event.GetType()) { - case WebInputEvent::Type::kGestureTap: { - WebMouseEvent mouse(WebInputEvent::Type::kMouseMove, - gesture_event->GetModifiers(), - gesture_event->TimeStamp()); - mouse.SetPositionInWidget(gesture_event->PositionInWidget()); - mouse.SetPositionInScreen(gesture_event->PositionInScreen()); - mouse.movement_x = 0; - mouse.movement_y = 0; - result |= plugin()->HandleInputEvent(mouse, &cursor); - - mouse.SetType(WebInputEvent::Type::kMouseDown); - mouse.button = WebMouseEvent::Button::kLeft; - mouse.click_count = gesture_event->data.tap.tap_count; - result |= plugin()->HandleInputEvent(mouse, &cursor); - - mouse.SetType(WebInputEvent::Type::kMouseUp); - result |= plugin()->HandleInputEvent(mouse, &cursor); - break; - } - - default: { - WebMouseEvent mouse = WebMouseEventFromGestureEvent(*gesture_event); - if (mouse.GetType() != WebInputEvent::Type::kUndefined) - result |= plugin()->HandleInputEvent(mouse, &cursor); - break; - } - } - return result ? WebInputEventResult::kHandledApplication - : WebInputEventResult::kNotHandled; - } - - bool result = plugin()->HandleInputEvent(event, &cursor); - - // For normal web pages, WebViewImpl does input event translations and - // generates context menu events. Since we don't have a WebView, we need to - // do the necessary translation ourselves. - if (WebInputEvent::IsMouseEventType(event.GetType())) { - const WebMouseEvent& mouse_event = static_cast<const WebMouseEvent&>(event); - bool send_context_menu_event = false; - // On Mac/Linux, we handle it on mouse down. - // On Windows, we handle it on mouse up. -#if defined(OS_WIN) - send_context_menu_event = - mouse_event.GetType() == WebInputEvent::Type::kMouseUp && - mouse_event.button == WebMouseEvent::Button::kRight; -#elif defined(OS_MAC) - send_context_menu_event = - mouse_event.GetType() == WebInputEvent::Type::kMouseDown && - (mouse_event.button == WebMouseEvent::Button::kRight || - (mouse_event.button == WebMouseEvent::Button::kLeft && - mouse_event.GetModifiers() & WebMouseEvent::kControlKey)); -#else - send_context_menu_event = - mouse_event.GetType() == WebInputEvent::Type::kMouseDown && - mouse_event.button == WebMouseEvent::Button::kRight; -#endif - if (send_context_menu_event) { - WebMouseEvent context_menu_event(mouse_event); - context_menu_event.SetType(WebInputEvent::Type::kContextMenu); - plugin()->HandleInputEvent(context_menu_event, &cursor); - } - } - return result ? WebInputEventResult::kHandledApplication - : WebInputEventResult::kNotHandled; -} - -void RenderWidgetFullscreenPepper::DidResize(const gfx::Size& size) { - if (!plugin()) - return; - gfx::Rect plugin_rect(size); - plugin()->ViewChanged(plugin_rect, plugin_rect, plugin_rect); -} - -} // namespace content
diff --git a/content/renderer/render_widget_fullscreen_pepper.h b/content/renderer/render_widget_fullscreen_pepper.h deleted file mode 100644 index 5dd20af..0000000 --- a/content/renderer/render_widget_fullscreen_pepper.h +++ /dev/null
@@ -1,100 +0,0 @@ -// Copyright (c) 2012 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_RENDERER_RENDER_WIDGET_FULLSCREEN_PEPPER_H_ -#define CONTENT_RENDERER_RENDER_WIDGET_FULLSCREEN_PEPPER_H_ - -#include <stdint.h> - -#include <memory> - -#include "base/macros.h" -#include "content/renderer/mouse_lock_dispatcher.h" -#include "content/renderer/pepper/fullscreen_container.h" -#include "content/renderer/render_widget.h" -#include "mojo/public/cpp/bindings/pending_receiver.h" -#include "third_party/blink/public/mojom/page/widget.mojom.h" -#include "third_party/blink/public/web/web_external_widget.h" -#include "third_party/blink/public/web/web_external_widget_client.h" -#include "url/gurl.h" - -namespace cc { -class Layer; -} - -namespace content { -class AgentSchedulingGroup; -class CompositorDependencies; -class PepperPluginInstanceImpl; -class PepperExternalWidgetClient; - -// A RenderWidget that hosts a fullscreen pepper plugin. This provides a -// FullscreenContainer that the plugin instance can callback into to e.g. -// invalidate rects. -class RenderWidgetFullscreenPepper : public RenderWidget, - public FullscreenContainer { - public: - // The created object is owned by the browser process. The browser process - // is responsible for destroying it with an IPC message. - static RenderWidgetFullscreenPepper* Create( - AgentSchedulingGroup& agent_scheduling_group, - int32_t routing_id, - RenderWidget::ShowCallback show_callback, - CompositorDependencies* compositor_deps, - const blink::ScreenInfo& screen_info, - PepperPluginInstanceImpl* plugin, - const blink::WebURL& local_main_frame_url, - mojo::PendingAssociatedRemote<blink::mojom::WidgetHost> blink_widget_host, - mojo::PendingAssociatedReceiver<blink::mojom::Widget> blink_widget); - - // pepper::FullscreenContainer API. - void Destroy() override; - void PepperDidChangeCursor(const ui::Cursor& cursor) override; - void SetLayer(scoped_refptr<cc::Layer> layer) override; - - // Could be NULL when this widget is closing. - PepperPluginInstanceImpl* plugin() const { return plugin_; } - - MouseLockDispatcher* mouse_lock_dispatcher() const { - return mouse_lock_dispatcher_.get(); - } - - protected: - RenderWidgetFullscreenPepper( - AgentSchedulingGroup& agent_scheduling_group, - int32_t routing_id, - CompositorDependencies* compositor_deps, - PepperPluginInstanceImpl* plugin, - mojo::PendingAssociatedRemote<blink::mojom::WidgetHost> blink_widget_host, - mojo::PendingAssociatedReceiver<blink::mojom::Widget> blink_widget, - blink::WebURL main_frame_url); - ~RenderWidgetFullscreenPepper() override; - - // RenderWidget API. - void Close(std::unique_ptr<RenderWidget> widget) override; - - private: - friend class PepperExternalWidgetClient; - - void DidInitiatePaint(); - void UpdateLayerBounds(); - void DidResize(const gfx::Size& size); - blink::WebInputEventResult ProcessInputEvent( - const blink::WebCoalescedInputEvent& event); - - // The plugin instance this widget wraps. - PepperPluginInstanceImpl* plugin_; - - cc::Layer* layer_ = nullptr; - - std::unique_ptr<MouseLockDispatcher> mouse_lock_dispatcher_; - std::unique_ptr<PepperExternalWidgetClient> widget_client_; - std::unique_ptr<blink::WebExternalWidget> blink_widget_; - - DISALLOW_COPY_AND_ASSIGN(RenderWidgetFullscreenPepper); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_RENDER_WIDGET_FULLSCREEN_PEPPER_H_
diff --git a/content/shell/fuchsia/OWNERS b/content/shell/fuchsia/OWNERS new file mode 100644 index 0000000..e7fa181 --- /dev/null +++ b/content/shell/fuchsia/OWNERS
@@ -0,0 +1,7 @@ +file://build/fuchsia/OWNERS +# COMPONENT: Fuchsia +# OS: Fuchsia +# TEAM: cr-fuchsia@chromium.org + +per-file *.cmx=set noparent +per-file *.cmx=file://fuchsia/SECURITY_OWNERS
diff --git a/content/shell/fuchsia/content_shell.cmx b/content/shell/fuchsia/content_shell.cmx index 912ae8b..57b1ccd 100644 --- a/content/shell/fuchsia/content_shell.cmx +++ b/content/shell/fuchsia/content_shell.cmx
@@ -25,6 +25,7 @@ "fuchsia.sysmem.Allocator", "fuchsia.ui.input.ImeService", "fuchsia.ui.input.ImeVisibilityService", + "fuchsia.ui.policy.Presenter", "fuchsia.ui.scenic.Scenic", "fuchsia.vulkan.loader.Loader" ]
diff --git a/device/BUILD.gn b/device/BUILD.gn index bfe360d..747e5b6 100644 --- a/device/BUILD.gn +++ b/device/BUILD.gn
@@ -171,6 +171,7 @@ "fido/large_blob_unittest.cc", "fido/make_credential_handler_unittest.cc", "fido/make_credential_task_unittest.cc", + "fido/pin_unittest.cc", "fido/test_callback_receiver_unittest.cc", "fido/u2f_command_constructor_unittest.cc", "fido/u2f_register_operation_unittest.cc",
diff --git a/device/fido/BUILD.gn b/device/fido/BUILD.gn index ec3c528..6e58545 100644 --- a/device/fido/BUILD.gn +++ b/device/fido/BUILD.gn
@@ -173,6 +173,8 @@ "opaque_attestation_statement.h", "pin.cc", "pin.h", + "pin_internal.cc", + "pin_internal.h", "platform_credential_store.h", "reset_request_handler.cc", "reset_request_handler.h",
diff --git a/device/fido/device_response_converter.cc b/device/fido/device_response_converter.cc index 31e7a758..7e50fb4 100644 --- a/device/fido/device_response_converter.cc +++ b/device/fido/device_response_converter.cc
@@ -746,7 +746,8 @@ } base::Optional<PINUVAuthProtocol> ToPINUVAuthProtocol(int64_t in) { - if (in != static_cast<uint8_t>(PINUVAuthProtocol::kV1)) { + if (in != static_cast<uint8_t>(PINUVAuthProtocol::kV1) && + in != static_cast<uint8_t>(PINUVAuthProtocol::kV2)) { return base::nullopt; } return static_cast<PINUVAuthProtocol>(in);
diff --git a/device/fido/fido_constants.h b/device/fido/fido_constants.h index 5f6e9c164..514cf980 100644 --- a/device/fido/fido_constants.h +++ b/device/fido/fido_constants.h
@@ -476,6 +476,7 @@ // PINUVAuthProtocol is the version number of a PIN/UV auth protocol. enum class PINUVAuthProtocol : uint8_t { kV1 = 1, + kV2 = 2, }; } // namespace device
diff --git a/device/fido/fido_device_authenticator.cc b/device/fido/fido_device_authenticator.cc index 7af7cc4..93f44ed3 100644 --- a/device/fido/fido_device_authenticator.cc +++ b/device/fido/fido_device_authenticator.cc
@@ -261,7 +261,7 @@ if (Options()->supports_pin_uv_auth_token) { pin::PinTokenWithPermissionsRequest request(*chosen_pin_uv_auth_protocol_, pin, *key, permissions, rp_id); - std::array<uint8_t, 32> shared_key = request.shared_key(); + std::vector<uint8_t> shared_key = request.shared_key(); RunOperation<pin::PinTokenWithPermissionsRequest, pin::TokenResponse>( std::move(request), std::move(callback), base::BindOnce(&pin::TokenResponse::Parse, @@ -270,7 +270,7 @@ } pin::PinTokenRequest request(*chosen_pin_uv_auth_protocol_, pin, *key); - std::array<uint8_t, 32> shared_key = request.shared_key(); + std::vector<uint8_t> shared_key = request.shared_key(); RunOperation<pin::PinTokenRequest, pin::TokenResponse>( std::move(request), std::move(callback), base::BindOnce(&pin::TokenResponse::Parse, *chosen_pin_uv_auth_protocol_, @@ -1068,7 +1068,7 @@ pin::UvTokenRequest request(*chosen_pin_uv_auth_protocol_, *key, std::move(rp_id)); - std::array<uint8_t, 32> shared_key = request.shared_key(); + std::vector<uint8_t> shared_key = request.shared_key(); RunOperation<pin::UvTokenRequest, pin::TokenResponse>( std::move(request), std::move(callback), base::BindOnce(&pin::TokenResponse::Parse, *chosen_pin_uv_auth_protocol_,
diff --git a/device/fido/pin.cc b/device/fido/pin.cc index 83c9dcc1..8ae7e09 100644 --- a/device/fido/pin.cc +++ b/device/fido/pin.cc
@@ -15,13 +15,8 @@ #include "device/fido/fido_constants.h" #include "device/fido/pin_internal.h" #include "third_party/boringssl/src/include/openssl/aes.h" -#include "third_party/boringssl/src/include/openssl/bn.h" #include "third_party/boringssl/src/include/openssl/ec.h" -#include "third_party/boringssl/src/include/openssl/ec_key.h" -#include "third_party/boringssl/src/include/openssl/ecdh.h" -#include "third_party/boringssl/src/include/openssl/evp.h" -#include "third_party/boringssl/src/include/openssl/hmac.h" -#include "third_party/boringssl/src/include/openssl/obj.h" +#include "third_party/boringssl/src/include/openssl/nid.h" #include "third_party/boringssl/src/include/openssl/sha.h" namespace device { @@ -35,19 +30,6 @@ return it.Advance() && it.Advance() && it.Advance() && it.Advance(); } -// MakePinAuth returns `LEFT(HMAC-SHA-256(secret, data), 16)`. -std::vector<uint8_t> MakePinAuth(base::span<const uint8_t> secret, - base::span<const uint8_t> data) { - std::vector<uint8_t> pin_auth; - pin_auth.resize(SHA256_DIGEST_LENGTH); - unsigned hmac_bytes; - CHECK(HMAC(EVP_sha256(), secret.data(), secret.size(), data.data(), - data.size(), pin_auth.data(), &hmac_bytes)); - DCHECK_EQ(pin_auth.size(), static_cast<size_t>(hmac_bytes)); - pin_auth.resize(16); - return pin_auth; -} - bool IsValid(const std::string& pin) { return pin.size() >= kMinBytes && pin.size() <= kMaxBytes && pin.back() != 0 && base::IsStringUTF8(pin) && @@ -118,28 +100,6 @@ KeyAgreementResponse::KeyAgreementResponse() = default; -// PointFromKeyAgreementResponse returns an |EC_POINT| that represents the same -// P-256 point as |response|. It returns |nullopt| if |response| encodes an -// invalid point. -base::Optional<bssl::UniquePtr<EC_POINT>> PointFromKeyAgreementResponse( - const EC_GROUP* group, - const KeyAgreementResponse& response) { - bssl::UniquePtr<EC_POINT> ret(EC_POINT_new(group)); - - bssl::UniquePtr<BIGNUM> x_bn(BN_new()), y_bn(BN_new()); - BN_bin2bn(response.x, sizeof(response.x), x_bn.get()); - BN_bin2bn(response.y, sizeof(response.y), y_bn.get()); - const bool on_curve = - EC_POINT_set_affine_coordinates_GFp(group, ret.get(), x_bn.get(), - y_bn.get(), nullptr /* ctx */) == 1; - - if (!on_curve) { - return base::nullopt; - } - - return ret; -} - // static base::Optional<KeyAgreementResponse> KeyAgreementResponse::Parse( const base::Optional<cbor::Value>& cbor) { @@ -224,31 +184,6 @@ memcpy(pin_, pin.data(), pin.size()); } -// SHA256KDF implements CTAP2's KDF, which just runs SHA-256 on the x-coordinate -// of the result. The function signature is such that it fits into OpenSSL's -// ECDH API. -static void* SHA256KDF(const void* in, - size_t in_len, - void* out, - size_t* out_len) { - DCHECK_GE(*out_len, static_cast<size_t>(SHA256_DIGEST_LENGTH)); - SHA256(reinterpret_cast<const uint8_t*>(in), in_len, - reinterpret_cast<uint8_t*>(out)); - *out_len = SHA256_DIGEST_LENGTH; - return out; -} - -// CalculateSharedKey writes the CTAP2 shared key between |key| and |peers_key| -// to |out_shared_key|. -void CalculateSharedKey(const EC_KEY* key, - const EC_POINT* peers_key, - uint8_t out_shared_key[SHA256_DIGEST_LENGTH]) { - CHECK_EQ(static_cast<int>(SHA256_DIGEST_LENGTH), - ECDH_compute_key(out_shared_key, SHA256_DIGEST_LENGTH, peers_key, - key, SHA256KDF)); -} - -// EncodeCOSEPublicKey converts an X9.62 public key into a COSE structure. cbor::Value::MapValue EncodeCOSEPublicKey( base::span<const uint8_t, kP256X962Length> x962) { cbor::Value::MapValue cose_key; @@ -262,44 +197,6 @@ return cose_key; } -// GenerateSharedKey generates and returns an ephemeral key, and writes the -// shared key between that ephemeral key and the authenticator's ephemeral key -// (from |peers_key|) to |out_shared_key|. -static std::array<uint8_t, kP256X962Length> GenerateSharedKey( - const KeyAgreementResponse& peers_key, - uint8_t out_shared_key[SHA256_DIGEST_LENGTH]) { - bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); - CHECK(EC_KEY_generate_key(key.get())); - auto peers_point = - PointFromKeyAgreementResponse(EC_KEY_get0_group(key.get()), peers_key); - CalculateSharedKey(key.get(), peers_point->get(), out_shared_key); - std::array<uint8_t, kP256X962Length> x962; - CHECK_EQ(x962.size(), - EC_POINT_point2oct(EC_KEY_get0_group(key.get()), - EC_KEY_get0_public_key(key.get()), - POINT_CONVERSION_UNCOMPRESSED, x962.data(), - x962.size(), nullptr /* BN_CTX */)); - - return x962; -} - -// Encrypt encrypts |plaintext| using |key|, writing the ciphertext to -// |out_ciphertext|. |plaintext| must be a whole number of AES blocks. -void Encrypt(const uint8_t key[SHA256_DIGEST_LENGTH], - base::span<const uint8_t> plaintext, - uint8_t* out_ciphertext) { - DCHECK_EQ(0u, plaintext.size() % AES_BLOCK_SIZE); - - EVP_CIPHER_CTX aes_ctx; - EVP_CIPHER_CTX_init(&aes_ctx); - const uint8_t kZeroIV[AES_BLOCK_SIZE] = {0}; - CHECK(EVP_EncryptInit_ex(&aes_ctx, EVP_aes_256_cbc(), nullptr, key, kZeroIV)); - CHECK(EVP_CIPHER_CTX_set_padding(&aes_ctx, 0 /* no padding */)); - CHECK( - EVP_Cipher(&aes_ctx, out_ciphertext, plaintext.data(), plaintext.size())); - EVP_CIPHER_CTX_cleanup(&aes_ctx); -} - ChangeRequest::ChangeRequest(PINUVAuthProtocol protocol, const std::string& old_pin, const std::string& new_pin, @@ -336,24 +233,6 @@ TokenResponse::TokenResponse(const TokenResponse&) = default; TokenResponse& TokenResponse::operator=(const TokenResponse&) = default; -// Decrypt AES-256 CBC decrypts some number of whole blocks from |ciphertext| -// into |plaintext|, using |key|. -void Decrypt(const uint8_t key[SHA256_DIGEST_LENGTH], - base::span<const uint8_t> ciphertext, - uint8_t* out_plaintext) { - DCHECK_EQ(0u, ciphertext.size() % AES_BLOCK_SIZE); - - EVP_CIPHER_CTX aes_ctx; - EVP_CIPHER_CTX_init(&aes_ctx); - const uint8_t kZeroIV[AES_BLOCK_SIZE] = {0}; - CHECK(EVP_DecryptInit_ex(&aes_ctx, EVP_aes_256_cbc(), nullptr, key, kZeroIV)); - CHECK(EVP_CIPHER_CTX_set_padding(&aes_ctx, 0 /* no padding */)); - - CHECK(EVP_Cipher(&aes_ctx, out_plaintext, ciphertext.data(), - ciphertext.size())); - EVP_CIPHER_CTX_cleanup(&aes_ctx); -} - base::Optional<TokenResponse> TokenResponse::Parse( PINUVAuthProtocol protocol, base::span<const uint8_t> shared_key, @@ -374,14 +253,14 @@ } TokenResponse ret(protocol); - ret.token_.resize(encrypted_token.size()); - Decrypt(shared_key.data(), encrypted_token, ret.token_.data()); + ret.token_ = ProtocolVersion(protocol).Decrypt(shared_key, encrypted_token); return ret; } std::pair<PINUVAuthProtocol, std::vector<uint8_t>> TokenResponse::PinAuth( base::span<const uint8_t> client_data_hash) const { - return {protocol_, MakePinAuth(token_, client_data_hash)}; + return {protocol_, + ProtocolVersion(protocol_).Authenticate(token_, client_data_hash)}; } // static @@ -407,27 +286,26 @@ AsCTAPRequestValuePair(const SetRequest& request) { // See // https://fidoalliance.org/specs/fido-v2.0-rd-20180702/fido-client-to-authenticator-protocol-v2.0-rd-20180702.html#settingNewPin - uint8_t shared_key[SHA256_DIGEST_LENGTH]; - auto cose_key = - EncodeCOSEPublicKey(GenerateSharedKey(request.peer_key_, shared_key)); + std::vector<uint8_t> shared_key; + const Protocol& pin_protocol = ProtocolVersion(request.protocol_); + auto cose_key = EncodeCOSEPublicKey( + pin_protocol.Encapsulate(request.peer_key_, &shared_key)); static_assert((sizeof(request.pin_) % AES_BLOCK_SIZE) == 0, "pin_ is not a multiple of the AES block size"); - uint8_t encrypted_pin[sizeof(request.pin_)]; - Encrypt(shared_key, request.pin_, encrypted_pin); + std::vector<uint8_t> encrypted_pin = + pin_protocol.Encrypt(shared_key, request.pin_); std::vector<uint8_t> pin_auth = - MakePinAuth(base::make_span(shared_key, sizeof(shared_key)), - base::make_span(encrypted_pin, sizeof(encrypted_pin))); + pin_protocol.Authenticate(shared_key, encrypted_pin); return EncodePINCommand( request.protocol_, Subcommand::kSetPIN, [&cose_key, &encrypted_pin, &pin_auth](cbor::Value::MapValue* map) { map->emplace(static_cast<int>(RequestKey::kKeyAgreement), std::move(cose_key)); - map->emplace( - static_cast<int>(RequestKey::kNewPINEnc), - base::span<const uint8_t>(encrypted_pin, sizeof(encrypted_pin))); + map->emplace(static_cast<int>(RequestKey::kNewPINEnc), + std::move(encrypted_pin)); map->emplace(static_cast<int>(RequestKey::kPINAuth), std::move(pin_auth)); }); @@ -438,27 +316,29 @@ AsCTAPRequestValuePair(const ChangeRequest& request) { // See // https://fidoalliance.org/specs/fido-v2.0-rd-20180702/fido-client-to-authenticator-protocol-v2.0-rd-20180702.html#changingExistingPin - uint8_t shared_key[SHA256_DIGEST_LENGTH]; - auto cose_key = - EncodeCOSEPublicKey(GenerateSharedKey(request.peer_key_, shared_key)); + std::vector<uint8_t> shared_key; + const Protocol& pin_protocol = ProtocolVersion(request.protocol_); + auto cose_key = EncodeCOSEPublicKey( + pin_protocol.Encapsulate(request.peer_key_, &shared_key)); static_assert((sizeof(request.new_pin_) % AES_BLOCK_SIZE) == 0, "new_pin_ is not a multiple of the AES block size"); - uint8_t encrypted_pin[sizeof(request.new_pin_)]; - Encrypt(shared_key, request.new_pin_, encrypted_pin); + std::vector<uint8_t> encrypted_pin = + pin_protocol.Encrypt(shared_key, request.new_pin_); static_assert((sizeof(request.old_pin_hash_) % AES_BLOCK_SIZE) == 0, "old_pin_hash_ is not a multiple of the AES block size"); - uint8_t old_pin_hash_enc[sizeof(request.old_pin_hash_)]; - Encrypt(shared_key, request.old_pin_hash_, old_pin_hash_enc); + std::vector<uint8_t> old_pin_hash_enc = + pin_protocol.Encrypt(shared_key, request.old_pin_hash_); - uint8_t ciphertexts_concat[sizeof(encrypted_pin) + sizeof(old_pin_hash_enc)]; - memcpy(ciphertexts_concat, encrypted_pin, sizeof(encrypted_pin)); - memcpy(ciphertexts_concat + sizeof(encrypted_pin), old_pin_hash_enc, - sizeof(old_pin_hash_enc)); - std::vector<uint8_t> pin_auth = MakePinAuth( - base::make_span(shared_key, sizeof(shared_key)), - base::make_span(ciphertexts_concat, sizeof(ciphertexts_concat))); + std::vector<uint8_t> ciphertexts_concat(encrypted_pin.size() + + old_pin_hash_enc.size()); + memcpy(ciphertexts_concat.data(), encrypted_pin.data(), encrypted_pin.size()); + memcpy(ciphertexts_concat.data() + encrypted_pin.size(), + old_pin_hash_enc.data(), old_pin_hash_enc.size()); + + std::vector<uint8_t> pin_auth = + pin_protocol.Authenticate(shared_key, ciphertexts_concat); return EncodePINCommand( request.protocol_, Subcommand::kChangePIN, @@ -467,11 +347,9 @@ map->emplace(static_cast<int>(RequestKey::kKeyAgreement), std::move(cose_key)); map->emplace(static_cast<int>(RequestKey::kPINHashEnc), - base::span<const uint8_t>(old_pin_hash_enc, - sizeof(old_pin_hash_enc))); - map->emplace( - static_cast<int>(RequestKey::kNewPINEnc), - base::span<const uint8_t>(encrypted_pin, sizeof(encrypted_pin))); + std::move(old_pin_hash_enc)); + map->emplace(static_cast<int>(RequestKey::kNewPINEnc), + std::move(encrypted_pin)); map->emplace(static_cast<int>(RequestKey::kPINAuth), std::move(pin_auth)); }); @@ -486,15 +364,14 @@ TokenRequest::TokenRequest(PINUVAuthProtocol protocol, const KeyAgreementResponse& peer_key) : protocol_(protocol), - public_key_(GenerateSharedKey(peer_key, shared_key_.data())) { - DCHECK_EQ(static_cast<size_t>(SHA256_DIGEST_LENGTH), shared_key_.size()); -} + public_key_( + ProtocolVersion(protocol_).Encapsulate(peer_key, &shared_key_)) {} TokenRequest::~TokenRequest() = default; TokenRequest::TokenRequest(TokenRequest&& other) = default; -const std::array<uint8_t, 32>& TokenRequest::shared_key() const { +const std::vector<uint8_t>& TokenRequest::shared_key() const { return shared_key_; } @@ -516,17 +393,17 @@ AsCTAPRequestValuePair(const PinTokenRequest& request) { static_assert((sizeof(request.pin_hash_) % AES_BLOCK_SIZE) == 0, "pin_hash_ is not a multiple of the AES block size"); - uint8_t encrypted_pin[sizeof(request.pin_hash_)]; - Encrypt(request.shared_key_.data(), request.pin_hash_, encrypted_pin); + std::vector<uint8_t> encrypted_pin = + ProtocolVersion(request.protocol_) + .Encrypt(request.shared_key_, request.pin_hash_); return EncodePINCommand( request.protocol_, Subcommand::kGetPINToken, [&request, &encrypted_pin](cbor::Value::MapValue* map) { map->emplace(static_cast<int>(RequestKey::kKeyAgreement), EncodeCOSEPublicKey(request.public_key_)); - map->emplace( - static_cast<int>(RequestKey::kPINHashEnc), - base::span<const uint8_t>(encrypted_pin, sizeof(encrypted_pin))); + map->emplace(static_cast<int>(RequestKey::kPINHashEnc), + std::move(encrypted_pin)); }); } @@ -543,17 +420,17 @@ // static std::pair<CtapRequestCommand, base::Optional<cbor::Value>> AsCTAPRequestValuePair(const PinTokenWithPermissionsRequest& request) { - uint8_t encrypted_pin[sizeof(request.pin_hash_)]; - Encrypt(request.shared_key_.data(), request.pin_hash_, encrypted_pin); + std::vector<uint8_t> encrypted_pin = + ProtocolVersion(request.protocol_) + .Encrypt(request.shared_key_, request.pin_hash_); return EncodePINCommand( request.protocol_, Subcommand::kGetPinUvAuthTokenUsingPinWithPermissions, [&request, &encrypted_pin](cbor::Value::MapValue* map) { map->emplace(static_cast<int>(RequestKey::kKeyAgreement), EncodeCOSEPublicKey(request.public_key_)); - map->emplace( - static_cast<int>(RequestKey::kPINHashEnc), - base::span<const uint8_t>(encrypted_pin, sizeof(encrypted_pin))); + map->emplace(static_cast<int>(RequestKey::kPINHashEnc), + std::move(encrypted_pin)); map->emplace(static_cast<int>(RequestKey::kPermissions), std::move(request.permissions_)); if (request.rp_id_) { @@ -595,15 +472,6 @@ }); } -static std::vector<uint8_t> EncryptToVector( - base::span<const uint8_t, SHA256_DIGEST_LENGTH> key, - base::span<const uint8_t> plaintext) { - std::vector<uint8_t> ret; - ret.resize(plaintext.size()); - Encrypt(key.data(), plaintext, ret.data()); - return ret; -} - static std::vector<uint8_t> ConcatSalts( base::span<const uint8_t, 32> salt1, const base::Optional<std::array<uint8_t, 32>>& salt2) { @@ -625,9 +493,13 @@ base::span<const uint8_t, 32> salt1, const base::Optional<std::array<uint8_t, 32>>& salt2) : protocol_(protocol), - public_key_x962(GenerateSharedKey(peer_key, shared_key_.data())), - encrypted_salts(EncryptToVector(shared_key_, ConcatSalts(salt1, salt2))), - salts_auth(MakePinAuth(shared_key_, encrypted_salts)) {} + public_key_x962( + ProtocolVersion(protocol_).Encapsulate(peer_key, &shared_key_)), + encrypted_salts( + ProtocolVersion(protocol_).Encrypt(shared_key_, + ConcatSalts(salt1, salt2))), + salts_auth(ProtocolVersion(protocol_).Authenticate(shared_key_, + encrypted_salts)) {} HMACSecretRequest::~HMACSecretRequest() = default; @@ -639,12 +511,8 @@ return base::nullopt; } - std::vector<uint8_t> ret; - ret.resize(ciphertext.size()); - pin::Decrypt(shared_key_.data(), ciphertext, ret.data()); - return ret; + return pin::ProtocolVersion(protocol_).Decrypt(shared_key_, ciphertext); } } // namespace pin - } // namespace device
diff --git a/device/fido/pin.h b/device/fido/pin.h index fd485f91..dd478f9 100644 --- a/device/fido/pin.h +++ b/device/fido/pin.h
@@ -55,6 +55,7 @@ constexpr size_t kMaxBytes = 63; // EncodeCOSEPublicKey converts an X9.62 public key to a COSE structure. +COMPONENT_EXPORT(DEVICE_FIDO) cbor::Value::MapValue EncodeCOSEPublicKey( base::span<const uint8_t, kP256X962Length> x962); @@ -100,7 +101,7 @@ // KeyAgreementResponse reflects an authenticator's response to a // |KeyAgreementRequest| and is also used as representation of the // authenticator's ephemeral key. -struct KeyAgreementResponse { +struct COMPONENT_EXPORT(DEVICE_FIDO) KeyAgreementResponse { static base::Optional<KeyAgreementResponse> Parse( const base::Optional<cbor::Value>& cbor); static base::Optional<KeyAgreementResponse> ParseFromCOSE( @@ -177,7 +178,7 @@ // shared_key returns the shared ECDH key that was used to encrypt the PIN. // This is needed to decrypt the response. - const std::array<uint8_t, 32>& shared_key() const; + const std::vector<uint8_t>& shared_key() const; protected: TokenRequest(TokenRequest&&); @@ -186,7 +187,7 @@ ~TokenRequest(); const PINUVAuthProtocol protocol_; - std::array<uint8_t, 32> shared_key_; + std::vector<uint8_t> shared_key_; std::array<uint8_t, kP256X962Length> public_key_; }; @@ -257,7 +258,7 @@ private: const PINUVAuthProtocol protocol_; - std::array<uint8_t, 32> shared_key_ = {}; + std::vector<uint8_t> shared_key_; public: const std::array<uint8_t, kP256X962Length> public_key_x962;
diff --git a/device/fido/pin_internal.cc b/device/fido/pin_internal.cc new file mode 100644 index 0000000..369fa35 --- /dev/null +++ b/device/fido/pin_internal.cc
@@ -0,0 +1,316 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/fido/pin_internal.h" + +#include <string> +#include <utility> + +#include "base/i18n/char_iterator.h" +#include "base/no_destructor.h" +#include "base/strings/string_util.h" +#include "crypto/random.h" +#include "third_party/boringssl/src/include/openssl/aes.h" +#include "third_party/boringssl/src/include/openssl/bn.h" +#include "third_party/boringssl/src/include/openssl/ec.h" +#include "third_party/boringssl/src/include/openssl/ec_key.h" +#include "third_party/boringssl/src/include/openssl/ecdh.h" +#include "third_party/boringssl/src/include/openssl/evp.h" +#include "third_party/boringssl/src/include/openssl/hkdf.h" +#include "third_party/boringssl/src/include/openssl/hmac.h" +#include "third_party/boringssl/src/include/openssl/mem.h" +#include "third_party/boringssl/src/include/openssl/sha.h" + +namespace device { +namespace pin { + +base::Optional<bssl::UniquePtr<EC_POINT>> PointFromKeyAgreementResponse( + const EC_GROUP* group, + const KeyAgreementResponse& response) { + bssl::UniquePtr<EC_POINT> ret(EC_POINT_new(group)); + + bssl::UniquePtr<BIGNUM> x_bn(BN_new()), y_bn(BN_new()); + BN_bin2bn(response.x, sizeof(response.x), x_bn.get()); + BN_bin2bn(response.y, sizeof(response.y), y_bn.get()); + const bool on_curve = + EC_POINT_set_affine_coordinates_GFp(group, ret.get(), x_bn.get(), + y_bn.get(), nullptr /* ctx */) == 1; + + if (!on_curve) { + return base::nullopt; + } + + return ret; +} + +// ProtocolV1 implements CTAP2.1 PIN/UV Auth Protocol One (6.5.10). +class ProtocolV1 : public Protocol { + private: + static constexpr size_t kSharedKeySize = 32u; + static constexpr size_t kSignatureSize = 16u; + + std::array<uint8_t, kP256X962Length> Encapsulate( + const KeyAgreementResponse& peers_key, + std::vector<uint8_t>* out_shared_key) const override { + bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); + CHECK(EC_KEY_generate_key(key.get())); + base::Optional<bssl::UniquePtr<EC_POINT>> peers_point = + PointFromKeyAgreementResponse(EC_KEY_get0_group(key.get()), peers_key); + *out_shared_key = CalculateSharedKey(key.get(), peers_point->get()); + // KeyAgreementResponse parsing ensures that the point is on the curve. + DCHECK(peers_point); + std::array<uint8_t, kP256X962Length> x962; + CHECK_EQ(x962.size(), + EC_POINT_point2oct(EC_KEY_get0_group(key.get()), + EC_KEY_get0_public_key(key.get()), + POINT_CONVERSION_UNCOMPRESSED, x962.data(), + x962.size(), nullptr /* BN_CTX */)); + + return x962; + } + + std::vector<uint8_t> Encrypt( + base::span<const uint8_t> shared_key, + base::span<const uint8_t> plaintext) const override { + DCHECK_EQ(plaintext.size() % AES_BLOCK_SIZE, 0u); + DCHECK_EQ(shared_key.size(), kSharedKeySize); + + std::vector<uint8_t> ciphertext(plaintext.size()); + + EVP_CIPHER_CTX aes_ctx; + EVP_CIPHER_CTX_init(&aes_ctx); + const uint8_t kZeroIV[AES_BLOCK_SIZE] = {}; + CHECK(EVP_EncryptInit_ex(&aes_ctx, EVP_aes_256_cbc(), nullptr, + shared_key.data(), kZeroIV)); + CHECK(EVP_CIPHER_CTX_set_padding(&aes_ctx, 0 /* no padding */)); + CHECK(EVP_Cipher(&aes_ctx, ciphertext.data(), plaintext.data(), + plaintext.size())); + EVP_CIPHER_CTX_cleanup(&aes_ctx); + return ciphertext; + } + + std::vector<uint8_t> Decrypt( + base::span<const uint8_t> shared_key, + base::span<const uint8_t> ciphertext) const override { + DCHECK_EQ(ciphertext.size() % AES_BLOCK_SIZE, 0u); + DCHECK_EQ(shared_key.size(), kSharedKeySize); + + std::vector<uint8_t> plaintext(ciphertext.size()); + + EVP_CIPHER_CTX aes_ctx; + EVP_CIPHER_CTX_init(&aes_ctx); + const uint8_t kZeroIV[AES_BLOCK_SIZE] = {}; + CHECK(EVP_DecryptInit_ex(&aes_ctx, EVP_aes_256_cbc(), nullptr, + shared_key.data(), kZeroIV)); + CHECK(EVP_CIPHER_CTX_set_padding(&aes_ctx, 0 /* no padding */)); + + CHECK(EVP_Cipher(&aes_ctx, plaintext.data(), ciphertext.data(), + ciphertext.size())); + EVP_CIPHER_CTX_cleanup(&aes_ctx); + return plaintext; + } + + std::vector<uint8_t> Authenticate( + base::span<const uint8_t> key, + base::span<const uint8_t> data) const override { + DCHECK_EQ(key.size(), kSharedKeySize); + + std::vector<uint8_t> pin_auth(SHA256_DIGEST_LENGTH); + unsigned hmac_bytes; + CHECK(HMAC(EVP_sha256(), key.data(), key.size(), data.data(), data.size(), + pin_auth.data(), &hmac_bytes)); + DCHECK_EQ(pin_auth.size(), static_cast<size_t>(hmac_bytes)); + pin_auth.resize(kSignatureSize); + return pin_auth; + } + + bool Verify(base::span<const uint8_t> key, + base::span<const uint8_t> data, + base::span<const uint8_t> signature) const override { + if (signature.size() != kSignatureSize) { + return false; + } + const std::vector<uint8_t> computed_signature = Authenticate(key, data); + CHECK_EQ(computed_signature.size(), kSignatureSize); + return CRYPTO_memcmp(signature.data(), computed_signature.data(), + kSignatureSize) == 0; + } + + std::vector<uint8_t> CalculateSharedKey( + const EC_KEY* key, + const EC_POINT* peers_key) const override { + std::vector<uint8_t> shared_key(SHA256_DIGEST_LENGTH); + CHECK_EQ(static_cast<int>(SHA256_DIGEST_LENGTH), + ECDH_compute_key(shared_key.data(), shared_key.size(), peers_key, + key, SHA256KDF)); + return shared_key; + } + + static void* SHA256KDF(const void* in, + size_t in_len, + void* out, + size_t* out_len) { + DCHECK_GE(*out_len, static_cast<size_t>(SHA256_DIGEST_LENGTH)); + SHA256(reinterpret_cast<const uint8_t*>(in), in_len, + reinterpret_cast<uint8_t*>(out)); + *out_len = SHA256_DIGEST_LENGTH; + return out; + } +}; + +// ProtocolV2 implements CTAP2.1 PIN/UV Auth Protocol Two (6.5.11). +class ProtocolV2 : public ProtocolV1 { + private: + static constexpr size_t kAESKeyLength = 32; + static constexpr size_t kHMACKeyLength = 32; + static constexpr size_t kSharedKeyLength = kAESKeyLength + kHMACKeyLength; + static constexpr size_t kSignatureSize = SHA256_DIGEST_LENGTH; + + // GetHMACSubKey returns the HMAC-key portion of the shared secret. + static base::span<const uint8_t, kHMACKeyLength> GetHMACSubKey( + base::span<const uint8_t, kSharedKeyLength> shared_key) { + CHECK_EQ(shared_key.size(), kSharedKeyLength); + return base::make_span<kHMACKeyLength>( + shared_key.subspan(0, kHMACKeyLength)); + } + + // GetAESSubKey returns the HMAC-key portion of the shared secret. + static base::span<const uint8_t, kAESKeyLength> GetAESSubKey( + base::span<const uint8_t, kSharedKeyLength> shared_key) { + return base::make_span<kAESKeyLength>(shared_key.subspan(kHMACKeyLength)); + } + + std::vector<uint8_t> Encrypt( + base::span<const uint8_t> shared_key, + base::span<const uint8_t> plaintext) const override { + DCHECK_EQ(plaintext.size() % AES_BLOCK_SIZE, 0u); + + const base::span<const uint8_t, kAESKeyLength> aes_key = + GetAESSubKey(base::make_span<kSharedKeyLength>(shared_key)); + + std::vector<uint8_t> result(AES_BLOCK_SIZE + plaintext.size()); + const base::span<uint8_t> iv = + base::make_span(result).subspan(0, AES_BLOCK_SIZE); + const base::span<uint8_t> ciphertext = + base::make_span(result).subspan(AES_BLOCK_SIZE); + + crypto::RandBytes(iv); + + EVP_CIPHER_CTX aes_ctx; + EVP_CIPHER_CTX_init(&aes_ctx); + CHECK(EVP_EncryptInit_ex(&aes_ctx, EVP_aes_256_cbc(), nullptr, + aes_key.data(), iv.data())); + CHECK(EVP_CIPHER_CTX_set_padding(&aes_ctx, 0 /* no padding */)); + CHECK(EVP_Cipher(&aes_ctx, ciphertext.data(), plaintext.data(), + plaintext.size())); + EVP_CIPHER_CTX_cleanup(&aes_ctx); + + return result; + } + + std::vector<uint8_t> Decrypt(base::span<const uint8_t> shared_key, + base::span<const uint8_t> input) const override { + DCHECK_EQ(input.size() % AES_BLOCK_SIZE, 0u); + + const base::span<const uint8_t, kAESKeyLength> aes_key = + GetAESSubKey(base::make_span<kSharedKeyLength>(shared_key)); + const base::span<const uint8_t> iv = input.subspan(0, AES_BLOCK_SIZE); + const base::span<const uint8_t> ciphertext = input.subspan(AES_BLOCK_SIZE); + std::vector<uint8_t> plaintext(ciphertext.size()); + + EVP_CIPHER_CTX aes_ctx; + EVP_CIPHER_CTX_init(&aes_ctx); + CHECK(EVP_DecryptInit_ex(&aes_ctx, EVP_aes_256_cbc(), nullptr, + aes_key.data(), iv.data())); + CHECK(EVP_CIPHER_CTX_set_padding(&aes_ctx, 0 /* no padding */)); + + CHECK(EVP_Cipher(&aes_ctx, plaintext.data(), ciphertext.data(), + ciphertext.size())); + EVP_CIPHER_CTX_cleanup(&aes_ctx); + + return plaintext; + } + + std::vector<uint8_t> Authenticate( + base::span<const uint8_t> key, + base::span<const uint8_t> data) const override { + // Authenticate can be invoked with the shared secret or with a PIN/UV Auth + // Token, which is fixed at 32 bytes in this protocol version. + CHECK(key.size() == kSharedKeyLength || key.size() == kHMACKeyLength); + const base::span<const uint8_t, kHMACKeyLength> hmac_key = + (key.size() == kSharedKeyLength + ? GetHMACSubKey(base::make_span<kSharedKeyLength>(key)) + : base::make_span<kHMACKeyLength>(key)); + + std::vector<uint8_t> pin_auth(SHA256_DIGEST_LENGTH); + unsigned hmac_bytes; + CHECK(HMAC(EVP_sha256(), hmac_key.data(), hmac_key.size(), data.data(), + data.size(), pin_auth.data(), &hmac_bytes)); + DCHECK_EQ(pin_auth.size(), static_cast<size_t>(hmac_bytes)); + return pin_auth; + } + + bool Verify(base::span<const uint8_t> key, + base::span<const uint8_t> data, + base::span<const uint8_t> signature) const override { + if (signature.size() != kSignatureSize) { + return false; + } + const std::vector<uint8_t> computed_signature = Authenticate(key, data); + CHECK_EQ(computed_signature.size(), kSignatureSize); + return CRYPTO_memcmp(signature.data(), computed_signature.data(), + kSignatureSize) == 0; + } + + std::vector<uint8_t> CalculateSharedKey( + const EC_KEY* key, + const EC_POINT* peers_key) const override { + std::vector<uint8_t> shared_key(kSharedKeyLength); + CHECK_EQ(static_cast<int>(kSharedKeyLength), + ECDH_compute_key(shared_key.data(), shared_key.size(), peers_key, + key, KDF)); + return shared_key; + } + + static void* KDF(const void* in, size_t in_len, void* out, size_t* out_len) { + static_assert(kSharedKeyLength == 2 * SHA256_DIGEST_LENGTH, ""); + DCHECK_GE(*out_len, static_cast<size_t>(kSharedKeyLength)); + auto hmac_key_out = + base::make_span(reinterpret_cast<uint8_t*>(out), SHA256_DIGEST_LENGTH); + auto aes_key_out = + base::make_span(reinterpret_cast<uint8_t*>(out) + SHA256_DIGEST_LENGTH, + SHA256_DIGEST_LENGTH); + + constexpr uint8_t kHMACKeyInfo[] = "CTAP2 HMAC key"; + constexpr uint8_t kAESKeyInfo[] = "CTAP2 AES key"; + constexpr uint8_t kZeroSalt[32] = {}; + + CHECK(HKDF(hmac_key_out.data(), hmac_key_out.size(), EVP_sha256(), + reinterpret_cast<const uint8_t*>(in), in_len, kZeroSalt, + sizeof(kZeroSalt), kHMACKeyInfo, sizeof(kHMACKeyInfo) - 1)); + CHECK(HKDF(aes_key_out.data(), aes_key_out.size(), EVP_sha256(), + reinterpret_cast<const uint8_t*>(in), in_len, kZeroSalt, + sizeof(kZeroSalt), kAESKeyInfo, sizeof(kAESKeyInfo) - 1)); + + *out_len = kSharedKeyLength; + return out; + } +}; + +// static +const Protocol& ProtocolVersion(PINUVAuthProtocol protocol) { + static const base::NoDestructor<ProtocolV1> kProtocolV1; + static const base::NoDestructor<ProtocolV2> kProtocolV2; + + switch (protocol) { + case PINUVAuthProtocol::kV1: + return *kProtocolV1; + case PINUVAuthProtocol::kV2: + return *kProtocolV2; + } +} + +} // namespace pin + +} // namespace device
diff --git a/device/fido/pin_internal.h b/device/fido/pin_internal.h index 73713bb..3712f49d 100644 --- a/device/fido/pin_internal.h +++ b/device/fido/pin_internal.h
@@ -11,10 +11,16 @@ #include <stdint.h> +#include <array> +#include <vector> + +#include "base/component_export.h" +#include "base/containers/span.h" +#include "base/optional.h" #include "components/cbor/values.h" +#include "device/fido/fido_constants.h" #include "device/fido/pin.h" -#include "third_party/boringssl/src/include/openssl/ec.h" -#include "third_party/boringssl/src/include/openssl/sha.h" +#include "third_party/boringssl/src/include/openssl/base.h" namespace device { namespace pin { @@ -65,27 +71,60 @@ const EC_GROUP* group, const KeyAgreementResponse& response); -// MakePinAuth returns a PIN protocol v1 authentication tag for |data|. -std::vector<uint8_t> MakePinAuth(base::span<const uint8_t> secret, - base::span<const uint8_t> data); +// Protocol abstracts a PIN/UV Auth Token Protocol. Instances are obtained +// through ProtocolVersion(). +class COMPONENT_EXPORT(DEVICE_FIDO) Protocol { + public: + virtual ~Protocol() = default; + Protocol(Protocol&) = delete; + Protocol& operator=(Protocol&) = delete; -// CalculateSharedKey writes the CTAP2 shared key between |key| and |peers_key| -// to |out_shared_key|. -void CalculateSharedKey(const EC_KEY* key, - const EC_POINT* peers_key, - uint8_t out_shared_key[SHA256_DIGEST_LENGTH]); + // Encapsulate derives a shared secret, which it writes to |out_shared_key|, + // and returns the platform's public key. + virtual std::array<uint8_t, kP256X962Length> Encapsulate( + const KeyAgreementResponse& peers_key, + std::vector<uint8_t>* out_shared_key) const = 0; -// Encrypt encrypts |plaintext| using |key|, writing the ciphertext to -// |out_ciphertext|. |plaintext| must be a whole number of AES blocks. -void Encrypt(const uint8_t key[SHA256_DIGEST_LENGTH], - base::span<const uint8_t> plaintext, - uint8_t* out_ciphertext); + // Encrypt encrypts |plaintext| under |shared_key|. |plaintext| must be a + // multiple of AES_BLOCK_SIZE in length. |shared_key| must be a shared secret + // derived by Encapsulate(). + virtual std::vector<uint8_t> Encrypt( + base::span<const uint8_t> shared_key, + base::span<const uint8_t> plaintext) const = 0; -// Decrypt AES-256 CBC decrypts some number of whole blocks from |ciphertext| -// into |plaintext|, using |key|. -void Decrypt(const uint8_t key[SHA256_DIGEST_LENGTH], - base::span<const uint8_t> ciphertext, - uint8_t* out_plaintext); + // Decrypt returns the decryption of |ciphertext|, which must be non-empty and + // a multiple of AES_BLOCK_SIZE in length. |shared_key| must be a shared + // secret derived by Encapsulate(). + virtual std::vector<uint8_t> Decrypt( + base::span<const uint8_t> shared_key, + base::span<const uint8_t> ciphertext) const = 0; + + // Authenticate() returns a signature of |data|. |key| must be either a shared + // secret derived by Encapsulate() or a valid pinUvAuthToken from the same + // PIN/UV Auth Protocol. + virtual std::vector<uint8_t> Authenticate( + base::span<const uint8_t> key, + base::span<const uint8_t> data) const = 0; + + // Verify verifies a signature computed by Authenticate(). + virtual bool Verify(base::span<const uint8_t> key, + base::span<const uint8_t> data, + base::span<const uint8_t> signature) const = 0; + + // CalculateSharedKey returns the CTAP2 shared key between |key| and + // |peers_key|. + virtual std::vector<uint8_t> CalculateSharedKey( + const EC_KEY* key, + const EC_POINT* peers_key) const = 0; + + protected: + Protocol() = default; +}; + +// ProtocolVersion returns the |Protocol| implementation for +// |PINUvAuthProtocol|. +COMPONENT_EXPORT(DEVICE_FIDO) +const Protocol& ProtocolVersion(PINUVAuthProtocol protocol); } // namespace pin } // namespace device
diff --git a/device/fido/pin_unittest.cc b/device/fido/pin_unittest.cc new file mode 100644 index 0000000..c4c7ba5a --- /dev/null +++ b/device/fido/pin_unittest.cc
@@ -0,0 +1,107 @@ +// 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 "device/fido/pin.h" + +#include "components/cbor/reader.h" +#include "device/fido/fido_test_data.h" +#include "device/fido/pin_internal.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/boringssl/src/include/openssl/aes.h" +#include "third_party/boringssl/src/include/openssl/ec.h" +#include "third_party/boringssl/src/include/openssl/ec_key.h" +#include "third_party/boringssl/src/include/openssl/mem.h" +#include "third_party/boringssl/src/include/openssl/nid.h" + +namespace device { +namespace { + +using testing::ElementsAreArray; +using testing::Not; + +class PINProtocolTest : public ::testing::TestWithParam<PINUVAuthProtocol> { + protected: + void SetUp() override { + peer_key_.reset(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); + CHECK(EC_KEY_generate_key(peer_key_.get())); + } + + const pin::Protocol& pin_protocol() { + return pin::ProtocolVersion(GetParam()); + } + + pin::KeyAgreementResponse PeerKeyAgreement() { + std::array<uint8_t, kP256X962Length> peer_x962; + CHECK_EQ(EC_POINT_point2oct(EC_KEY_get0_group(peer_key_.get()), + EC_KEY_get0_public_key(peer_key_.get()), + POINT_CONVERSION_UNCOMPRESSED, peer_x962.data(), + peer_x962.size(), nullptr /* BN_CTX */), + peer_x962.size()); + const base::Optional<pin::KeyAgreementResponse> peer_response = + pin::KeyAgreementResponse::ParseFromCOSE( + pin::EncodeCOSEPublicKey(peer_x962)); + CHECK(peer_response); + return *peer_response; + } + + EC_KEY* peer_key() { return peer_key_.get(); } + + bssl::UniquePtr<EC_KEY> peer_key_; +}; + +TEST_P(PINProtocolTest, EncapsulateDecapsulate) { + // Encapsulate() and CalculateSharedKey() should yield the same shared secret. + std::vector<uint8_t> shared_key; + const std::array<uint8_t, kP256X962Length> platform_x962 = + pin_protocol().Encapsulate(PeerKeyAgreement(), &shared_key); + + const bssl::UniquePtr<EC_GROUP> p256( + EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)); + const bssl::UniquePtr<EC_POINT> platform_point(EC_POINT_new(p256.get())); + ASSERT_TRUE(EC_POINT_oct2point(p256.get(), platform_point.get(), + platform_x962.data(), platform_x962.size(), + /*ctx=*/nullptr)); + + EXPECT_EQ(shared_key.size(), + GetParam() == PINUVAuthProtocol::kV1 ? 32u : 64u); + EXPECT_THAT( + pin_protocol().CalculateSharedKey(peer_key(), platform_point.get()), + ElementsAreArray(shared_key)); +} + +TEST_P(PINProtocolTest, EncryptDecrypt) { + constexpr char kTestPlaintext[] = "pinprotocoltestpinprotocoltest_"; + static_assert(sizeof(kTestPlaintext) % AES_BLOCK_SIZE == 0u, ""); + std::vector<uint8_t> shared_key; + pin_protocol().Encapsulate(PeerKeyAgreement(), &shared_key); + + const std::vector<uint8_t> ciphertext = pin_protocol().Encrypt( + shared_key, base::as_bytes(base::make_span(kTestPlaintext))); + ASSERT_FALSE(ciphertext.empty()); + + EXPECT_THAT(pin_protocol().Decrypt(shared_key, ciphertext), + ElementsAreArray(base::make_span(kTestPlaintext))); +} + +TEST_P(PINProtocolTest, AuthenticateVerify) { + constexpr char kTestMessage[] = "pin protocol test"; + std::vector<uint8_t> shared_key; + pin_protocol().Encapsulate(PeerKeyAgreement(), &shared_key); + + const std::vector<uint8_t> mac = pin_protocol().Authenticate( + shared_key, base::as_bytes(base::make_span(kTestMessage))); + ASSERT_FALSE(mac.empty()); + + EXPECT_TRUE(pin_protocol().Verify( + shared_key, base::as_bytes(base::make_span(kTestMessage)), mac)); +} + +INSTANTIATE_TEST_SUITE_P(All, + PINProtocolTest, + testing::Values(PINUVAuthProtocol::kV1, + PINUVAuthProtocol::kV2)); + +} // namespace +} // namespace device
diff --git a/device/fido/virtual_ctap2_device.cc b/device/fido/virtual_ctap2_device.cc index 6004eaac..3f2efed 100644 --- a/device/fido/virtual_ctap2_device.cc +++ b/device/fido/virtual_ctap2_device.cc
@@ -127,21 +127,6 @@ data.value_or(std::vector<uint8_t>{})))); } -// CheckPINToken returns true iff |pin_auth| is a valid authentication of -// |data| given that the PIN token in effect is |pin_token|. -bool CheckPINToken(base::span<const uint8_t> pin_token, - base::span<const uint8_t> pin_auth, - base::span<const uint8_t> data) { - uint8_t calculated_pin_auth[SHA256_DIGEST_LENGTH]; - unsigned hmac_bytes; - CHECK(HMAC(EVP_sha256(), pin_token.data(), pin_token.size(), data.data(), - data.size(), calculated_pin_auth, &hmac_bytes)); - DCHECK_EQ(sizeof(calculated_pin_auth), static_cast<size_t>(hmac_bytes)); - - return pin_auth.size() == 16 && - CRYPTO_memcmp(pin_auth.data(), calculated_pin_auth, 16) == 0; -} - std::vector<uint8_t> ConstructSignatureBuffer( const AuthenticatorData& authenticator_data, base::span<const uint8_t, kClientDataHashLength> client_data_hash) { @@ -233,9 +218,16 @@ // possession of the PIN, given that |shared_key| is the result of the ECDH key // agreement. CtapDeviceResponseCode ConfirmPresentedPIN( + PINUVAuthProtocol pin_protocol, VirtualCtap2Device::State* state, - const uint8_t shared_key[SHA256_DIGEST_LENGTH], + const std::vector<uint8_t>& shared_key, const std::vector<uint8_t>& encrypted_pin_hash) { + constexpr size_t kPinHashSize = AES_BLOCK_SIZE; + if (encrypted_pin_hash.empty() || + encrypted_pin_hash.size() % kPinHashSize != 0u) { + return CtapDeviceResponseCode::kCtap2ErrPinInvalid; + } + if (state->pin_retries == 0) { return CtapDeviceResponseCode::kCtap2ErrPinBlocked; } @@ -246,16 +238,16 @@ state->pin_retries--; state->pin_retries_since_insertion++; - DCHECK_EQ(encrypted_pin_hash.size() % AES_BLOCK_SIZE, 0ul); - uint8_t pin_hash[AES_BLOCK_SIZE]; - pin::Decrypt(shared_key, encrypted_pin_hash, pin_hash); + std::vector<uint8_t> pin_hash = pin::ProtocolVersion(pin_protocol) + .Decrypt(shared_key, encrypted_pin_hash); uint8_t calculated_pin_hash[SHA256_DIGEST_LENGTH]; SHA256(reinterpret_cast<const uint8_t*>(state->pin.data()), state->pin.size(), calculated_pin_hash); + static_assert(sizeof(calculated_pin_hash) >= kPinHashSize, ""); - if (state->pin.empty() || - CRYPTO_memcmp(pin_hash, calculated_pin_hash, sizeof(pin_hash)) != 0) { + if (state->pin.empty() || pin_hash.size() != kPinHashSize || + CRYPTO_memcmp(pin_hash.data(), calculated_pin_hash, kPinHashSize) != 0) { if (state->pin_retries == 0) { return CtapDeviceResponseCode::kCtap2ErrPinBlocked; } @@ -275,24 +267,13 @@ // SetPIN sets the current PIN based on the ciphertext in |encrypted_pin|, given // that |shared_key| is the result of the ECDH key agreement. -CtapDeviceResponseCode SetPIN(VirtualCtap2Device::State* state, - const uint8_t shared_key[SHA256_DIGEST_LENGTH], +CtapDeviceResponseCode SetPIN(PINUVAuthProtocol protocol, + VirtualCtap2Device::State* state, + const std::vector<uint8_t>& shared_key, const std::vector<uint8_t>& encrypted_pin, const std::vector<uint8_t>& pin_auth) { - // See - // https://fidoalliance.org/specs/fido-v2.0-rd-20180702/fido-client-to-authenticator-protocol-v2.0-rd-20180702.html#settingNewPin - uint8_t calculated_pin_auth[SHA256_DIGEST_LENGTH]; - unsigned hmac_bytes; - CHECK(HMAC(EVP_sha256(), shared_key, SHA256_DIGEST_LENGTH, - encrypted_pin.data(), encrypted_pin.size(), calculated_pin_auth, - &hmac_bytes)); - DCHECK_EQ(sizeof(calculated_pin_auth), static_cast<size_t>(hmac_bytes)); - - static_assert(sizeof(calculated_pin_auth) >= 16, - "calculated_pin_auth is expected to be at least 16 bytes"); - if (pin_auth.size() != 16 || - CRYPTO_memcmp(calculated_pin_auth, pin_auth.data(), pin_auth.size()) != - 0) { + const pin::Protocol& pin_protocol = pin::ProtocolVersion(protocol); + if (!pin_protocol.Verify(shared_key, encrypted_pin, pin_auth)) { return CtapDeviceResponseCode::kCtap2ErrPinAuthInvalid; } @@ -300,8 +281,8 @@ return CtapDeviceResponseCode::kCtap2ErrPinPolicyViolation; } - std::vector<uint8_t> plaintext_pin(encrypted_pin.size()); - pin::Decrypt(shared_key, encrypted_pin, plaintext_pin.data()); + std::vector<uint8_t> plaintext_pin = + pin_protocol.Decrypt(shared_key, encrypted_pin); size_t padding_len = 0; while (padding_len < plaintext_pin.size() && @@ -355,8 +336,8 @@ if (pinauth_it == request_map.end() || !pinauth_it->second.is_bytestring()) { return CtapDeviceResponseCode::kCtap2ErrCBORUnexpectedType; } - if (!CheckPINToken(pin_token, pinauth_it->second.GetBytestring(), - pinauth_bytes)) { + if (!pin::ProtocolVersion(*protocol).Verify( + pin_token, pinauth_bytes, pinauth_it->second.GetBytestring())) { return CtapDeviceResponseCode::kCtap2ErrPinAuthInvalid; } return CtapDeviceResponseCode::kSuccess; @@ -446,13 +427,12 @@ return WriteCBOR(cbor::Value(std::move(response_map)), allow_invalid_utf8); } -std::array<uint8_t, 32> GenerateAndEncryptToken( - base::span<const uint8_t, SHA256_DIGEST_LENGTH> shared_key, +std::vector<uint8_t> GenerateAndEncryptToken( + PINUVAuthProtocol pin_protocol, + base::span<const uint8_t> shared_key, base::span<uint8_t, 32> pin_token) { RAND_bytes(pin_token.data(), pin_token.size()); - std::array<uint8_t, pin_token.size()> encrypted_pin_token; - pin::Encrypt(shared_key.data(), pin_token, encrypted_pin_token.data()); - return encrypted_pin_token; + return pin::ProtocolVersion(pin_protocol).Encrypt(shared_key, pin_token); } } // namespace @@ -849,11 +829,12 @@ } // Verify pinUvAuthParam. - if (CheckPINToken(pin_token, *pin_auth, client_data_hash)) { - uv = true; - } else { + if (!pin::ProtocolVersion(*pin_protocol) + .Verify(pin_token, client_data_hash, *pin_auth)) { return CtapDeviceResponseCode::kCtap2ErrPinAuthInvalid; } + + uv = true; } if (is_make_credential && !uv) { @@ -1290,6 +1271,11 @@ NOTREACHED(); return CtapDeviceResponseCode::kCtap2ErrMissingParameter; } + if (!request.pin_protocol) { + return CtapDeviceResponseCode::kCtap2ErrPinAuthInvalid; + } + const pin::Protocol& pin_protocol = + pin::ProtocolVersion(*request.pin_protocol); const auto& x962 = request.hmac_secret->public_key_x962; bssl::UniquePtr<EC_GROUP> p256( @@ -1301,9 +1287,8 @@ return CtapDeviceResponseCode::kCtap1ErrInvalidParameter; } - uint8_t shared_key[SHA256_DIGEST_LENGTH]; - pin::CalculateSharedKey(mutable_state()->ecdh_key.get(), - platform_point.get(), shared_key); + std::vector<uint8_t> shared_key = pin_protocol.CalculateSharedKey( + mutable_state()->ecdh_key.get(), platform_point.get()); const auto& encrypted_salts = request.hmac_secret->encrypted_salts; if (encrypted_salts.size() != 32 && encrypted_salts.size() != 64) { @@ -1311,26 +1296,27 @@ return CtapDeviceResponseCode::kCtap1ErrInvalidParameter; } - uint8_t salts[64]; - pin::Decrypt(shared_key, encrypted_salts, salts); + std::vector<uint8_t> salts = + pin_protocol.Decrypt(shared_key, encrypted_salts); + CHECK_EQ(salts.size(), encrypted_salts.size()); - if (pin::MakePinAuth(shared_key, encrypted_salts) != + if (pin_protocol.Authenticate(shared_key, encrypted_salts) != request.hmac_secret->salts_auth) { NOTREACHED(); return CtapDeviceResponseCode::kCtap1ErrInvalidParameter; } hmac_salt1.emplace(); - memcpy(hmac_salt1->data(), salts, hmac_salt1->size()); + memcpy(hmac_salt1->data(), salts.data(), hmac_salt1->size()); if (encrypted_salts.size() == 64) { hmac_salt2.emplace(); - memcpy(hmac_salt2->data(), salts + hmac_salt1->size(), + memcpy(hmac_salt2->data(), salts.data() + hmac_salt1->size(), hmac_salt2->size()); } hmac_shared_key.emplace(); - CHECK_EQ(hmac_shared_key->size(), sizeof(shared_key)); - memcpy(hmac_shared_key->data(), shared_key, sizeof(shared_key)); + CHECK_EQ(hmac_shared_key->size(), shared_key.size()); + memcpy(hmac_shared_key->data(), shared_key.data(), shared_key.size()); } // This implementation does not sort credentials by creation time as the spec @@ -1377,8 +1363,10 @@ &hmac_result[sizeof(hmac_result)]); } - std::vector<uint8_t> encrypted_outputs(outputs.size()); - pin::Encrypt(hmac_shared_key->data(), outputs, encrypted_outputs.data()); + std::vector<uint8_t> encrypted_outputs = + pin::ProtocolVersion(*request.pin_protocol) + .Encrypt(*hmac_shared_key, outputs); + CHECK_EQ(encrypted_outputs.size(), outputs.size()); extensions_map.emplace(kExtensionHmacSecret, std::move(encrypted_outputs)); @@ -1586,8 +1574,7 @@ const auto peer_key = GetPINKey(request_map, pin::RequestKey::kKeyAgreement); - if (!encrypted_pin || (encrypted_pin->size() % AES_BLOCK_SIZE) != 0 || - !pin_auth || !peer_key) { + if (!encrypted_pin || !pin_auth || !peer_key) { return CtapDeviceResponseCode::kCtap2ErrMissingParameter; } @@ -1595,17 +1582,19 @@ return CtapDeviceResponseCode::kCtap2ErrPinAuthInvalid; } - uint8_t shared_key[SHA256_DIGEST_LENGTH]; if (!mutable_state()->ecdh_key) { // kGetKeyAgreement should have been called first. NOTREACHED(); return CtapDeviceResponseCode::kCtap2ErrPinTokenExpired; } - pin::CalculateSharedKey(mutable_state()->ecdh_key.get(), peer_key->get(), - shared_key); + std::vector<uint8_t> shared_key = + pin::ProtocolVersion(*pin_protocol) + .CalculateSharedKey(mutable_state()->ecdh_key.get(), + peer_key->get()); CtapDeviceResponseCode err = - SetPIN(mutable_state(), shared_key, *encrypted_pin, *pin_auth); + SetPIN(*pin_protocol, mutable_state(), shared_key, *encrypted_pin, + *pin_auth); if (err != CtapDeviceResponseCode::kSuccess) { return err; } @@ -1628,25 +1617,29 @@ const auto peer_key = GetPINKey(request_map, pin::RequestKey::kKeyAgreement); - if (!encrypted_pin_hash || encrypted_pin_hash->size() != AES_BLOCK_SIZE || - !encrypted_new_pin || - (encrypted_new_pin->size() % AES_BLOCK_SIZE) != 0 || !pin_auth || - !peer_key) { + if (!encrypted_pin_hash || !encrypted_new_pin || !pin_auth || !peer_key) { return CtapDeviceResponseCode::kCtap2ErrMissingParameter; } - uint8_t shared_key[SHA256_DIGEST_LENGTH]; - pin::CalculateSharedKey(mutable_state()->ecdh_key.get(), peer_key->get(), - shared_key); + if (!mutable_state()->ecdh_key) { + // kGetKeyAgreement should have been called first. + NOTREACHED(); + return CtapDeviceResponseCode::kCtap2ErrPinTokenExpired; + } + std::vector<uint8_t> shared_key = + pin::ProtocolVersion(*pin_protocol) + .CalculateSharedKey(mutable_state()->ecdh_key.get(), + peer_key->get()); - CtapDeviceResponseCode err = - ConfirmPresentedPIN(mutable_state(), shared_key, *encrypted_pin_hash); + CtapDeviceResponseCode err = ConfirmPresentedPIN( + *pin_protocol, mutable_state(), shared_key, *encrypted_pin_hash); if (err != CtapDeviceResponseCode::kSuccess) { RegenerateKeyAgreementKey(); return err; } - err = SetPIN(mutable_state(), shared_key, *encrypted_new_pin, *pin_auth); + err = SetPIN(*pin_protocol, mutable_state(), shared_key, + *encrypted_new_pin, *pin_auth); if (err != CtapDeviceResponseCode::kSuccess) { return err; } @@ -1668,8 +1661,7 @@ const auto peer_key = GetPINKey(request_map, pin::RequestKey::kKeyAgreement); - if (!encrypted_pin_hash || encrypted_pin_hash->size() != AES_BLOCK_SIZE || - !peer_key) { + if (!encrypted_pin_hash || !peer_key) { return CtapDeviceResponseCode::kCtap2ErrMissingParameter; } @@ -1698,17 +1690,18 @@ } } - uint8_t shared_key[SHA256_DIGEST_LENGTH]; if (!mutable_state()->ecdh_key) { // kGetKeyAgreement should have been called first. NOTREACHED(); return CtapDeviceResponseCode::kCtap2ErrPinTokenExpired; } - pin::CalculateSharedKey(mutable_state()->ecdh_key.get(), peer_key->get(), - shared_key); + std::vector<uint8_t> shared_key = + pin::ProtocolVersion(*pin_protocol) + .CalculateSharedKey(mutable_state()->ecdh_key.get(), + peer_key->get()); - CtapDeviceResponseCode err = - ConfirmPresentedPIN(mutable_state(), shared_key, *encrypted_pin_hash); + CtapDeviceResponseCode err = ConfirmPresentedPIN( + *pin_protocol, mutable_state(), shared_key, *encrypted_pin_hash); if (err != CtapDeviceResponseCode::kSuccess) { RegenerateKeyAgreementKey(); return err; @@ -1719,9 +1712,9 @@ mutable_state()->pin_uv_token_permissions = permissions.permissions; mutable_state()->pin_uv_token_rpid = permissions.rp_id; - response_map.emplace( - static_cast<int>(pin::ResponseKey::kPINToken), - GenerateAndEncryptToken(shared_key, mutable_state()->pin_token)); + response_map.emplace(static_cast<int>(pin::ResponseKey::kPINToken), + GenerateAndEncryptToken(*pin_protocol, shared_key, + mutable_state()->pin_token)); break; } @@ -1749,14 +1742,15 @@ return CtapDeviceResponseCode::kCtap2ErrUvBlocked; } - uint8_t shared_key[SHA256_DIGEST_LENGTH]; if (!mutable_state()->ecdh_key) { // kGetKeyAgreement should have been called first. NOTREACHED(); return CtapDeviceResponseCode::kCtap2ErrPinTokenExpired; } - pin::CalculateSharedKey(mutable_state()->ecdh_key.get(), peer_key->get(), - shared_key); + std::vector<uint8_t> shared_key = + pin::ProtocolVersion(*pin_protocol) + .CalculateSharedKey(mutable_state()->ecdh_key.get(), + peer_key->get()); --mutable_state()->uv_retries; @@ -1773,9 +1767,9 @@ mutable_state()->pin_uv_token_permissions = permissions.permissions; mutable_state()->pin_uv_token_rpid = permissions.rp_id; - response_map.emplace( - static_cast<int>(pin::ResponseKey::kPINToken), - GenerateAndEncryptToken(shared_key, mutable_state()->pin_token)); + response_map.emplace(static_cast<int>(pin::ResponseKey::kPINToken), + GenerateAndEncryptToken(*pin_protocol, shared_key, + mutable_state()->pin_token)); break; }
diff --git a/docs/windows_shortcut_and_taskbar_handling.md b/docs/windows_shortcut_and_taskbar_handling.md new file mode 100644 index 0000000..655d6ab8 --- /dev/null +++ b/docs/windows_shortcut_and_taskbar_handling.md
@@ -0,0 +1,75 @@ +# Windows Shortcut and Pinned Taskbar Icon handling + +When Chrome is installed on Windows, it creates a shortcut on the desktop that +launches Chrome. It also adds the same shortcut to the start menu. These +shortcuts do not specify a profile, so they launch Chrome with the most recently +used profile. + +Windows allows users to pin applications to the taskbar. When a user +pins an application to the taskbar, Windows looks for a desktop shortcut that +matches the application, and if it finds one, it creates a .lnk file in the +directory +`<user dir>\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar.` +If it does not find a matching desktop shortcut, it creates an 8-hex-digit +sub-directory of +`<user dir>\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\ImplicitAppShortcuts\` +and puts the .lnk file in that directory. For example, 3ffff1b1b170b31e. + +App windows on Windows have an +[App User Model ID (AUMI)](https://docs.microsoft.com/en-us/windows/win32/shell/appids) +property. For Chrome windows, this is set in +[BrowserWindowPropertyManager::UpdateWindowProperties](https://source.chromium.org/chromium/chromium/src/+/master:chrome/browser/ui/views/frame/browser_window_property_manager_win.cc?q=BrowserWindowPropertyManager::UpdateWindowProperties), +when a window is opened. Windows desktop shortcuts have an app model property, +and this should match the open window's AUMI. Windows groups open windows with +the same AUMI to a taskbar icon. + +There are two kinds of Chrome windows with AUMI's: browser windows, and app +windows, which include web apps, and extensions, i.e., windows opened via +--app-id or --app. + +[GetAppUserModelIdForBrowser](https://source.chromium.org/chromium/chromium/src/+/master:chrome/browser/shell_integration_win.cc?q=GetAppUserModelIdForBrowser) +constructs an AUMI for a browser window and +[GetAppUserModelIdForApp](https://source.chromium.org/chromium/chromium/src/+/master:chrome/browser/shell_integration_win.cc?q=GetAppUserModelIdForApp) +constructs an AUMI for an app window. Each calls +[ShellUtil::BuildAppUserModelId](https://source.chromium.org/chromium/chromium/src/+/master:chrome/installer/util/shell_util.cc;q=ShellUtil::BuildAppUserModelId) +to construct the AUMI out of component strings. + +All AUMI's start with the base app id, +[install_static::GetBaseAppId](https://source.chromium.org/chromium/chromium/src/+/master:chrome/install_static/install_util.cc?q=install_static::GetBaseAppId). +This varies for different Chrome channels (e.g., Canary vs. Stable) and +different Chromium-based browsers (e.g., Chrome vs. Chromium). + +The AUMI for a browser app has the format: +`<BaseAppId>.<app_name>[.<profile_name>]`. +profile_name is only appended when it's not the default profile. + +The AUMI for a Chrome browser window has the format: +`<BaseAppId>[browser_suffix][.profile_name]`. +profile_name is only appended when it's not the default profile. +browser_suffix is only appended to the BaseAppId if the installer +has set the kRegisterChromeBrowserSuffix command line switch, e.g., +on user-level installs. + +Since AUMI's for browser and app windows include the profile_name, each +profile's windows will be grouped together on the taskbar. + +shell_integration_win.cc has a function [GetExpectedAppId](https://source.chromium.org/chromium/chromium/src/+/master:chrome/browser/shell_integration_win.cc?q=GetExpectedAppid) +to determine what the AUMI for a shortcut should be. It also has a function +[MigrateTaskbarPins](https://source.chromium.org/chromium/chromium/src/+/master:chrome/browser/shell_integration_win.cc?q=MigrateTaskbarPins) +to migrate pinned taskbar icons if the AUMI's need to change. + +## Multi-profile Support +When the user has more than one profile, the shortcuts are renamed to include +the profile name, e.g., `Chrome.lnk` becomes `<profile name> - Chrome`. The +shortcut icons, both desktop and taskbar, are badged with their profile icon. +This badged icon is also used in the tab preview for a Chrome window. + +## Diagnosing Issues +To dump a taskbar icon's properties, run this command: + +`python \src\chromium\src\chrome\installer\tools\shortcut_properties.py --dump-all <user dir>\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar` + +This shows you the properties of all the taskbar pinned icons. If the taskbar +icon is in a subdirectory of ImplicitApps, pass that directory to +shortcut_properties.py. +
diff --git a/fuchsia/engine/browser/accessibility_bridge.cc b/fuchsia/engine/browser/accessibility_bridge.cc index b45b4966..16bd613f 100644 --- a/fuchsia/engine/browser/accessibility_bridge.cc +++ b/fuchsia/engine/browser/accessibility_bridge.cc
@@ -115,17 +115,6 @@ TryCommit(); } -uint32_t AccessibilityBridge::ConvertToFuchsiaNodeId(int32_t ax_node_id) { - if (ax_node_id == root_id_) { - // On the Fuchsia side, the root node is indicated by id - // |kSemanticNodeRootId|, which is 0. - return kSemanticNodeRootId; - } else { - // AXNode ids are signed, Semantic Node ids are unsigned. - return bit_cast<uint32_t>(ax_node_id); - } -} - void AccessibilityBridge::AccessibilityEventReceived( const content::AXEventNotificationDetails& details) { // Updates to AXTree must be applied first. @@ -143,7 +132,7 @@ pending_hit_test_callbacks_.find(event.action_request_id) != pending_hit_test_callbacks_.end()) { fuchsia::accessibility::semantics::Hit hit; - hit.set_node_id(ConvertToFuchsiaNodeId(event.id)); + hit.set_node_id(ConvertToFuchsiaNodeId(event.id, root_id_)); // Run the pending callback with the hit. pending_hit_test_callbacks_[event.action_request_id](std::move(hit)); @@ -236,7 +225,7 @@ if (node->id() != root_id_) { to_send_.push_back( SemanticUpdateOrDelete(SemanticUpdateOrDelete::Type::DELETE, {}, - ConvertToFuchsiaNodeId(node->id()))); + ConvertToFuchsiaNodeId(node->id(), root_id_))); } for (ui::AXNode* child : node->children()) DeleteSubtree(child);
diff --git a/fuchsia/engine/browser/accessibility_bridge.h b/fuchsia/engine/browser/accessibility_bridge.h index 8165b12..35669c5 100644 --- a/fuchsia/engine/browser/accessibility_bridge.h +++ b/fuchsia/engine/browser/accessibility_bridge.h
@@ -86,10 +86,6 @@ // Callback for SemanticTree::CommitUpdates. void OnCommitComplete(); - // Converts AXNode ids to Semantic Node ids, and handles special casing of - // the root. - uint32_t ConvertToFuchsiaNodeId(int32_t ax_node_id); - // Deletes all nodes in subtree rooted at and including |node|, unless // |node| is the root of the tree. |tree| and |node| are owned by the // accessibility bridge.
diff --git a/fuchsia/engine/browser/ax_tree_converter.cc b/fuchsia/engine/browser/ax_tree_converter.cc index 7fa4346..43f9089 100644 --- a/fuchsia/engine/browser/ax_tree_converter.cc +++ b/fuchsia/engine/browser/ax_tree_converter.cc
@@ -8,9 +8,11 @@ #include <fuchsia/ui/gfx/cpp/fidl.h> #include <fuchsia/ui/views/cpp/fidl.h> #include <lib/ui/scenic/cpp/commands.h> +#include <stdint.h> #include <vector> #include "base/bit_cast.h" +#include "base/numerics/safe_conversions.h" #include "ui/accessibility/ax_enums.mojom.h" #include "ui/accessibility/ax_tree_id.h" #include "ui/gfx/geometry/rect_f.h" @@ -19,6 +21,14 @@ namespace { +// Fuchsia's default root node ID. +constexpr uint32_t kFuchsiaRootNodeId = 0; + +// Remmaped value for an AxNode ID that is 0 and is not a root. +// Value is chosen specifically to be outside the range of a 32-bit signed int, +// so as to not conflict with other values used by Chromium. +constexpr uint32_t kZeroIdRemappedForFuchsia = 1u + INT32_MAX; + fuchsia::accessibility::semantics::Role ConvertRole(ax::mojom::Role role) { if (role == ax::mojom::Role::kButton) return fuchsia::accessibility::semantics::Role::BUTTON; @@ -152,7 +162,7 @@ std::vector<uint32_t> child_ids; child_ids.reserve(ids.size()); for (auto i : ids) { - child_ids.push_back(bit_cast<uint32_t>(i)); + child_ids.push_back(base::checked_cast<uint32_t>(i)); } return child_ids; } @@ -182,7 +192,7 @@ fuchsia::accessibility::semantics::Node AXNodeDataToSemanticNode( const ui::AXNodeData& node) { fuchsia::accessibility::semantics::Node fuchsia_node; - fuchsia_node.set_node_id(bit_cast<uint32_t>(node.id)); + fuchsia_node.set_node_id(base::checked_cast<uint32_t>(node.id)); fuchsia_node.set_role(ConvertRole(node.role)); fuchsia_node.set_states(ConvertStates(node)); fuchsia_node.set_attributes(ConvertAttributes(node)); @@ -223,3 +233,16 @@ return false; } } + +uint32_t ConvertToFuchsiaNodeId(int32_t ax_node_id, int32_t ax_root_node_id) { + if (ax_node_id == ax_root_node_id) + return kFuchsiaRootNodeId; + + if (ax_node_id == kFuchsiaRootNodeId) { + // This AxNode is not the root, but its ID is the same as Fuchsia's root ID. + // We remap it to something different to not create a confflict. + return kZeroIdRemappedForFuchsia; + } + + return base::checked_cast<uint32_t>(ax_node_id); +}
diff --git a/fuchsia/engine/browser/ax_tree_converter.h b/fuchsia/engine/browser/ax_tree_converter.h index 839c988..bdb8e6e 100644 --- a/fuchsia/engine/browser/ax_tree_converter.h +++ b/fuchsia/engine/browser/ax_tree_converter.h
@@ -24,4 +24,13 @@ bool ConvertAction(fuchsia::accessibility::semantics::Action fuchsia_action, ax::mojom::Action* mojom_action); +// Converts |ax_node_id|, which is signed, to a Fuchsia node ID, which is +// unsigned. +// Fuchsia requires root node IDs to be zero. This function ensures +// that the conversion takes that into account. +// If |ax_node_id| is 0 and is not the root, we return the +// MAX(int32_t) + 1, which is a number that will never conflict with other IDs. +WEB_ENGINE_EXPORT uint32_t ConvertToFuchsiaNodeId(int32_t ax_node_id, + int32_t ax_root_node_id); + #endif // FUCHSIA_ENGINE_BROWSER_AX_TREE_CONVERTER_H_
diff --git a/fuchsia/engine/browser/ax_tree_converter_unittest.cc b/fuchsia/engine/browser/ax_tree_converter_unittest.cc index 16bdfba..cec422f3 100644 --- a/fuchsia/engine/browser/ax_tree_converter_unittest.cc +++ b/fuchsia/engine/browser/ax_tree_converter_unittest.cc
@@ -41,6 +41,9 @@ base::StringPiece description, ax::mojom::CheckedState checked_state) { ui::AXNodeData node; + // Important! ID must be set to zero here because its default value (-1), will + // fail when getting converted to an unsigned int (Fuchsia's ID format). + node.id = 0; node.role = role; node.AddAction(action); node.AddIntAttribute(ax::mojom::IntAttribute::kCheckedState, @@ -113,8 +116,9 @@ states.set_hidden(false); states.set_selected(false); auto expected_node = CreateSemanticNode( - source_node_data.id, Role::BUTTON, std::move(attributes), - std::move(states), std::vector<Action>{Action::SET_FOCUS}, + static_cast<uint32_t>(source_node_data.id), Role::BUTTON, + std::move(attributes), std::move(states), + std::vector<Action>{Action::SET_FOCUS}, std::vector<uint32_t>{kChildId1, kChildId2, kChildId3}, box, mat.value); EXPECT_TRUE(fidl::Equals(converted_node, expected_node)); @@ -122,6 +126,7 @@ TEST_F(AXTreeConverterTest, SomeFieldsSetAndEqual) { ui::AXNodeData source_node_data; + source_node_data.id = 0; source_node_data.AddAction(ax::mojom::Action::kFocus); source_node_data.AddAction(ax::mojom::Action::kSetValue); source_node_data.child_ids = std::vector<int32_t>{kChildId1}; @@ -133,10 +138,11 @@ converted_node.node_id()); Node expected_node; - expected_node.set_node_id(source_node_data.id); + expected_node.set_node_id(static_cast<uint32_t>(source_node_data.id)); expected_node.set_actions( std::vector<Action>{Action::SET_FOCUS, Action::SET_VALUE}); - expected_node.set_child_ids(std::vector<uint32_t>{kChildId1}); + expected_node.set_child_ids( + std::vector<uint32_t>{static_cast<uint32_t>(kChildId1)}); expected_node.set_role(Role::IMAGE); States states; states.set_hidden(false); @@ -198,4 +204,19 @@ EXPECT_FALSE(fidl::Equals(converted_node, expected_node)); } +TEST_F(AXTreeConverterTest, ConvertToFuchsiaNodeId) { + // Root AxNode is 0, Fuchsia is also 0. + EXPECT_EQ(0u, ConvertToFuchsiaNodeId(0, 0)); + + // Root AxNode is not 0, Fuchsia is still 0. + EXPECT_EQ(0u, ConvertToFuchsiaNodeId(2, 2)); + + // Regular AxNode is 0, Fuchsia can't be 0. + EXPECT_EQ(static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) + 1, + ConvertToFuchsiaNodeId(0, 2)); + + // Regular AxNode is not 0, Fuchsia is same value. + EXPECT_EQ(10u, ConvertToFuchsiaNodeId(10, 0)); +} + } // namespace
diff --git a/fuchsia/engine/web_engine_integration_test.cc b/fuchsia/engine/web_engine_integration_test.cc index 329885af..56a0d50 100644 --- a/fuchsia/engine/web_engine_integration_test.cc +++ b/fuchsia/engine/web_engine_integration_test.cc
@@ -690,9 +690,8 @@ #endif class MAYBE_VulkanWebEngineIntegrationTest : public WebEngineIntegrationTest {}; -// TODO(crbug.com/1104563): Flakily times-out. TEST_F(MAYBE_VulkanWebEngineIntegrationTest, - DISABLED_WebGLContextPresentWithVulkanFeature) { + WebGLContextPresentWithVulkanFeature) { fuchsia::web::CreateContextParams create_params = DefaultContextParams(); create_params.set_features(fuchsia::web::ContextFeatureFlags::VULKAN); CreateContextAndFrame(std::move(create_params));
diff --git a/fuchsia/runners/cast/cast_runner.cc b/fuchsia/runners/cast/cast_runner.cc index fa15d03..af4f3a3 100644 --- a/fuchsia/runners/cast/cast_runner.cc +++ b/fuchsia/runners/cast/cast_runner.cc
@@ -67,6 +67,9 @@ return false; } +// Ephemeral remote debugging port used by child contexts. +const uint16_t kEphemeralRemoteDebuggingPort = 0; + } // namespace CastRunner::CastRunner(bool is_headless) @@ -226,8 +229,6 @@ params.set_user_agent_product("CrKey"); params.set_user_agent_version("1.43.000000"); - params.set_remote_debugging_port(CastRunner::kRemoteDebuggingPort); - // When tests require that VULKAN be disabled, DRM must also be disabled. if (disable_vulkan_for_test_) { *params.mutable_features() &= @@ -248,6 +249,7 @@ fuchsia::web::CreateContextParams CastRunner::GetMainContextParams() { fuchsia::web::CreateContextParams params = GetCommonContextParams(); + params.set_remote_debugging_port(CastRunner::kRemoteDebuggingPort); *params.mutable_features() |= fuchsia::web::ContextFeatureFlags::NETWORK | fuchsia::web::ContextFeatureFlags::LEGACYMETRICS; @@ -266,6 +268,7 @@ CastRunner::GetIsolatedContextParamsWithFuchsiaDirs( std::vector<fuchsia::web::ContentDirectoryProvider> content_directories) { fuchsia::web::CreateContextParams params = GetCommonContextParams(); + params.set_remote_debugging_port(kEphemeralRemoteDebuggingPort); params.set_content_directories(std::move(content_directories)); isolated_services_->ConnectClient( params.mutable_service_directory()->NewRequest()); @@ -275,6 +278,7 @@ fuchsia::web::CreateContextParams CastRunner::GetIsolatedContextParamsForCastStreaming() { fuchsia::web::CreateContextParams params = GetCommonContextParams(); + params.set_remote_debugging_port(kEphemeralRemoteDebuggingPort); ApplyCastStreamingContextParams(¶ms); // TODO(crbug.com/1069746): Use a different FilteredServiceDirectory for Cast // Streaming Contexts.
diff --git a/ios/chrome/browser/crash_report/synthetic_crash_report_util.mm b/ios/chrome/browser/crash_report/synthetic_crash_report_util.mm index f618c15..5772f318 100644 --- a/ios/chrome/browser/crash_report/synthetic_crash_report_util.mm +++ b/ios/chrome/browser/crash_report/synthetic_crash_report_util.mm
@@ -72,6 +72,24 @@ "BreakpadServerParameterPrefix_memory_warning_in_progress", "yes"); } + + if (previous_session.applicationState && + *(previous_session.applicationState) == UIApplicationStateBackground) { + AppendConfig(config, "BreakpadServerParameterPrefix_crashed_in_background", + "yes"); + } + + if (previous_session.terminatedDuringSessionRestoration) { + AppendConfig(config, + "BreakpadServerParameterPrefix_crashed_during_session_restore", + "yes"); + } + + if (previous_session.OSVersion) { + AppendConfig(config, "BreakpadServerParameterPrefix_os_version", + base::SysNSStringToUTF8(previous_session.OSVersion)); + } + AppendConfig(config, "BreakpadServerParameterPrefix_platform", base::SysInfo::HardwareModelName());
diff --git a/ios/chrome/browser/crash_report/synthetic_crash_report_util_unittest.mm b/ios/chrome/browser/crash_report/synthetic_crash_report_util_unittest.mm index 82815b5..fc681d66 100644 --- a/ios/chrome/browser/crash_report/synthetic_crash_report_util_unittest.mm +++ b/ios/chrome/browser/crash_report/synthetic_crash_report_util_unittest.mm
@@ -37,6 +37,9 @@ PreviousSessionInfo* previous_session = [PreviousSessionInfo sharedInstance]; previous_session.availableDeviceStorage = kAvailableStorage; previous_session.didSeeMemoryWarningShortlyBeforeTerminating = YES; + NSString* const kOSVersion = @"OSVersion"; + previous_session.OSVersion = kOSVersion; + previous_session.terminatedDuringSessionRestoration = YES; // Create crash report. base::ScopedTempDir temp_dir; @@ -93,7 +96,7 @@ // Verify config file content. Config file has the following format: // <Key1>\n<Value1Length>\n<Value1>\n...<KeyN>\n<ValueNLength>\n<ValueN> - ASSERT_EQ(33U, config_lines.size()) + ASSERT_EQ(39U, config_lines.size()) << "<content>" << config_content << "</content>"; EXPECT_EQ("MinidumpDir", config_lines[0]); @@ -144,10 +147,19 @@ EXPECT_EQ(base::NumberToString(strlen(kYesString)), config_lines[28]); EXPECT_EQ(kYesString, config_lines[29]); - EXPECT_EQ("BreakpadServerParameterPrefix_platform", config_lines[30]); + EXPECT_EQ("BreakpadServerParameterPrefix_crashed_during_session_restore", + config_lines[30]); + EXPECT_EQ(base::NumberToString(strlen(kYesString)), config_lines[31]); + EXPECT_EQ(kYesString, config_lines[32]); + + EXPECT_EQ("BreakpadServerParameterPrefix_os_version", config_lines[33]); + EXPECT_EQ(base::NumberToString(kOSVersion.length), config_lines[34]); + EXPECT_EQ(base::SysNSStringToUTF8(kOSVersion), config_lines[35]); + + EXPECT_EQ("BreakpadServerParameterPrefix_platform", config_lines[36]); EXPECT_EQ(base::NumberToString(base::SysInfo::HardwareModelName().size()), - config_lines[31]); - EXPECT_EQ(base::SysInfo::HardwareModelName(), config_lines[32]); + config_lines[37]); + EXPECT_EQ(base::SysInfo::HardwareModelName(), config_lines[38]); // Read minidump file. It must be empty as there is no stack trace, but // Breakpad will not upload config without minidump file.
diff --git a/ios/chrome/browser/metrics/previous_session_info_private.h b/ios/chrome/browser/metrics/previous_session_info_private.h index 6be2b24..026c0a7 100644 --- a/ios/chrome/browser/metrics/previous_session_info_private.h +++ b/ios/chrome/browser/metrics/previous_session_info_private.h
@@ -17,6 +17,8 @@ @property(nonatomic, assign) previous_session_info_constants::DeviceBatteryState deviceBatteryState; @property(nonatomic, assign) BOOL OSRestartedAfterPreviousSession; +@property(nonatomic, copy) NSString* OSVersion; +@property(nonatomic, assign) BOOL terminatedDuringSessionRestoration; @property(nonatomic, strong) NSMutableSet<NSString*>* connectedSceneSessionsIDs; + (void)resetSharedInstanceForTesting;
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/password_view_controller_egtest.mm b/ios/chrome/browser/ui/autofill/manual_fill/password_view_controller_egtest.mm index ddd563cb..d46999a0 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/password_view_controller_egtest.mm +++ b/ios/chrome/browser/ui/autofill/manual_fill/password_view_controller_egtest.mm
@@ -268,9 +268,6 @@ // Verify keyboard is shown without the password controller. GREYAssertTrue([ChromeEarlGrey isKeyboardShownWithError:nil], @"Keyboard Should be Shown"); - [[EarlGrey - selectElementWithMatcher:chrome_test_util::NavigationBarCancelButton()] - performAction:grey_tap()]; [[EarlGrey selectElementWithMatcher:ManualFallbackPasswordTableViewMatcher()] assertWithMatcher:grey_notVisible()]; }
diff --git a/ios/chrome/browser/ui/settings/password/BUILD.gn b/ios/chrome/browser/ui/settings/password/BUILD.gn index 3f25afa..0ac4f31 100644 --- a/ios/chrome/browser/ui/settings/password/BUILD.gn +++ b/ios/chrome/browser/ui/settings/password/BUILD.gn
@@ -233,7 +233,6 @@ ":password_constants", "//base:base", "//base/test:test_support", - "//components/password_manager/core/common", "//components/strings:components_strings_grit", "//ios/chrome/app/strings:ios_strings_grit", "//ios/chrome/browser/ui/settings:settings_root_constants",
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_constants.mm b/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_constants.mm index e1901d4..c74c413 100644 --- a/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_constants.mm +++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_constants.mm
@@ -9,4 +9,4 @@ #endif NSString* const kPasswordDetailsViewControllerId = - @"PasswordDetailsTableViewId"; + @"kPasswordDetailsViewControllerId";
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller.mm b/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller.mm index 3c89c5c..0ae4468b 100644 --- a/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller.mm
@@ -210,8 +210,6 @@ item.identifyingIcon = [[UIImage imageNamed:image] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; item.identifyingIconEnabled = YES; - item.identifyingIconAccessibilityLabel = - l10n_util::GetNSString(IDS_IOS_SETTINGS_PASSWORD_SHOW_BUTTON); } return item; }
diff --git a/ios/chrome/browser/ui/settings/password/passwords_settings_egtest.mm b/ios/chrome/browser/ui/settings/password/passwords_settings_egtest.mm index ba4d7ced..00d88eb 100644 --- a/ios/chrome/browser/ui/settings/password/passwords_settings_egtest.mm +++ b/ios/chrome/browser/ui/settings/password/passwords_settings_egtest.mm
@@ -8,9 +8,7 @@ #include "base/callback.h" #include "base/ios/ios_util.h" -#include "base/test/scoped_feature_list.h" #include "base/time/time.h" -#include "components/password_manager/core/common/password_manager_features.h" #include "components/strings/grit/components_strings.h" #include "ios/chrome/browser/ui/settings/password/passwords_settings_app_interface.h" #import "ios/chrome/browser/ui/settings/password/passwords_table_view_constants.h" @@ -48,7 +46,6 @@ // go here, the rest into the unittest. using chrome_test_util::ButtonWithAccessibilityLabel; -using chrome_test_util::ButtonWithAccessibilityLabelId; using chrome_test_util::NavigationBarDoneButton; using chrome_test_util::SettingsDoneButton; using chrome_test_util::SettingsMenuBackButton; @@ -61,11 +58,6 @@ // it too high could result in scrolling way past the searched element. constexpr int kScrollAmount = 150; -NSString* GetTextFieldForID(int category_id) { - return [NSString - stringWithFormat:@"%@_textField", l10n_util::GetNSString(category_id)]; -} - // Returns the GREYElementInteraction* for the item on the password list with // the given |matcher|. It scrolls in |direction| if necessary to ensure that // the matched item is interactable. @@ -92,12 +84,22 @@ id<GREYMatcher> matcher) { return [[EarlGrey selectElementWithMatcher:grey_allOf(matcher, grey_interactable(), nil)] - usingSearchAction:grey_scrollToContentEdge(kGREYContentEdgeTop) + usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, + kScrollAmount) onElementWithMatcher:grey_accessibilityID(kPasswordDetailsTableViewId)]; } // Returns the GREYElementInteraction* for the item on the deletion alert // identified with the given |matcher|. +GREYElementInteraction* GetInteractionForPasswordDetailDeletionAlert( + id<GREYMatcher> matcher) { + return [[EarlGrey + selectElementWithMatcher:grey_allOf(matcher, grey_interactable(), nil)] + inRoot:grey_accessibilityID(kPasswordDetailsDeletionAlertViewId)]; +} + +// Returns the GREYElementInteraction* for the item on the deletion alert +// identified with the given |matcher|. GREYElementInteraction* GetInteractionForPasswordsExportConfirmAlert( id<GREYMatcher> matcher) { return [[EarlGrey @@ -118,6 +120,34 @@ return grey_accessibilityID(kPasswordsSearchBarId); } +id<GREYMatcher> SiteHeader() { + return grey_allOf( + grey_accessibilityLabel( + l10n_util::GetNSString(IDS_IOS_SHOW_PASSWORD_VIEW_SITE)), + grey_accessibilityTrait(UIAccessibilityTraitHeader), nullptr); +} + +id<GREYMatcher> UsernameHeader() { + return grey_allOf( + grey_accessibilityLabel( + l10n_util::GetNSString(IDS_IOS_SHOW_PASSWORD_VIEW_USERNAME)), + grey_accessibilityTrait(UIAccessibilityTraitHeader), nullptr); +} + +id<GREYMatcher> PasswordHeader() { + return grey_allOf( + grey_accessibilityLabel( + l10n_util::GetNSString(IDS_IOS_SHOW_PASSWORD_VIEW_PASSWORD)), + grey_accessibilityTrait(UIAccessibilityTraitHeader), nullptr); +} + +id<GREYMatcher> FederationHeader() { + return grey_allOf( + grey_accessibilityLabel( + l10n_util::GetNSString(IDS_IOS_SHOW_PASSWORD_VIEW_FEDERATION)), + grey_accessibilityTrait(UIAccessibilityTraitHeader), nullptr); +} + GREYLayoutConstraint* Below() { return [GREYLayoutConstraint layoutConstraintWithAttribute:kGREYLayoutAttributeTop @@ -128,24 +158,39 @@ } // Matcher for the Copy site button in Password Details view. -id<GREYMatcher> PasswordDetailWebsite() { +id<GREYMatcher> CopySiteButton() { return grey_allOf( - grey_accessibilityID(GetTextFieldForID(IDS_IOS_SHOW_PASSWORD_VIEW_SITE)), - grey_kindOfClassName(@"UITextField"), nil); + ButtonWithAccessibilityLabel( + [NSString stringWithFormat:@"%@: %@", + l10n_util::GetNSString( + IDS_IOS_SHOW_PASSWORD_VIEW_SITE), + l10n_util::GetNSString( + IDS_IOS_SETTINGS_SITE_COPY_BUTTON)]), + grey_interactable(), nullptr); } // Matcher for the Copy username button in Password Details view. -id<GREYMatcher> PasswordDetailUsername() { - return grey_allOf(grey_accessibilityID( - GetTextFieldForID(IDS_IOS_SHOW_PASSWORD_VIEW_USERNAME)), - grey_kindOfClassName(@"UITextField"), nil); +id<GREYMatcher> CopyUsernameButton() { + return grey_allOf( + ButtonWithAccessibilityLabel([NSString + stringWithFormat:@"%@: %@", + l10n_util::GetNSString( + IDS_IOS_SHOW_PASSWORD_VIEW_USERNAME), + l10n_util::GetNSString( + IDS_IOS_SETTINGS_USERNAME_COPY_BUTTON)]), + grey_interactable(), nullptr); } // Matcher for the Copy password button in Password Details view. -id<GREYMatcher> PasswordDetailPassword() { - return grey_allOf(grey_accessibilityID( - GetTextFieldForID(IDS_IOS_SHOW_PASSWORD_VIEW_PASSWORD)), - grey_kindOfClassName(@"UITextField"), nil); +id<GREYMatcher> CopyPasswordButton() { + return grey_allOf( + ButtonWithAccessibilityLabel([NSString + stringWithFormat:@"%@: %@", + l10n_util::GetNSString( + IDS_IOS_SHOW_PASSWORD_VIEW_PASSWORD), + l10n_util::GetNSString( + IDS_IOS_SETTINGS_PASSWORD_COPY_BUTTON)]), + grey_interactable(), nullptr); } // Matcher for the Show password button in Password Details view. @@ -157,16 +202,8 @@ // Matcher for the Delete button in Password Details view. id<GREYMatcher> DeleteButton() { - return grey_allOf( - ButtonWithAccessibilityLabelId(IDS_IOS_SETTINGS_TOOLBAR_DELETE), - grey_not(grey_accessibilityTrait(UIAccessibilityTraitNotEnabled)), - nullptr); -} - -// Matcher for the Delete button in Confirmation Alert for password deletion. -id<GREYMatcher> DeleteConfirmationButton() { return grey_allOf(ButtonWithAccessibilityLabel(l10n_util::GetNSString( - IDS_IOS_CONFIRM_PASSWORD_DELETION)), + IDS_IOS_SETTINGS_PASSWORD_DELETE_BUTTON)), grey_interactable(), nullptr); } @@ -263,24 +300,10 @@ performAction:grey_tap()]; } -void CopyPasswordDetailWithID(int detail_id) { - [GetInteractionForPasswordDetailItem(grey_allOf( - grey_accessibilityID(GetTextFieldForID(detail_id)), - grey_kindOfClassName(@"UITextField"), nil)) performAction:grey_tap()]; - - // Tap the context menu item for copying. - [[EarlGrey selectElementWithMatcher:PopUpMenuItemWithLabel( - IDS_IOS_SETTINGS_SITE_COPY_MENU_ITEM)] - performAction:grey_tap()]; -} - } // namespace // Various tests for the Save Passwords section of the settings. -@interface PasswordsSettingsTestCase : ChromeTestCase { - base::test::ScopedFeatureList _featureList; -} - +@interface PasswordsSettingsTestCase : ChromeTestCase @end @implementation PasswordsSettingsTestCase @@ -296,18 +319,6 @@ [super tearDown]; } -- (AppLaunchConfiguration)appConfigurationForTestCase { - AppLaunchConfiguration config; - - // Password Check Feature is enabled for all tests. This is done because it - // is inefficient to use ensureAppLaunchedWithConfiguration for each test. - // This should be removed once test config is modified. - // TODO(crbug.com/1075494): Remove this once feature is launched. - config.features_enabled.push_back(password_manager::features::kPasswordCheck); - - return config; -} - // Verifies the UI elements are accessible on the Passwords page. - (void)testAccessibilityOnPasswords { // Saving a form is needed for using the "password details" view. @@ -345,12 +356,13 @@ [GetInteractionForPasswordEntry(@"example.com, concrete username") performAction:grey_tap()]; - // Check the snackbar in case of successful reauthentication. [PasswordSettingsAppInterface setUpMockReauthenticationModule]; [PasswordSettingsAppInterface mockReauthenticationModuleExpectedResult: ReauthenticationResult::kSuccess]; - CopyPasswordDetailWithID(IDS_IOS_SHOW_PASSWORD_VIEW_PASSWORD); + // Check the snackbar in case of successful reauthentication. + [GetInteractionForPasswordDetailItem(CopyPasswordButton()) + performAction:grey_tap()]; NSString* snackbarLabel = l10n_util::GetNSString(IDS_IOS_SETTINGS_PASSWORD_WAS_COPIED_MESSAGE); @@ -361,8 +373,8 @@ // Check the snackbar in case of failed reauthentication. [PasswordSettingsAppInterface mockReauthenticationModuleExpectedResult: ReauthenticationResult::kFailure]; - - CopyPasswordDetailWithID(IDS_IOS_SHOW_PASSWORD_VIEW_PASSWORD); + [GetInteractionForPasswordDetailItem(CopyPasswordButton()) + performAction:grey_tap()]; snackbarLabel = l10n_util::GetNSString(IDS_IOS_SETTINGS_PASSWORD_WAS_NOT_COPIED_MESSAGE); @@ -380,7 +392,7 @@ // Checks that an attempt to show a password provides an appropriate feedback // when reauthentication succeeds. -- (void)testShowPasswordAuthSucceeded { +- (void)testShowPasswordToastAuthSucceeded { // Saving a form is needed for using the "password details" view. SaveExamplePasswordForm(); @@ -393,12 +405,14 @@ [PasswordSettingsAppInterface mockReauthenticationModuleExpectedResult: ReauthenticationResult::kSuccess]; + // Check the snackbar in case of successful reauthentication. [GetInteractionForPasswordDetailItem(ShowPasswordButton()) performAction:grey_tap()]; - // Ensure that password is shown. - [GetInteractionForPasswordDetailItem(grey_textFieldValue( - @"concrete password")) assertWithMatcher:grey_notNil()]; + // Check that the password is displayed. + [[EarlGrey + selectElementWithMatcher:grey_accessibilityLabel(@"concrete password")] + assertWithMatcher:grey_sufficientlyVisible()]; [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] performAction:grey_tap()]; @@ -428,7 +442,8 @@ performAction:grey_tap()]; // Check that the password is not displayed. - [[EarlGrey selectElementWithMatcher:grey_textFieldValue(@"concrete password")] + [[EarlGrey + selectElementWithMatcher:grey_accessibilityLabel(@"concrete password")] assertWithMatcher:grey_nil()]; // Note that there is supposed to be no message (cf. the case of the copy @@ -453,7 +468,8 @@ [GetInteractionForPasswordEntry(@"example.com, concrete username") performAction:grey_tap()]; - CopyPasswordDetailWithID(IDS_IOS_SHOW_PASSWORD_VIEW_USERNAME); + [GetInteractionForPasswordDetailItem(CopyUsernameButton()) + performAction:grey_tap()]; NSString* snackbarLabel = l10n_util::GetNSString(IDS_IOS_SETTINGS_USERNAME_WAS_COPIED_MESSAGE); // The tap checks the existence of the snackbar and also closes it. @@ -478,8 +494,8 @@ [GetInteractionForPasswordEntry(@"example.com, concrete username") performAction:grey_tap()]; - CopyPasswordDetailWithID(IDS_IOS_SHOW_PASSWORD_VIEW_SITE); - + [GetInteractionForPasswordDetailItem(CopySiteButton()) + performAction:grey_tap()]; NSString* snackbarLabel = l10n_util::GetNSString(IDS_IOS_SETTINGS_SITE_WAS_COPIED_MESSAGE); // The tap checks the existence of the snackbar and also closes it. @@ -505,16 +521,11 @@ [GetInteractionForPasswordEntry(@"example.com, concrete username") performAction:grey_tap()]; - [PasswordSettingsAppInterface setUpMockReauthenticationModule]; - [PasswordSettingsAppInterface mockReauthenticationModuleExpectedResult: - ReauthenticationResult::kSuccess]; - - [[EarlGrey selectElementWithMatcher:NavigationBarEditButton()] + [GetInteractionForPasswordDetailItem(DeleteButton()) performAction:grey_tap()]; - [[EarlGrey selectElementWithMatcher:DeleteButton()] performAction:grey_tap()]; - - [[EarlGrey selectElementWithMatcher:DeleteConfirmationButton()] + [GetInteractionForPasswordDetailDeletionAlert(ButtonWithAccessibilityLabel( + l10n_util::GetNSString(IDS_IOS_CONFIRM_PASSWORD_DELETION))) performAction:grey_tap()]; // Wait until the alert and the detail view are dismissed. @@ -565,16 +576,11 @@ [GetInteractionForPasswordEntry(@"example.com, concrete username") performAction:grey_tap()]; - [PasswordSettingsAppInterface setUpMockReauthenticationModule]; - [PasswordSettingsAppInterface mockReauthenticationModuleExpectedResult: - ReauthenticationResult::kSuccess]; - - [[EarlGrey selectElementWithMatcher:NavigationBarEditButton()] + [GetInteractionForPasswordDetailItem(DeleteButton()) performAction:grey_tap()]; - [[EarlGrey selectElementWithMatcher:DeleteButton()] performAction:grey_tap()]; - - [[EarlGrey selectElementWithMatcher:DeleteConfirmationButton()] + [GetInteractionForPasswordDetailDeletionAlert(ButtonWithAccessibilityLabel( + l10n_util::GetNSString(IDS_IOS_CONFIRM_PASSWORD_DELETION))) performAction:grey_tap()]; // Wait until the alert and the detail view are dismissed. @@ -617,12 +623,11 @@ [GetInteractionForPasswordEntry(@"blocked.com") performAction:grey_tap()]; - [[EarlGrey selectElementWithMatcher:NavigationBarEditButton()] + [GetInteractionForPasswordDetailItem(DeleteButton()) performAction:grey_tap()]; - [[EarlGrey selectElementWithMatcher:DeleteButton()] performAction:grey_tap()]; - - [[EarlGrey selectElementWithMatcher:DeleteConfirmationButton()] + [GetInteractionForPasswordDetailDeletionAlert(ButtonWithAccessibilityLabel( + l10n_util::GetNSString(IDS_IOS_CONFIRM_PASSWORD_DELETION))) performAction:grey_tap()]; // Wait until the alert and the detail view are dismissed. @@ -666,17 +671,11 @@ [GetInteractionForPasswordEntry(@"example.com, concrete username") performAction:grey_tap()]; - [PasswordSettingsAppInterface setUpMockReauthenticationModule]; - [PasswordSettingsAppInterface mockReauthenticationModuleExpectedResult: - ReauthenticationResult::kSuccess]; - - [[EarlGrey selectElementWithMatcher:NavigationBarEditButton()] + [GetInteractionForPasswordDetailItem(DeleteButton()) performAction:grey_tap()]; - [[EarlGrey selectElementWithMatcher:DeleteButton()] performAction:grey_tap()]; - // Tap the alert's Cancel button to cancel. - if ([ChromeEarlGrey isIPadIdiom]) { + if (base::ios::IsRunningOnOrLater(13, 2, 0) && [ChromeEarlGrey isIPadIdiom]) { [[EarlGrey selectElementWithMatcher:grey_accessibilityID( kPasswordDetailsTableViewId)] performAction:grey_tap()]; @@ -690,10 +689,10 @@ performAction:grey_tap()]; } - // Check that the current view is still the detail view. - [[EarlGrey selectElementWithMatcher:grey_accessibilityID( - kPasswordDetailsTableViewId)] - assertWithMatcher:grey_notNil()]; + // Check that the current view is still the detail view, by locating the Copy + // button. + [[EarlGrey selectElementWithMatcher:CopyPasswordButton()] + assertWithMatcher:grey_sufficientlyVisible()]; // Verify that the deletion did not happen. GREYAssertEqual(1u, [PasswordSettingsAppInterface passwordStoreResultsCount], @@ -733,7 +732,7 @@ // Check that the current view is not the detail view, by failing to locate // the Copy button. - [[EarlGrey selectElementWithMatcher:PasswordDetailPassword()] + [[EarlGrey selectElementWithMatcher:CopyPasswordButton()] assertWithMatcher:grey_nil()]; [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] @@ -742,6 +741,77 @@ performAction:grey_tap()]; } +// Checks that attempts to copy the site via the context menu item provide an +// appropriate feedback. +- (void)testCopySiteMenuItem { + // Saving a form is needed for using the "password details" view. + SaveExamplePasswordForm(); + + OpenPasswordSettings(); + + [GetInteractionForPasswordEntry(@"example.com, concrete username") + performAction:grey_tap()]; + + // Tap the site cell to display the context menu. + [GetInteractionForPasswordDetailItem(grey_accessibilityLabel( + @"https://example.com/")) performAction:grey_tap()]; + + // Tap the context menu item for copying. + [[EarlGrey selectElementWithMatcher:PopUpMenuItemWithLabel( + IDS_IOS_SETTINGS_SITE_COPY_MENU_ITEM)] + performAction:grey_tap()]; + + // Check the snackbar. + NSString* snackbarLabel = + l10n_util::GetNSString(IDS_IOS_SETTINGS_SITE_WAS_COPIED_MESSAGE); + // The tap checks the existence of the snackbar and also closes it. + [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(snackbarLabel)] + performAction:grey_tap()]; + + [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] + performAction:grey_tap()]; + [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] + performAction:grey_tap()]; + [[EarlGrey selectElementWithMatcher:SettingsDoneButton()] + performAction:grey_tap()]; +} + +// Checks that attempts to copy the username via the context menu item provide +// an appropriate feedback. +- (void)testCopyUsernameMenuItem { + // Saving a form is needed for using the "password details" view. + SaveExamplePasswordForm(); + + OpenPasswordSettings(); + + [GetInteractionForPasswordEntry(@"example.com, concrete username") + performAction:grey_tap()]; + + // Tap the username cell to display the context menu. + [GetInteractionForPasswordDetailItem( + grey_accessibilityLabel(@"concrete username")) performAction:grey_tap()]; + + // Tap the context menu item for copying. + [[EarlGrey + selectElementWithMatcher:PopUpMenuItemWithLabel( + IDS_IOS_SETTINGS_USERNAME_COPY_MENU_ITEM)] + performAction:grey_tap()]; + + // Check the snackbar. + NSString* snackbarLabel = + l10n_util::GetNSString(IDS_IOS_SETTINGS_USERNAME_WAS_COPIED_MESSAGE); + // The tap checks the existence of the snackbar and also closes it. + [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(snackbarLabel)] + performAction:grey_tap()]; + + [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] + performAction:grey_tap()]; + [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] + performAction:grey_tap()]; + [[EarlGrey selectElementWithMatcher:SettingsDoneButton()] + performAction:grey_tap()]; +} + // Checks that attempts to copy the password via the context menu item provide // an appropriate feedback. - (void)testCopyPasswordMenuItem { @@ -790,6 +860,62 @@ performAction:grey_tap()]; } +// Checks that attempts to show and hide the password via the context menu item +// provide an appropriate feedback. +- (void)testShowHidePasswordMenuItem { + if (![ChromeEarlGrey isIPadIdiom]) { + // TODO(crbug.com/1109644): Enable the test on iPhone once the bug is fixed. + EARL_GREY_TEST_DISABLED(@"Disabled for iPhone."); + } + + // Saving a form is needed for using the "password details" view. + SaveExamplePasswordForm(); + + OpenPasswordSettings(); + + [GetInteractionForPasswordEntry(@"example.com, concrete username") + performAction:grey_tap()]; + + // Tap the password cell to display the context menu. + [GetInteractionForPasswordDetailItem(grey_text(kMaskedPassword)) + performAction:grey_tap()]; + + // Make sure to capture the reauthentication module in a variable until the + // end of the test, otherwise it might get deleted too soon and break the + // functionality of copying and viewing passwords. + [PasswordSettingsAppInterface setUpMockReauthenticationModule]; + [PasswordSettingsAppInterface mockReauthenticationModuleExpectedResult: + ReauthenticationResult::kSuccess]; + + // Tap the context menu item for showing. + [[EarlGrey + selectElementWithMatcher:PopUpMenuItemWithLabel( + IDS_IOS_SETTINGS_PASSWORD_SHOW_MENU_ITEM)] + performAction:grey_tap()]; + + // Tap the password cell to display the context menu again, and to check that + // the password was unmasked. + [GetInteractionForPasswordDetailItem( + grey_accessibilityLabel(@"concrete password")) performAction:grey_tap()]; + + // Tap the context menu item for hiding. + [[EarlGrey + selectElementWithMatcher:PopUpMenuItemWithLabel( + IDS_IOS_SETTINGS_PASSWORD_HIDE_MENU_ITEM)] + performAction:grey_tap()]; + + // Check that the password is masked again. + [GetInteractionForPasswordDetailItem(grey_text(kMaskedPassword)) + performAction:grey_tap()]; + + [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] + performAction:grey_tap()]; + [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] + performAction:grey_tap()]; + [[EarlGrey selectElementWithMatcher:SettingsDoneButton()] + performAction:grey_tap()]; +} + // Checks that federated credentials have no password but show the federation. - (void)testFederated { GREYAssert([PasswordSettingsAppInterface @@ -803,26 +929,24 @@ [GetInteractionForPasswordEntry(@"example.com, federated username") performAction:grey_tap()]; - // Check that the Site and Username are present and correct. - [[EarlGrey selectElementWithMatcher:PasswordDetailWebsite()] - assertWithMatcher:grey_textFieldValue(@"https://example.com/")]; - [[EarlGrey selectElementWithMatcher:PasswordDetailUsername()] - assertWithMatcher:grey_textFieldValue(@"federated username")]; + // Check that the Site, Username, Federation and Delete Saved Password + // sections are there. + [GetInteractionForPasswordDetailItem(SiteHeader()) + assertWithMatcher:grey_notNil()]; + [GetInteractionForPasswordDetailItem(UsernameHeader()) + assertWithMatcher:grey_notNil()]; + // For federation check both the section header and content. + [GetInteractionForPasswordDetailItem(FederationHeader()) + assertWithMatcher:grey_notNil()]; + [GetInteractionForPasswordDetailItem(grey_text(@"famous.provider.net")) + assertWithMatcher:grey_notNil()]; + [GetInteractionForPasswordDetailItem(DeleteButton()) + assertWithMatcher:grey_notNil()]; // Check that the password is not present. - [[EarlGrey selectElementWithMatcher:PasswordDetailPassword()] + [GetInteractionForPasswordDetailItem(PasswordHeader()) assertWithMatcher:grey_nil()]; - // Check that editing doesn't require reauth. - [PasswordSettingsAppInterface setUpMockReauthenticationModule]; - [PasswordSettingsAppInterface mockReauthenticationModuleExpectedResult: - ReauthenticationResult::kFailure]; - [[EarlGrey selectElementWithMatcher:NavigationBarEditButton()] - performAction:grey_tap()]; - // Ensure delete button is present after entering editing mode. - [[EarlGrey selectElementWithMatcher:DeleteButton()] - assertWithMatcher:grey_notNil()]; - [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] performAction:grey_tap()]; [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] @@ -841,17 +965,44 @@ [GetInteractionForPasswordEntry(@"example.com, concrete username") performAction:grey_tap()]; - [[EarlGrey selectElementWithMatcher:PasswordDetailWebsite()] - assertWithMatcher:grey_textFieldValue(@"https://example.com/")]; - [[EarlGrey selectElementWithMatcher:PasswordDetailUsername()] - assertWithMatcher:grey_textFieldValue(@"concrete username")]; - [[EarlGrey selectElementWithMatcher:PasswordDetailPassword()] - assertWithMatcher:grey_textFieldValue(kMaskedPassword)]; + [GetInteractionForPasswordDetailItem(SiteHeader()) + assertWithMatcher:grey_notNil()]; + id<GREYMatcher> siteCell = grey_accessibilityLabel(@"https://example.com/"); + [GetInteractionForPasswordDetailItem(siteCell) + assertWithMatcher:grey_layout(@[ Below() ], SiteHeader())]; + [GetInteractionForPasswordDetailItem(CopySiteButton()) + assertWithMatcher:grey_layout(@[ Below() ], siteCell)]; - [GetInteractionForPasswordDetailItem(PasswordDetailPassword()) - assertWithMatcher:grey_layout(@[ Below() ], PasswordDetailUsername())]; - [GetInteractionForPasswordDetailItem(PasswordDetailUsername()) - assertWithMatcher:grey_layout(@[ Below() ], PasswordDetailWebsite())]; + [GetInteractionForPasswordDetailItem(UsernameHeader()) + assertWithMatcher:grey_layout(@[ Below() ], CopySiteButton())]; + id<GREYMatcher> usernameCell = grey_accessibilityLabel(@"concrete username"); + [GetInteractionForPasswordDetailItem(usernameCell) + assertWithMatcher:grey_layout(@[ Below() ], UsernameHeader())]; + [GetInteractionForPasswordDetailItem(CopyUsernameButton()) + assertWithMatcher:grey_layout(@[ Below() ], usernameCell)]; + + id<GREYMatcher> passwordHeader = + grey_allOf(PasswordHeader(), + grey_kindOfClassName(@"UITableViewHeaderFooterView"), nil); + [GetInteractionForPasswordDetailItem(passwordHeader) + assertWithMatcher:grey_layout(@[ Below() ], CopyUsernameButton())]; + id<GREYMatcher> passwordCell = grey_accessibilityLabel( + l10n_util::GetNSString(IDS_IOS_SETTINGS_PASSWORD_HIDDEN_LABEL)); + [GetInteractionForPasswordDetailItem(passwordCell) + assertWithMatcher:grey_layout(@[ Below() ], passwordHeader)]; + [GetInteractionForPasswordDetailItem(CopyPasswordButton()) + assertWithMatcher:grey_layout(@[ Below() ], passwordCell)]; + [GetInteractionForPasswordDetailItem(ShowPasswordButton()) + assertWithMatcher:grey_layout(@[ Below() ], CopyPasswordButton())]; + + [GetInteractionForPasswordDetailItem(DeleteButton()) + assertWithMatcher:grey_layout(@[ Below() ], ShowPasswordButton())]; + + // Check that the federation block is not present. Match directly to also + // catch the case where the block would be present but not currently visible + // due to the scrolling state. + [[EarlGrey selectElementWithMatcher:FederationHeader()] + assertWithMatcher:grey_nil()]; [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] performAction:grey_tap()]; @@ -872,11 +1023,25 @@ [GetInteractionForPasswordEntry(@"example.com") performAction:grey_tap()]; - [[EarlGrey selectElementWithMatcher:PasswordDetailWebsite()] - assertWithMatcher:grey_textFieldValue(@"https://example.com/")]; - [[EarlGrey selectElementWithMatcher:PasswordDetailUsername()] + [GetInteractionForPasswordDetailItem(SiteHeader()) + assertWithMatcher:grey_notNil()]; + id<GREYMatcher> siteCell = grey_accessibilityLabel(@"https://example.com/"); + [GetInteractionForPasswordDetailItem(siteCell) + assertWithMatcher:grey_layout(@[ Below() ], SiteHeader())]; + [GetInteractionForPasswordDetailItem(CopySiteButton()) + assertWithMatcher:grey_layout(@[ Below() ], siteCell)]; + + [GetInteractionForPasswordDetailItem(DeleteButton()) + assertWithMatcher:grey_layout(@[ Below() ], CopySiteButton())]; + + // Check that the other blocks are not present. Match directly to also catch + // the case where those blocks would be present but not currently visible due + // to the scrolling state. + [[EarlGrey selectElementWithMatcher:UsernameHeader()] assertWithMatcher:grey_nil()]; - [[EarlGrey selectElementWithMatcher:PasswordDetailPassword()] + [[EarlGrey selectElementWithMatcher:PasswordHeader()] + assertWithMatcher:grey_nil()]; + [[EarlGrey selectElementWithMatcher:FederationHeader()] assertWithMatcher:grey_nil()]; [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] @@ -901,15 +1066,36 @@ [GetInteractionForPasswordEntry(@"example.com, federated username") performAction:grey_tap()]; - [[EarlGrey selectElementWithMatcher:PasswordDetailWebsite()] - assertWithMatcher:grey_textFieldValue(@"https://example.com/")]; - [[EarlGrey selectElementWithMatcher:PasswordDetailUsername()] - assertWithMatcher:grey_textFieldValue(@"federated username")]; - [[EarlGrey selectElementWithMatcher:PasswordDetailPassword()] - assertWithMatcher:grey_nil()]; + [GetInteractionForPasswordDetailItem(SiteHeader()) + assertWithMatcher:grey_notNil()]; + id<GREYMatcher> siteCell = grey_accessibilityLabel(@"https://example.com/"); + [GetInteractionForPasswordDetailItem(siteCell) + assertWithMatcher:grey_layout(@[ Below() ], SiteHeader())]; + [GetInteractionForPasswordDetailItem(CopySiteButton()) + assertWithMatcher:grey_layout(@[ Below() ], siteCell)]; - [GetInteractionForPasswordDetailItem(PasswordDetailUsername()) - assertWithMatcher:grey_layout(@[ Below() ], PasswordDetailWebsite())]; + [GetInteractionForPasswordDetailItem(UsernameHeader()) + assertWithMatcher:grey_layout(@[ Below() ], CopySiteButton())]; + id<GREYMatcher> usernameCell = grey_accessibilityLabel(@"federated username"); + [GetInteractionForPasswordDetailItem(usernameCell) + assertWithMatcher:grey_layout(@[ Below() ], UsernameHeader())]; + [GetInteractionForPasswordDetailItem(CopyUsernameButton()) + assertWithMatcher:grey_layout(@[ Below() ], usernameCell)]; + + [GetInteractionForPasswordDetailItem(FederationHeader()) + assertWithMatcher:grey_layout(@[ Below() ], CopyUsernameButton())]; + id<GREYMatcher> federationCell = grey_text(@"famous.provider.net"); + [GetInteractionForPasswordDetailItem(federationCell) + assertWithMatcher:grey_layout(@[ Below() ], FederationHeader())]; + + [GetInteractionForPasswordDetailItem(DeleteButton()) + assertWithMatcher:grey_layout(@[ Below() ], federationCell)]; + + // Check that the password is not present. Match directly to also catch the + // case where the password header would be present but not currently visible + // due to the scrolling state. + [[EarlGrey selectElementWithMatcher:PasswordHeader()] + assertWithMatcher:grey_nil()]; [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] performAction:grey_tap()]; @@ -924,13 +1110,15 @@ - (void)testStoredEntriesAlwaysShown { SaveExamplePasswordForm(); + GREYAssert([PasswordSettingsAppInterface + saveExampleBlockedOrigin:@"https://blocked.com"], + @"Stored form was not found in the PasswordStore results."); + OpenPasswordSettings(); // Toggle the "Save Passwords" control off and back on and check that stored // items are still present. - BOOL isSwitchEnabled = - [PasswordSettingsAppInterface isCredentialsServiceEnabled]; - BOOL kExpectedState[] = {isSwitchEnabled, !isSwitchEnabled}; + constexpr BOOL kExpectedState[] = {YES, NO}; for (BOOL expected_state : kExpectedState) { // Toggle the switch. It is located near the top, so if not interactable, // try scrolling up. @@ -948,6 +1136,8 @@ // Check the stored items. Scroll down if needed. [GetInteractionForPasswordEntry(@"example.com, concrete username") assertWithMatcher:grey_notNil()]; + [GetInteractionForPasswordEntry(@"blocked.com") + assertWithMatcher:grey_notNil()]; } [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] @@ -1024,7 +1214,8 @@ [PasswordSettingsAppInterface setUpMockReauthenticationModule]; [PasswordSettingsAppInterface mockReauthenticationModuleCanAttempt:NO]; - CopyPasswordDetailWithID(IDS_IOS_SHOW_PASSWORD_VIEW_PASSWORD); + [GetInteractionForPasswordDetailItem(CopyPasswordButton()) + performAction:grey_tap()]; NSString* title = l10n_util::GetNSString(IDS_IOS_SETTINGS_SET_UP_SCREENLOCK_TITLE); @@ -1032,10 +1223,6 @@ assertWithMatcher:grey_sufficientlyVisible()]; [[EarlGrey selectElementWithMatcher:chrome_test_util::OKButton()] performAction:grey_tap()]; - [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] - performAction:grey_tap()]; - [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] - performAction:grey_tap()]; [[EarlGrey selectElementWithMatcher:SettingsDoneButton()] performAction:grey_tap()]; } @@ -1116,12 +1303,12 @@ assertWithMatcher:grey_notNil()]; // Aim at an entry almost at the end of the list. - constexpr int kRemoteIndex = kPasswordsCount - 4; + constexpr int kRemoteIndex = kPasswordsCount - 2; // The scrolling in GetInteractionForPasswordEntry has too fine steps to // reach the desired part of the list quickly. The following gives it a head - // start of the desired position, counting 30 points per entry and - // aiming at |kRemoteIndex|. - constexpr int kJump = kRemoteIndex * 30 + 150; + // start of almost the desired position, counting 30 points per entry and + // aiming 3 entries before |kRemoteIndex|. + constexpr int kJump = (kRemoteIndex - 3) * 30; [[EarlGrey selectElementWithMatcher:grey_accessibilityID(kPasswordsTableViewId)] performAction:grey_scrollInDirection(kGREYDirectionDown, kJump)]; @@ -1130,10 +1317,10 @@ kRemoteIndex, kRemoteIndex]) performAction:grey_tap()]; // Check that the detail view loaded correctly by verifying the site content. - [[EarlGrey selectElementWithMatcher:PasswordDetailWebsite()] - assertWithMatcher:grey_textFieldValue([NSString - stringWithFormat:@"https://www%02d.example.com/", - kRemoteIndex])]; + id<GREYMatcher> siteCell = grey_accessibilityLabel([NSString + stringWithFormat:@"https://www%02d.example.com/", kRemoteIndex]); + [GetInteractionForPasswordDetailItem(siteCell) + assertWithMatcher:grey_notNil()]; [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] performAction:grey_tap()]; @@ -1282,17 +1469,15 @@ assertWithMatcher:grey_nil()]; [GetInteractionForPasswordEntry(@"exclude2.com") assertWithMatcher:grey_notNil()]; - [[EarlGrey - selectElementWithMatcher:ButtonWithAccessibilityLabelId(IDS_CANCEL)] - performAction:grey_tap()]; - [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()] - performAction:grey_tap()]; - [[EarlGrey selectElementWithMatcher:SettingsDoneButton()] - performAction:grey_tap()]; } // Test search and delete all passwords and blocked items. - (void)testSearchAndDeleteAllPasswords { + // TODO(crbug.com/1129441): This is failing regularly downstream on iOS14. + if (@available(iOS 14, *)) { + EARL_GREY_TEST_DISABLED(@"Test disabled on iOS14."); + } + SaveExamplePasswordForms(); SaveExampleBlockedForms(); @@ -1304,10 +1489,6 @@ // [[EarlGrey selectElementWithMatcher:SearchTextField()] // performAction:grey_typeText(@"u\n")]; - [[EarlGrey - selectElementWithMatcher:grey_accessibilityID(kPasswordsTableViewId)] - performAction:grey_scrollToContentEdge(kGREYContentEdgeBottom)]; - TapEdit(); // Select all. @@ -1315,7 +1496,6 @@ performAction:grey_tap()]; [GetInteractionForPasswordEntry(@"example12.com, user2") performAction:grey_tap()]; - [GetInteractionForPasswordEntry(@"exclude1.com") performAction:grey_tap()]; [GetInteractionForPasswordEntry(@"exclude2.com") performAction:grey_tap()];
diff --git a/ios/chrome/browser/web/content_mode_egtest.mm b/ios/chrome/browser/web/content_mode_egtest.mm index ce376d5c..d4215e2 100644 --- a/ios/chrome/browser/web/content_mode_egtest.mm +++ b/ios/chrome/browser/web/content_mode_egtest.mm
@@ -139,9 +139,10 @@ // Tests the platform when the page is inside an iframe. - (void)testIFrameNavigation { - // TODO(crbug.com/1076233): Test is failing when running on iOS 13.4. - if (base::ios::IsRunningOnOrLater(13, 4, 0)) { - EARL_GREY_TEST_SKIPPED(@"Test disabled on iOS 13.4 and later."); + // This test fails in iOS 13.4 but is fixed in iOS 14. See crbug.com//1076233. + if (base::ios::IsRunningOnOrLater(13, 4, 0) && + !base::ios::IsRunningOnIOS14OrLater()) { + EARL_GREY_TEST_SKIPPED(@"Test disabled on iOS 13.4 but enabled in iOS 14"); } [ChromeEarlGrey loadURL:self.testServer->GetURL(kIFramePage)];
diff --git a/ios/chrome/browser/web/navigation_egtest.mm b/ios/chrome/browser/web/navigation_egtest.mm index 48e294dc..e15c5e9 100644 --- a/ios/chrome/browser/web/navigation_egtest.mm +++ b/ios/chrome/browser/web/navigation_egtest.mm
@@ -589,9 +589,10 @@ // Tests that navigating forward from NTP works when resuming from session // restore. This is a regression test for https://crbug.com/814790. - (void)testRestoreHistoryToNTPAndNavigateForward { - // TODO(crbug.com/1076598): Test is failing when running on iOS 13.4. - if (base::ios::IsRunningOnOrLater(13, 4, 0)) { - EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 13.4 and later."); + // This test fails in iOS 13.4 but is fixed in iOS 14. See crbug.com/1076598. + if (base::ios::IsRunningOnOrLater(13, 4, 0) && + !base::ios::IsRunningOnIOS14OrLater()) { + EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 13.4 but enabled in iOS 14"); } #if TARGET_IPHONE_SIMULATOR
diff --git a/ios/chrome/test/app/BUILD.gn b/ios/chrome/test/app/BUILD.gn index 7cac1279..eb3edd97 100644 --- a/ios/chrome/test/app/BUILD.gn +++ b/ios/chrome/test/app/BUILD.gn
@@ -43,7 +43,6 @@ "//components/keyed_service/core", "//components/metrics", "//components/metrics:demographics_test_support", - "//components/password_manager/core/common", "//components/prefs", "//components/signin/public/base", "//components/sync:test_support_nigori", @@ -71,7 +70,6 @@ "//ios/chrome/browser/signin", "//ios/chrome/browser/sync", "//ios/chrome/browser/tabs", - "//ios/chrome/browser/ui:feature_flags", "//ios/chrome/browser/ui/authentication/cells", "//ios/chrome/browser/ui/browser_view", "//ios/chrome/browser/ui/commands", @@ -83,7 +81,6 @@ "//ios/chrome/browser/ui/settings/password", "//ios/chrome/browser/ui/settings/password:password_ui", "//ios/chrome/browser/ui/settings/password:test_support", - "//ios/chrome/browser/ui/settings/password/password_details:password_details_ui", "//ios/chrome/browser/ui/tab_grid", "//ios/chrome/browser/ui/tabs", "//ios/chrome/browser/ui/util",
diff --git a/ios/chrome/test/app/password_test_util.mm b/ios/chrome/test/app/password_test_util.mm index cbf55d0e..56b6cfe9 100644 --- a/ios/chrome/test/app/password_test_util.mm +++ b/ios/chrome/test/app/password_test_util.mm
@@ -6,10 +6,8 @@ #include "base/mac/foundation_util.h" #import "ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller+testing.h" -#import "ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller.h" #import "ios/chrome/browser/ui/settings/password/passwords_table_view_controller.h" #import "ios/chrome/browser/ui/settings/settings_navigation_controller.h" -#include "ios/chrome/browser/ui/ui_feature_flags.h" #import "ios/chrome/browser/ui/util/top_view_controller.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -55,11 +53,12 @@ SettingsNavigationController* settings_navigation_controller = base::mac::ObjCCastStrict<SettingsNavigationController>( top_view_controller::TopPresentedViewController()); - PasswordDetailsTableViewController* password_details_table_view_controller = - base::mac::ObjCCastStrict<PasswordDetailsTableViewController>( - settings_navigation_controller.topViewController); - password_details_table_view_controller.reauthModule = - mock_reauthentication_module; + LegacyPasswordDetailsTableViewController* + password_details_table_view_controller = + base::mac::ObjCCastStrict<LegacyPasswordDetailsTableViewController>( + settings_navigation_controller.topViewController); + [password_details_table_view_controller + setReauthenticationModule:mock_reauthentication_module]; return mock_reauthentication_module; }
diff --git a/ios/web/web_state/web_state_observer_inttest.mm b/ios/web/web_state/web_state_observer_inttest.mm index b1f3f49..cb6218b 100644 --- a/ios/web/web_state/web_state_observer_inttest.mm +++ b/ios/web/web_state/web_state_observer_inttest.mm
@@ -2323,8 +2323,9 @@ // Tests that iframe navigation triggers DidChangeBackForwardState. TEST_F(WebStateObserverTest, IframeNavigation) { - // TODO(crbug.com/1076233): Test is failing when running on iOS 13.4. - if (base::ios::IsRunningOnOrLater(13, 4, 0)) { + // This test fails in iOS 13.4 but is fixed in iOS 14. See crbug.com//1076233. + if (base::ios::IsRunningOnOrLater(13, 4, 0) && + !base::ios::IsRunningOnIOS14OrLater()) { return; }
diff --git a/mojo/public/tools/bindings/generators/mojom_java_generator.py b/mojo/public/tools/bindings/generators/mojom_java_generator.py index 96b2fdf..c51824a 100644 --- a/mojo/public/tools/bindings/generators/mojom_java_generator.py +++ b/mojo/public/tools/bindings/generators/mojom_java_generator.py
@@ -20,9 +20,12 @@ import mojom.generate.module as mojom from mojom.generate.template_expander import UseJinja -sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir, - os.pardir, os.pardir, os.pardir, os.pardir, - 'build', 'android', 'gyp')) +# Item 0 of sys.path is the directory of the main file; item 1 is PYTHONPATH +# (if set); item 2 is system libraries. +sys.path.insert( + 1, + os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, os.pardir, + os.pardir, os.pardir, 'build', 'android', 'gyp')) from util import build_utils
diff --git a/ppapi/proxy/ppb_instance_proxy.cc b/ppapi/proxy/ppb_instance_proxy.cc index f47f551f..bddc6974 100644 --- a/ppapi/proxy/ppb_instance_proxy.cc +++ b/ppapi/proxy/ppb_instance_proxy.cc
@@ -227,13 +227,6 @@ return &data->view; } -PP_Bool PPB_Instance_Proxy::FlashIsFullscreen(PP_Instance instance) { - // This function is only used for proxying in the renderer process. It is not - // implemented in the plugin process. - NOTREACHED(); - return PP_FALSE; -} - PP_Var PPB_Instance_Proxy::GetWindowObject(PP_Instance instance) { ReceiveSerializedVarReturnValue result; dispatcher()->Send(new PpapiHostMsg_PPBInstance_GetWindowObject(
diff --git a/ppapi/proxy/ppb_instance_proxy.h b/ppapi/proxy/ppb_instance_proxy.h index 7bea4ee..a84b4872 100644 --- a/ppapi/proxy/ppb_instance_proxy.h +++ b/ppapi/proxy/ppb_instance_proxy.h
@@ -47,7 +47,6 @@ PP_Bool BindGraphics(PP_Instance instance, PP_Resource device) override; PP_Bool IsFullFrame(PP_Instance instance) override; const ViewData* GetViewData(PP_Instance instance) override; - PP_Bool FlashIsFullscreen(PP_Instance instance) override; PP_Var GetWindowObject(PP_Instance instance) override; PP_Var GetOwnerElementObject(PP_Instance instance) override; PP_Var ExecuteScript(PP_Instance instance,
diff --git a/ppapi/proxy/ppp_instance_proxy.cc b/ppapi/proxy/ppp_instance_proxy.cc index afe0a720..6809295 100644 --- a/ppapi/proxy/ppp_instance_proxy.cc +++ b/ppapi/proxy/ppp_instance_proxy.cc
@@ -77,8 +77,6 @@ PP_Bool flash_fullscreen = PP_FALSE; EnterInstanceNoLock enter_instance(instance); - if (!enter_instance.failed()) - flash_fullscreen = enter_instance.functions()->FlashIsFullscreen(instance); dispatcher->Send(new PpapiMsg_PPPInstance_DidChangeView( API_ID_PPP_INSTANCE, instance, enter_view.object()->GetData(), flash_fullscreen));
diff --git a/ppapi/thunk/ppb_instance_api.h b/ppapi/thunk/ppb_instance_api.h index 390e2ce7..520cb3c 100644 --- a/ppapi/thunk/ppb_instance_api.h +++ b/ppapi/thunk/ppb_instance_api.h
@@ -50,8 +50,6 @@ // Unexposed PPAPI functions for proxying. // Returns the internal view data struct. virtual const ViewData* GetViewData(PP_Instance instance) = 0; - // Returns the flash fullscreen status. - virtual PP_Bool FlashIsFullscreen(PP_Instance instance) = 0; // InstancePrivate. virtual PP_Var GetWindowObject(PP_Instance instance) = 0;
diff --git a/remoting/host/BUILD.gn b/remoting/host/BUILD.gn index 4b9aed5..9416676 100644 --- a/remoting/host/BUILD.gn +++ b/remoting/host/BUILD.gn
@@ -323,6 +323,7 @@ ] deps += [ "//remoting/host/linux:x11", + "//ui/events/platform/x11", "//ui/gfx/x", ] if (is_linux) {
diff --git a/remoting/host/it2me/it2me_native_messaging_host_main.cc b/remoting/host/it2me/it2me_native_messaging_host_main.cc index f429809..545a57d0 100644 --- a/remoting/host/it2me/it2me_native_messaging_host_main.cc +++ b/remoting/host/it2me/it2me_native_messaging_host_main.cc
@@ -33,6 +33,7 @@ #include <gtk/gtk.h> #include "base/linux_util.h" +#include "ui/events/platform/x11/x11_event_source.h" #include "ui/gfx/x/x11.h" #endif // defined(OS_LINUX) || defined(OS_CHROMEOS) @@ -116,6 +117,11 @@ // Required in order for us to run multiple X11 threads. XInitThreads(); + // Create an X11EventSource so the global X11 connection + // (x11::Connection::Get()) can dispatch X events. + auto event_source = + std::make_unique<ui::X11EventSource>(x11::Connection::Get()); + // Required for any calls into GTK functions, such as the Disconnect and // Continue windows. Calling with nullptr arguments because we don't have // any command line arguments for gtk to consume.
diff --git a/remoting/host/keyboard_layout_monitor_linux.cc b/remoting/host/keyboard_layout_monitor_linux.cc index 22d6866..a897dba4 100644 --- a/remoting/host/keyboard_layout_monitor_linux.cc +++ b/remoting/host/keyboard_layout_monitor_linux.cc
@@ -18,6 +18,7 @@ #include "ui/base/glib/glib_signal.h" #include "ui/events/keycodes/dom/dom_code.h" #include "ui/events/keycodes/dom/keycode_converter.h" +#include "ui/events/platform/x11/x11_event_source.h" #include "ui/gfx/x/x11.h" #include "ui/gfx/x/xkb.h" #include "ui/gfx/x/xproto.h" @@ -42,7 +43,7 @@ // Can be constructed on any thread, but must be started and destroyed on the // main GTK+ thread (i.e., the GLib global default main context). -class GdkLayoutMonitorOnGtkThread : public x11::Connection::Delegate { +class GdkLayoutMonitorOnGtkThread : public ui::XEventDispatcher { public: GdkLayoutMonitorOnGtkThread( scoped_refptr<base::SequencedTaskRunner> task_runner, @@ -53,19 +54,17 @@ void Start(); private: - // x11::Connection::Delegate: - bool ShouldContinueStream() const override; - void DispatchXEvent(x11::Event* event) override; + // ui::XEventDispatcher: + bool DispatchXEvent(x11::Event* event) override; void QueryLayout(); - void OnConnectionData(); CHROMEG_CALLBACK_0(GdkLayoutMonitorOnGtkThread, void, OnKeysChanged, GdkKeymap*); scoped_refptr<base::SequencedTaskRunner> task_runner_; base::WeakPtr<KeyboardLayoutMonitorLinux> weak_ptr_; - std::unique_ptr<x11::Connection> connection_; + x11::Connection* connection_; std::unique_ptr<base::FileDescriptorWatcher::Controller> controller_; GdkDisplay* display_ = nullptr; GdkKeymap* keymap_ = nullptr; @@ -120,8 +119,10 @@ GdkLayoutMonitorOnGtkThread::~GdkLayoutMonitorOnGtkThread() { DCHECK(g_main_context_is_owner(g_main_context_default())); - if (handler_id_) + if (handler_id_) { g_signal_handler_disconnect(keymap_, handler_id_); + ui::X11EventSource::GetInstance()->RemoveXEventDispatcher(this); + } } void GdkLayoutMonitorOnGtkThread::Start() { @@ -143,30 +144,22 @@ // when switching between groups with different writing directions. As a // result, we have to use Xkb directly to get and monitor that information, // which is a pain. - connection_ = std::make_unique<x11::Connection>(); + connection_ = x11::Connection::Get(); auto& xkb = connection_->xkb(); if (xkb.UseExtension({x11::Xkb::major_version, x11::Xkb::minor_version}) .Sync()) { - auto req = xkb.GetState( - {static_cast<x11::Xkb::DeviceSpec>(x11::Xkb::Id::UseCoreKbd)}); - if (auto reply = req.Sync()) { - current_group_ = static_cast<int>(reply->group); - constexpr auto kXkbAllStateComponentsMask = - static_cast<x11::Xkb::StatePart>(0x3fff); - xkb.SelectEvents({ - .deviceSpec = - static_cast<x11::Xkb::DeviceSpec>(x11::Xkb::Id::UseCoreKbd), - .affectWhich = x11::Xkb::EventType::StateNotify, - .affectState = kXkbAllStateComponentsMask, - .stateDetails = x11::Xkb::StatePart::GroupState, - }); - connection_->Flush(); - controller_ = base::FileDescriptorWatcher::WatchReadable( - connection_->GetFd(), - base::BindRepeating(&GdkLayoutMonitorOnGtkThread::OnConnectionData, - base::Unretained(this))); - } + constexpr auto kXkbAllStateComponentsMask = + static_cast<x11::Xkb::StatePart>(0x3fff); + xkb.SelectEvents({ + .deviceSpec = + static_cast<x11::Xkb::DeviceSpec>(x11::Xkb::Id::UseCoreKbd), + .affectWhich = x11::Xkb::EventType::StateNotify, + .affectState = kXkbAllStateComponentsMask, + .stateDetails = x11::Xkb::StatePart::GroupState, + }); + connection_->Flush(); } + ui::X11EventSource::GetInstance()->AddXEventDispatcher(this); keymap_ = gdk_keymap_get_for_display(display_); handler_id_ = g_signal_connect(keymap_, "keys-changed", @@ -174,19 +167,18 @@ QueryLayout(); } -bool GdkLayoutMonitorOnGtkThread::ShouldContinueStream() const { - return true; -} - -void GdkLayoutMonitorOnGtkThread::DispatchXEvent(x11::Event* event) { - if (auto* notify = event->As<x11::Xkb::StateNotifyEvent>()) { +bool GdkLayoutMonitorOnGtkThread::DispatchXEvent(x11::Event* event) { + if (event->As<x11::MappingNotifyEvent>() || + event->As<x11::Xkb::NewKeyboardNotifyEvent>()) { + QueryLayout(); + } else if (auto* notify = event->As<x11::Xkb::StateNotifyEvent>()) { int new_group = notify->baseGroup + notify->latchedGroup + static_cast<int16_t>(notify->lockedGroup); - if (new_group != current_group_) { - current_group_ = new_group; + if (new_group != current_group_) QueryLayout(); - } + return true; } + return false; } void GdkLayoutMonitorOnGtkThread::QueryLayout() { @@ -198,6 +190,11 @@ bool have_altgr = false; + auto req = connection_->xkb().GetState( + {static_cast<x11::Xkb::DeviceSpec>(x11::Xkb::Id::UseCoreKbd)}); + if (auto reply = req.Sync()) + current_group_ = static_cast<int>(reply->group); + for (ui::DomCode key : KeyboardLayoutMonitorLinux::kSupportedKeys) { // Skip single-layout IME keys for now, as they are always present in the // keyboard map but not present on most keyboards. Client-side IME is likely @@ -298,10 +295,6 @@ weak_ptr_, std::move(layout_message))); } -void GdkLayoutMonitorOnGtkThread::OnConnectionData() { - connection_->Dispatch(this); -} - void GdkLayoutMonitorOnGtkThread::OnKeysChanged(GdkKeymap* keymap) { QueryLayout(); }
diff --git a/remoting/host/remoting_me2me_host.cc b/remoting/host/remoting_me2me_host.cc index 0436254..aa8ed13 100644 --- a/remoting/host/remoting_me2me_host.cc +++ b/remoting/host/remoting_me2me_host.cc
@@ -120,9 +120,11 @@ #if defined(OS_LINUX) || defined(OS_CHROMEOS) #include <gtk/gtk.h> + #include "base/linux_util.h" #include "remoting/host/audio_capturer_linux.h" #include "remoting/host/linux/certificate_watcher.h" +#include "ui/events/platform/x11/x11_event_source.h" #include "ui/gfx/x/x11.h" #endif // defined(OS_LINUX) || defined(OS_CHROMEOS) @@ -1686,11 +1688,16 @@ HOST_LOG << "Starting host process: version " << STRINGIZE(VERSION); #if defined(OS_LINUX) || defined(OS_CHROMEOS) + std::unique_ptr<ui::X11EventSource> event_source; if (!base::CommandLine::ForCurrentProcess()->HasSwitch( kReportOfflineReasonSwitchName)) { // Required in order for us to run multiple X11 threads. XInitThreads(); + // Create an X11EventSource so the global X11 connection + // (x11::Connection::Get()) can dispatch X events. + event_source = std::make_unique<ui::X11EventSource>(x11::Connection::Get()); + // Required for any calls into GTK functions, such as the Disconnect and // Continue windows, though these should not be used for the Me2Me case // (crbug.com/104377).
diff --git a/remoting/test/DEPS b/remoting/test/DEPS index 8f93383..9c9e8445 100644 --- a/remoting/test/DEPS +++ b/remoting/test/DEPS
@@ -11,6 +11,7 @@ "+remoting/signaling", "+ui/gfx", "+ui/events/keycodes/dom", + "+ui/events/platform/x11", "+services/network", "+third_party/skia", ]
diff --git a/remoting/test/it2me_standalone_host_main.cc b/remoting/test/it2me_standalone_host_main.cc index d45013c0..e8c73f0 100644 --- a/remoting/test/it2me_standalone_host_main.cc +++ b/remoting/test/it2me_standalone_host_main.cc
@@ -13,6 +13,7 @@ #include <gtk/gtk.h> #include "base/linux_util.h" +#include "ui/events/platform/x11/x11_event_source.h" #include "ui/gfx/x/x11.h" #endif // defined(OS_LINUX) || defined(OS_CHROMEOS) @@ -25,6 +26,11 @@ // Required in order for us to run multiple X11 threads. XInitThreads(); + // Create an X11EventSource so the global X11 connection + // (x11::Connection::Get()) can dispatch X events. + auto event_source = + std::make_unique<ui::X11EventSource>(x11::Connection::Get()); + // Required for any calls into GTK functions, such as the Disconnect and // Continue windows. Calling with nullptr arguments because we don't have // any command line arguments for gtk to consume.
diff --git a/sandbox/policy/mac/gpu_v2.sb b/sandbox/policy/mac/gpu_v2.sb index 948e2900..f7e7559 100644 --- a/sandbox/policy/mac/gpu_v2.sb +++ b/sandbox/policy/mac/gpu_v2.sb
@@ -35,6 +35,7 @@ (path (param "PARENT_DIR")) (path (param "PWD")) (path-ancestors (param "PARENT_DIR")) ; libxpc.dylib`_xpc_bundle_resolve_sync walks the dir tree. + (subpath "/Library/Apple") (subpath "/Library/Application Support/CrashReporter") (subpath "/usr/share/locale") )
diff --git a/services/tracing/public/cpp/perfetto/trace_event_data_source.cc b/services/tracing/public/cpp/perfetto/trace_event_data_source.cc index cdb82f7..c10f7b2b 100644 --- a/services/tracing/public/cpp/perfetto/trace_event_data_source.cc +++ b/services/tracing/public/cpp/perfetto/trace_event_data_source.cc
@@ -49,6 +49,7 @@ #include "third_party/perfetto/include/perfetto/ext/tracing/core/shared_memory_arbiter.h" #include "third_party/perfetto/include/perfetto/ext/tracing/core/trace_writer.h" #include "third_party/perfetto/include/perfetto/tracing/track.h" +#include "third_party/perfetto/include/perfetto/tracing/track_event_interned_data_index.h" #include "third_party/perfetto/protos/perfetto/trace/chrome/chrome_metadata.pbzero.h" #include "third_party/perfetto/protos/perfetto/trace/chrome/chrome_trace_event.pbzero.h" #include "third_party/perfetto/protos/perfetto/trace/trace_packet.pbzero.h" @@ -1041,6 +1042,24 @@ } } +namespace { + +struct InternedHistogramName + : public perfetto::TrackEventInternedDataIndex< + InternedHistogramName, + perfetto::protos::pbzero::InternedData::kHistogramNamesFieldNumber, + std::string> { + static void Add(perfetto::protos::pbzero::InternedData* interned_data, + size_t iid, + const std::string& histogram_name) { + auto* msg = interned_data->add_histogram_names(); + msg->set_iid(iid); + msg->set_name(histogram_name); + } +}; + +} // namespace + // static void TraceEventDataSource::OnMetricsSampleCallback( const char* histogram_name, @@ -1056,7 +1075,8 @@ new_sample->set_name_hash(name_hash); new_sample->set_sample(sample); if (!privacy_filtering_enabled) { - new_sample->set_name(histogram_name); + size_t iid = InternedHistogramName::Get(&ctx, histogram_name); + new_sample->set_name_iid(iid); } }); }
diff --git a/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc b/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc index d7e1f8e6..7ca1c5a 100644 --- a/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc +++ b/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc
@@ -1917,9 +1917,11 @@ {{1u, TRACE_DISABLED_BY_DEFAULT("histogram_samples")}}); ExpectEventNames(e_packet, {{1u, "HistogramSample"}}); ASSERT_TRUE(e_packet->track_event().has_chrome_histogram_sample()); - EXPECT_EQ(e_packet->track_event().chrome_histogram_sample().name_hash(), - base::HashMetricName("Foo.Bar")); EXPECT_EQ(e_packet->track_event().chrome_histogram_sample().sample(), 1u); + ASSERT_TRUE(e_packet->has_interned_data()); + EXPECT_EQ(e_packet->track_event().chrome_histogram_sample().name_iid(), + e_packet->interned_data().histogram_names()[0].iid()); + EXPECT_EQ(e_packet->interned_data().histogram_names()[0].name(), "Foo.Bar"); } TEST_F(TraceEventDataSourceTest, HistogramSampleTraceConfigNotEmpty) { @@ -1946,9 +1948,11 @@ ASSERT_TRUE(e_packet->track_event().has_chrome_histogram_sample()); EXPECT_EQ(e_packet->track_event().chrome_histogram_sample().name_hash(), base::HashMetricName("Foo1.Bar1")); - EXPECT_EQ(e_packet->track_event().chrome_histogram_sample().name(), - "Foo1.Bar1"); EXPECT_EQ(e_packet->track_event().chrome_histogram_sample().sample(), 1u); + ASSERT_TRUE(e_packet->has_interned_data()); + EXPECT_EQ(e_packet->track_event().chrome_histogram_sample().name_iid(), + e_packet->interned_data().histogram_names()[0].iid()); + EXPECT_EQ(e_packet->interned_data().histogram_names()[0].name(), "Foo1.Bar1"); e_packet = producer_client()->GetFinalizedPacket(packet_index++); @@ -1957,9 +1961,11 @@ ASSERT_TRUE(e_packet->track_event().has_chrome_histogram_sample()); EXPECT_EQ(e_packet->track_event().chrome_histogram_sample().name_hash(), base::HashMetricName("Foo3.Bar3")); - EXPECT_EQ(e_packet->track_event().chrome_histogram_sample().name(), - "Foo3.Bar3"); EXPECT_EQ(e_packet->track_event().chrome_histogram_sample().sample(), 1u); + ASSERT_TRUE(e_packet->has_interned_data()); + EXPECT_EQ(e_packet->track_event().chrome_histogram_sample().name_iid(), + e_packet->interned_data().histogram_names()[0].iid()); + EXPECT_EQ(e_packet->interned_data().histogram_names()[0].name(), "Foo3.Bar3"); EXPECT_EQ(packet_index, producer_client()->GetFinalizedPacketCount()); }
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json index 67dc60c..73f788c 100644 --- a/testing/buildbot/chromium.clang.json +++ b/testing/buildbot/chromium.clang.json
@@ -23998,6 +23998,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -26431,6 +26434,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true,
diff --git a/testing/buildbot/chromium.dawn.json b/testing/buildbot/chromium.dawn.json index aa6e8bc..552f08a3 100644 --- a/testing/buildbot/chromium.dawn.json +++ b/testing/buildbot/chromium.dawn.json
@@ -234,6 +234,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webgpu_blink_web_tests", + "resultdb": { + "enable": true + }, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -265,6 +268,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webgpu_blink_web_tests_with_backend_validation", + "resultdb": { + "enable": true + }, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -511,6 +517,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webgpu_blink_web_tests", + "resultdb": { + "enable": true + }, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -542,6 +551,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webgpu_blink_web_tests_with_backend_validation", + "resultdb": { + "enable": true + }, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -788,6 +800,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webgpu_blink_web_tests", + "resultdb": { + "enable": true + }, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -819,6 +834,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webgpu_blink_web_tests_with_backend_validation", + "resultdb": { + "enable": true + }, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -1065,6 +1083,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webgpu_blink_web_tests", + "resultdb": { + "enable": true + }, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -1096,6 +1117,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webgpu_blink_web_tests_with_backend_validation", + "resultdb": { + "enable": true + }, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -1343,6 +1367,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webgpu_blink_web_tests", + "resultdb": { + "enable": true + }, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -1374,6 +1401,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webgpu_blink_web_tests_with_backend_validation", + "resultdb": { + "enable": true + }, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -1604,6 +1634,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webgpu_blink_web_tests", + "resultdb": { + "enable": true + }, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -1633,6 +1666,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webgpu_blink_web_tests_with_backend_validation", + "resultdb": { + "enable": true + }, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -1877,6 +1913,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webgpu_blink_web_tests", + "resultdb": { + "enable": true + }, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -1908,6 +1947,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webgpu_blink_web_tests_with_backend_validation", + "resultdb": { + "enable": true + }, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -2138,6 +2180,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webgpu_blink_web_tests", + "resultdb": { + "enable": true + }, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -2167,6 +2212,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webgpu_blink_web_tests_with_backend_validation", + "resultdb": { + "enable": true + }, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -2413,6 +2461,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webgpu_blink_web_tests", + "resultdb": { + "enable": true + }, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -2658,6 +2709,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webgpu_blink_web_tests", + "resultdb": { + "enable": true + }, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -2688,6 +2742,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webgpu_blink_web_tests_with_backend_validation", + "resultdb": { + "enable": true + }, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -2926,6 +2983,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webgpu_blink_web_tests", + "resultdb": { + "enable": true + }, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -2956,6 +3016,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webgpu_blink_web_tests_with_backend_validation", + "resultdb": { + "enable": true + }, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -3194,6 +3257,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webgpu_blink_web_tests", + "resultdb": { + "enable": true + }, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -3224,6 +3290,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webgpu_blink_web_tests_with_backend_validation", + "resultdb": { + "enable": true + }, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -3462,6 +3531,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webgpu_blink_web_tests", + "resultdb": { + "enable": true + }, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -3492,6 +3564,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webgpu_blink_web_tests_with_backend_validation", + "resultdb": { + "enable": true + }, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -3731,6 +3806,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webgpu_blink_web_tests", + "resultdb": { + "enable": true + }, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -3760,6 +3838,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webgpu_blink_web_tests_with_backend_validation", + "resultdb": { + "enable": true + }, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -3997,6 +4078,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webgpu_blink_web_tests", + "resultdb": { + "enable": true + }, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -4026,6 +4110,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webgpu_blink_web_tests_with_backend_validation", + "resultdb": { + "enable": true + }, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -4263,6 +4350,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webgpu_blink_web_tests", + "resultdb": { + "enable": true + }, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -4292,6 +4382,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webgpu_blink_web_tests_with_backend_validation", + "resultdb": { + "enable": true + }, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -4529,6 +4622,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webgpu_blink_web_tests", + "resultdb": { + "enable": true + }, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -4558,6 +4654,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webgpu_blink_web_tests_with_backend_validation", + "resultdb": { + "enable": true + }, "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [
diff --git a/testing/buildbot/chromium.devtools-frontend.json b/testing/buildbot/chromium.devtools-frontend.json index 92a4447..062b03e 100644 --- a/testing/buildbot/chromium.devtools-frontend.json +++ b/testing/buildbot/chromium.devtools-frontend.json
@@ -41,6 +41,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -68,6 +71,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webkit_layout_from_devtools", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true,
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index afaed73f..0125212 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -99,6 +99,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "non_skia_renderer_swiftshader_blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -134,6 +137,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "vulkan_swiftshader_blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -1567,6 +1573,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -2123,6 +2132,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -2181,6 +2193,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -5150,6 +5165,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -7367,6 +7385,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -18836,6 +18857,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -37053,6 +37077,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -38690,6 +38717,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -38722,6 +38752,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "high_dpi_blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -38751,6 +38784,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -42181,6 +42217,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -42357,6 +42396,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "non_skia_renderer_swiftshader_blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -42384,6 +42426,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "not_site_per_process_blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -42511,6 +42556,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "vulkan_swiftshader_blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -44286,6 +44334,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -44471,6 +44522,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "non_skia_renderer_swiftshader_blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -44500,6 +44554,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "not_site_per_process_blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -44630,6 +44687,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "vulkan_swiftshader_blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -49543,6 +49603,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -52967,6 +53030,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -53384,6 +53450,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -53437,6 +53506,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -53490,6 +53562,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -53542,6 +53617,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -53595,6 +53673,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -53691,6 +53772,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -55070,6 +55154,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true,
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json index 924c230..a4d4bd3b 100644 --- a/testing/buildbot/chromium.gpu.fyi.json +++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -14131,6 +14131,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "skia_renderer_gl_blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -14214,6 +14217,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "vulkan_native_blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -14559,6 +14565,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "skia_renderer_gl_blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -14642,6 +14651,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "vulkan_native_blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true,
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json index 894598d..c17cf11a 100644 --- a/testing/buildbot/chromium.linux.json +++ b/testing/buildbot/chromium.linux.json
@@ -4097,6 +4097,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -6838,6 +6841,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -7023,6 +7029,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "non_skia_renderer_swiftshader_blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -7052,6 +7061,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "not_site_per_process_blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -7184,6 +7196,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "vulkan_swiftshader_blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -8869,6 +8884,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -9278,6 +9296,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -10943,6 +10964,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -11119,6 +11143,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "non_skia_renderer_swiftshader_blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -11146,6 +11173,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "not_site_per_process_blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -11273,6 +11303,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "vulkan_swiftshader_blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true,
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json index f81a851..fbd4dba2 100644 --- a/testing/buildbot/chromium.mac.json +++ b/testing/buildbot/chromium.mac.json
@@ -4906,6 +4906,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -6679,6 +6682,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -8464,6 +8470,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -10198,6 +10207,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -11979,6 +11991,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -13690,6 +13705,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true,
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json index b732d44d..18ba2c5 100644 --- a/testing/buildbot/chromium.memory.json +++ b/testing/buildbot/chromium.memory.json
@@ -15099,6 +15099,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -15136,6 +15139,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -15170,6 +15176,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true,
diff --git a/testing/buildbot/chromium.win.json b/testing/buildbot/chromium.win.json index 25588ec..d3798b8 100644 --- a/testing/buildbot/chromium.win.json +++ b/testing/buildbot/chromium.win.json
@@ -15,6 +15,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -3534,6 +3537,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -7248,6 +7254,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -8772,6 +8781,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true,
diff --git a/testing/buildbot/client.devtools-frontend.integration.json b/testing/buildbot/client.devtools-frontend.integration.json index 845f6c6..09c8a5a8 100644 --- a/testing/buildbot/client.devtools-frontend.integration.json +++ b/testing/buildbot/client.devtools-frontend.integration.json
@@ -62,6 +62,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -89,6 +92,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webkit_layout_from_devtools", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true,
diff --git a/testing/buildbot/client.v8.fyi.json b/testing/buildbot/client.v8.fyi.json index 33541c9..79e9b72 100644 --- a/testing/buildbot/client.v8.fyi.json +++ b/testing/buildbot/client.v8.fyi.json
@@ -1367,6 +1367,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -1425,6 +1428,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -1481,6 +1487,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -1534,6 +1543,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -1590,6 +1602,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -1622,6 +1637,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true,
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index 35ec22fa..7e42d4d 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -934,10 +934,13 @@ ], 'script': '//third_party/blink/tools/merge_web_test_results.py', }, + 'resultdb': { + 'enable': True, + }, 'results_handler': 'layout tests', 'swarming': { 'shards': 12, - } + }, }, 'webdriver_tests_suite': { 'isolate_name': 'webdriver_wpt_tests', @@ -973,6 +976,9 @@ ], 'script': '//third_party/blink/tools/merge_web_test_results.py', }, + 'resultdb': { + 'enable': True, + }, 'results_handler': 'layout tests', 'swarming': { 'shards': 12, @@ -997,6 +1003,9 @@ ], 'script': '//third_party/blink/tools/merge_web_test_results.py', }, + 'resultdb': { + 'enable': True, + }, 'results_handler': 'layout tests', 'swarming': { 'shards': 12, @@ -1152,6 +1161,9 @@ ], 'script': '//third_party/blink/tools/merge_web_test_results.py', }, + 'resultdb': { + 'enable': True, + }, 'results_handler': 'layout tests', 'swarming': { 'shards': 12, @@ -1219,6 +1231,9 @@ ], 'script': '//third_party/blink/tools/merge_web_test_results.py', }, + 'resultdb': { + 'enable': True, + }, 'results_handler': 'layout tests', 'swarming': { 'shards': 12, @@ -1240,6 +1255,9 @@ ], 'script': '//third_party/blink/tools/merge_web_test_results.py', }, + 'resultdb': { + 'enable': True, + }, 'results_handler': 'layout tests', 'swarming': { 'shards': 4, @@ -2061,6 +2079,9 @@ ], 'script': '//third_party/blink/tools/merge_web_test_results.py', }, + 'resultdb': { + 'enable': True, + }, 'results_handler': 'layout tests', }, }, @@ -2096,6 +2117,9 @@ ], 'script': '//third_party/blink/tools/merge_web_test_results.py', }, + 'resultdb': { + 'enable': True, + }, 'results_handler': 'layout tests', }, }, @@ -3142,6 +3166,9 @@ 'script': '//third_party/blink/tools/merge_web_test_results.py', }, 'isolate_name': 'webgpu_blink_web_tests', + 'resultdb': { + 'enable': True, + }, }, }, @@ -3178,6 +3205,9 @@ 'script': '//third_party/blink/tools/merge_web_test_results.py', }, 'isolate_name': 'webgpu_blink_web_tests', + 'resultdb': { + 'enable': True, + }, }, }, @@ -3432,6 +3462,9 @@ ], 'script': '//third_party/blink/tools/merge_web_test_results.py', }, + 'resultdb': { + 'enable': True, + }, 'results_handler': 'layout tests', 'swarming': { 'shards': 10, @@ -3930,6 +3963,9 @@ ], 'script': '//third_party/blink/tools/merge_web_test_results.py', }, + 'resultdb': { + 'enable': True, + }, 'results_handler': 'layout tests', }, 'vulkan_swiftshader_blink_web_tests': { @@ -3957,6 +3993,9 @@ ], 'script': '//third_party/blink/tools/merge_web_test_results.py', }, + 'resultdb': { + 'enable': True, + }, 'results_handler': 'layout tests', }, },
diff --git a/testing/buildbot/tryserver.chromium.android.json b/testing/buildbot/tryserver.chromium.android.json index abcb2f1..92059ee3 100644 --- a/testing/buildbot/tryserver.chromium.android.json +++ b/testing/buildbot/tryserver.chromium.android.json
@@ -166,6 +166,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true,
diff --git a/testing/buildbot/tryserver.chromium.linux.json b/testing/buildbot/tryserver.chromium.linux.json index 2b5296b..b1054e2 100644 --- a/testing/buildbot/tryserver.chromium.linux.json +++ b/testing/buildbot/tryserver.chromium.linux.json
@@ -24,6 +24,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -57,6 +60,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true,
diff --git a/testing/buildbot/tryserver.devtools-frontend.json b/testing/buildbot/tryserver.devtools-frontend.json index d3d4b0e..fe4f44b 100644 --- a/testing/buildbot/tryserver.devtools-frontend.json +++ b/testing/buildbot/tryserver.devtools-frontend.json
@@ -39,6 +39,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -66,6 +69,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webkit_layout_from_devtools", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -95,6 +101,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "blink_web_tests", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true, @@ -122,6 +131,9 @@ "script": "//third_party/blink/tools/merge_web_test_results.py" }, "name": "webkit_layout_from_devtools", + "resultdb": { + "enable": true + }, "results_handler": "layout tests", "swarming": { "can_use_on_swarming_builders": true,
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index b235728d..6b86db6 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -1248,27 +1248,6 @@ ] } ], - "CSSOMViewScrollCoordinates": [ - { - "platforms": [ - "android", - "android_weblayer", - "android_webview", - "chromeos", - "linux", - "mac", - "windows" - ], - "experiments": [ - { - "name": "EnableCSSOMViewScrollCoordinates", - "enable_features": [ - "CSSOMViewScrollCoordinates" - ] - } - ] - } - ], "CacheStorageSequenceChromeOS": [ { "platforms": [
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index b1e77d0f..b4d8789 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc
@@ -162,10 +162,6 @@ #endif }; -// Enable CSSOM View Scroll Coordinates. https://crbug.com/721759. -const base::Feature kCSSOMViewScrollCoordinates{ - "CSSOMViewScrollCoordinates", base::FEATURE_DISABLED_BY_DEFAULT}; - // Enables Raw Clipboard. https://crbug.com/897289. const base::Feature kRawClipboard{"RawClipboard", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h index ed0274a6..4797031 100644 --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h
@@ -28,7 +28,6 @@ BLINK_COMMON_EXPORT extern const base::Feature kFreezeUserAgent; BLINK_COMMON_EXPORT extern const base::Feature kFtpProtocol; BLINK_COMMON_EXPORT extern const base::Feature kImplicitRootScroller; -BLINK_COMMON_EXPORT extern const base::Feature kCSSOMViewScrollCoordinates; BLINK_COMMON_EXPORT extern const base::Feature kDisplayLocking; BLINK_COMMON_EXPORT extern const base::Feature kJSONModules; BLINK_COMMON_EXPORT extern const base::Feature kForceSynchronousHTMLParsing;
diff --git a/third_party/blink/public/common/privacy_budget/identifiable_surface.h b/third_party/blink/public/common/privacy_budget/identifiable_surface.h index f2ea1d5a..c6ee81b 100644 --- a/third_party/blink/public/common/privacy_budget/identifiable_surface.h +++ b/third_party/blink/public/common/privacy_budget/identifiable_surface.h
@@ -187,6 +187,12 @@ // Represents a call to GPU.requestAdapter. Input is the options filter. kGPU_RequestAdapter = 20, + // For instrumenting HTMLCanvas.getContext() fingerprinting. Some scripts + // will iterate through the different possible arguments and record whether + // each type of context is supported. + // The input should be an instance of CanvasRenderingContext::ContextType. + kCanvasRenderingContext = 21, + // NavigatorUAData.getHighEntropyValues() is, shockingly, a high entropy // API to provide more detailed User-Agent data. The output is keyed on // the hint parameter.
diff --git a/third_party/blink/public/platform/web_runtime_features.h b/third_party/blink/public/platform/web_runtime_features.h index 1207db2..a666132d7 100644 --- a/third_party/blink/public/platform/web_runtime_features.h +++ b/third_party/blink/public/platform/web_runtime_features.h
@@ -111,7 +111,6 @@ BLINK_PLATFORM_EXPORT static void EnableForceTallerSelectPopup(bool); BLINK_PLATFORM_EXPORT static void EnableGenericSensorExtraClasses(bool); BLINK_PLATFORM_EXPORT static void EnableImplicitRootScroller(bool); - BLINK_PLATFORM_EXPORT static void EnableCSSOMViewScrollCoordinates(bool); BLINK_PLATFORM_EXPORT static void EnableInputMultipleFieldsUI(bool); BLINK_PLATFORM_EXPORT static void EnableLayoutNG(bool); BLINK_PLATFORM_EXPORT static void EnableLazyFrameLoading(bool);
diff --git a/third_party/blink/renderer/bindings/generated_in_modules.gni b/third_party/blink/renderer/bindings/generated_in_modules.gni index 9875903..c4f36e6f 100644 --- a/third_party/blink/renderer/bindings/generated_in_modules.gni +++ b/third_party/blink/renderer/bindings/generated_in_modules.gni
@@ -693,16 +693,6 @@ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_peer_connection_ice_error_event_init.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_peer_connection_ice_event_init.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_peer_connection_ice_event_init.h", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_quic_parameters.cc", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_quic_parameters.h", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_quic_stream_event_init.cc", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_quic_stream_event_init.h", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_quic_stream_read_result.cc", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_quic_stream_read_result.h", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_quic_stream_write_parameters.cc", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_quic_stream_write_parameters.h", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_quic_transport_stats.cc", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_quic_transport_stats.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_rtcp_parameters.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_rtcp_parameters.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_rtp_capabilities.cc", @@ -1114,12 +1104,6 @@ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_peer_connection_state.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_priority_type.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_priority_type.h", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_quic_role.cc", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_quic_role.h", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_quic_stream_state.cc", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_quic_stream_state.h", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_quic_transport_state.cc", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_quic_transport_state.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_rtcp_mux_policy.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_rtcp_mux_policy.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_rtp_transceiver_direction.cc", @@ -1899,12 +1883,6 @@ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_peer_connection_ice_error_event.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_peer_connection_ice_event.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_peer_connection_ice_event.h", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_quic_stream.cc", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_quic_stream.h", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_quic_stream_event.cc", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_quic_stream_event.h", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_quic_transport.cc", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_quic_transport.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_rtp_receiver.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_rtp_receiver.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_rtc_rtp_sender.cc",
diff --git a/third_party/blink/renderer/bindings/idl_in_modules.gni b/third_party/blink/renderer/bindings/idl_in_modules.gni index 3f3c2d3..317eac0 100644 --- a/third_party/blink/renderer/bindings/idl_in_modules.gni +++ b/third_party/blink/renderer/bindings/idl_in_modules.gni
@@ -498,14 +498,6 @@ "//third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_ice_error_event_init.idl", "//third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_ice_event.idl", "//third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_ice_event_init.idl", - "//third_party/blink/renderer/modules/peerconnection/rtc_quic_parameters.idl", - "//third_party/blink/renderer/modules/peerconnection/rtc_quic_stream.idl", - "//third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_event.idl", - "//third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_event_init.idl", - "//third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_read_result.idl", - "//third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_write_parameters.idl", - "//third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.idl", - "//third_party/blink/renderer/modules/peerconnection/rtc_quic_transport_stats.idl", "//third_party/blink/renderer/modules/peerconnection/rtc_rtcp_parameters.idl", "//third_party/blink/renderer/modules/peerconnection/rtc_rtp_capabilities.idl", "//third_party/blink/renderer/modules/peerconnection/rtc_rtp_codec_capability.idl",
diff --git a/third_party/blink/renderer/bindings/modules/BUILD.gn b/third_party/blink/renderer/bindings/modules/BUILD.gn index 5df6401..f13639be 100644 --- a/third_party/blink/renderer/bindings/modules/BUILD.gn +++ b/third_party/blink/renderer/bindings/modules/BUILD.gn
@@ -52,7 +52,6 @@ "//third_party/blink/renderer/modules/peerconnection/rtc_dtmf_tone_change_event.idl", "//third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_ice_error_event.idl", "//third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_ice_event.idl", - "//third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_event.idl", "//third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_event.idl", "//third_party/blink/renderer/modules/presentation/presentation_connection_available_event.idl", "//third_party/blink/renderer/modules/presentation/presentation_connection_close_event.idl",
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc index 45a7fe8..7ec31d8 100644 --- a/third_party/blink/renderer/core/dom/element.cc +++ b/third_party/blink/renderer/core/dom/element.cc
@@ -1399,16 +1399,8 @@ kElementWithLeftwardOrUpwardOverflowDirection_ScrollLeftOrTop); } - // In order to keep the behavior of element scroll consistent with document - // scroll, and consistent with the behavior of other vendors, the scrollLeft - // of a box is changed to the offset from |ScrollOrigin()|. - if (RuntimeEnabledFeatures::CSSOMViewScrollCoordinatesEnabled()) { - return AdjustForAbsoluteZoom::AdjustScroll( - scrollable_area->GetScrollOffset().Width(), *GetLayoutBox()); - } else { - return AdjustForAbsoluteZoom::AdjustScroll( - scrollable_area->ScrollPosition().X(), *GetLayoutBox()); - } + return AdjustForAbsoluteZoom::AdjustScroll( + scrollable_area->GetScrollOffset().Width(), *GetLayoutBox()); } return 0; @@ -1440,16 +1432,8 @@ kElementWithLeftwardOrUpwardOverflowDirection_ScrollLeftOrTop); } - // In order to keep the behavior of element scroll consistent with document - // scroll, and consistent with the behavior of other vendors, the scrollTop - // of a box is changed to the offset from |ScrollOrigin()|. - if (RuntimeEnabledFeatures::CSSOMViewScrollCoordinatesEnabled()) { - return AdjustForAbsoluteZoom::AdjustScroll( - scrollable_area->GetScrollOffset().Height(), *GetLayoutBox()); - } else { - return AdjustForAbsoluteZoom::AdjustScroll( - scrollable_area->ScrollPosition().Y(), *GetLayoutBox()); - } + return AdjustForAbsoluteZoom::AdjustScroll( + scrollable_area->GetScrollOffset().Height(), *GetLayoutBox()); } return 0; @@ -1490,38 +1474,21 @@ } } - if (RuntimeEnabledFeatures::CSSOMViewScrollCoordinatesEnabled()) { - ScrollOffset end_offset(new_left * box->Style()->EffectiveZoom(), - scrollable_area->GetScrollOffset().Height()); - std::unique_ptr<cc::SnapSelectionStrategy> strategy = - cc::SnapSelectionStrategy::CreateForEndPosition( - gfx::ScrollOffset( - scrollable_area->ScrollOffsetToPosition(end_offset)), - true, false); - base::Optional<FloatPoint> snap_point = - scrollable_area->GetSnapPositionAndSetTarget(*strategy); - if (snap_point.has_value()) { - end_offset = - scrollable_area->ScrollPositionToOffset(snap_point.value()); - } - scrollable_area->SetScrollOffset(end_offset, - mojom::blink::ScrollType::kProgrammatic, - mojom::blink::ScrollBehavior::kAuto); - } else { - FloatPoint end_point(new_left * box->Style()->EffectiveZoom(), - scrollable_area->ScrollPosition().Y()); - std::unique_ptr<cc::SnapSelectionStrategy> strategy = - cc::SnapSelectionStrategy::CreateForEndPosition( - gfx::ScrollOffset(end_point), true, false); - end_point = - scrollable_area->GetSnapPositionAndSetTarget(*strategy).value_or( - end_point); - - FloatPoint new_position(end_point.X(), - scrollable_area->ScrollPosition().Y()); - scrollable_area->ScrollToAbsolutePosition( - new_position, mojom::blink::ScrollBehavior::kAuto); + ScrollOffset end_offset(new_left * box->Style()->EffectiveZoom(), + scrollable_area->GetScrollOffset().Height()); + std::unique_ptr<cc::SnapSelectionStrategy> strategy = + cc::SnapSelectionStrategy::CreateForEndPosition( + gfx::ScrollOffset( + scrollable_area->ScrollOffsetToPosition(end_offset)), + true, false); + base::Optional<FloatPoint> snap_point = + scrollable_area->GetSnapPositionAndSetTarget(*strategy); + if (snap_point.has_value()) { + end_offset = scrollable_area->ScrollPositionToOffset(snap_point.value()); } + scrollable_area->SetScrollOffset(end_offset, + mojom::blink::ScrollType::kProgrammatic, + mojom::blink::ScrollBehavior::kAuto); } } @@ -1560,38 +1527,22 @@ } } - if (RuntimeEnabledFeatures::CSSOMViewScrollCoordinatesEnabled()) { - ScrollOffset end_offset(scrollable_area->GetScrollOffset().Width(), - new_top * box->Style()->EffectiveZoom()); - std::unique_ptr<cc::SnapSelectionStrategy> strategy = - cc::SnapSelectionStrategy::CreateForEndPosition( - gfx::ScrollOffset( - scrollable_area->ScrollOffsetToPosition(end_offset)), - false, true); - base::Optional<FloatPoint> snap_point = - scrollable_area->GetSnapPositionAndSetTarget(*strategy); - if (snap_point.has_value()) { - end_offset = - scrollable_area->ScrollPositionToOffset(snap_point.value()); - } - - scrollable_area->SetScrollOffset(end_offset, - mojom::blink::ScrollType::kProgrammatic, - mojom::blink::ScrollBehavior::kAuto); - } else { - FloatPoint end_point(scrollable_area->ScrollPosition().X(), - new_top * box->Style()->EffectiveZoom()); - std::unique_ptr<cc::SnapSelectionStrategy> strategy = - cc::SnapSelectionStrategy::CreateForEndPosition( - gfx::ScrollOffset(end_point), false, true); - end_point = - scrollable_area->GetSnapPositionAndSetTarget(*strategy).value_or( - end_point); - FloatPoint new_position(scrollable_area->ScrollPosition().X(), - end_point.Y()); - scrollable_area->ScrollToAbsolutePosition( - new_position, mojom::blink::ScrollBehavior::kAuto); + ScrollOffset end_offset(scrollable_area->GetScrollOffset().Width(), + new_top * box->Style()->EffectiveZoom()); + std::unique_ptr<cc::SnapSelectionStrategy> strategy = + cc::SnapSelectionStrategy::CreateForEndPosition( + gfx::ScrollOffset( + scrollable_area->ScrollOffsetToPosition(end_offset)), + false, true); + base::Optional<FloatPoint> snap_point = + scrollable_area->GetSnapPositionAndSetTarget(*strategy); + if (snap_point.has_value()) { + end_offset = scrollable_area->ScrollPositionToOffset(snap_point.value()); } + + scrollable_area->SetScrollOffset(end_offset, + mojom::blink::ScrollType::kProgrammatic, + mojom::blink::ScrollBehavior::kAuto); } } @@ -1759,60 +1710,31 @@ } } - // In order to keep the behavior of element scroll consistent with document - // scroll, and consistent with the behavior of other vendors, the - // offsets in |scroll_to_options| are treated as the offset from - // |ScrollOrigin()|. - if (RuntimeEnabledFeatures::CSSOMViewScrollCoordinatesEnabled()) { - ScrollOffset new_offset = scrollable_area->GetScrollOffset(); - if (scroll_to_options->hasLeft()) { - new_offset.SetWidth(ScrollableArea::NormalizeNonFiniteScroll( - scroll_to_options->left()) * - box->Style()->EffectiveZoom()); - } - if (scroll_to_options->hasTop()) { - new_offset.SetHeight( - ScrollableArea::NormalizeNonFiniteScroll(scroll_to_options->top()) * - box->Style()->EffectiveZoom()); - } - - std::unique_ptr<cc::SnapSelectionStrategy> strategy = - cc::SnapSelectionStrategy::CreateForEndPosition( - gfx::ScrollOffset( - scrollable_area->ScrollOffsetToPosition(new_offset)), - scroll_to_options->hasLeft(), scroll_to_options->hasTop()); - base::Optional<FloatPoint> snap_point = - scrollable_area->GetSnapPositionAndSetTarget(*strategy); - if (snap_point.has_value()) { - new_offset = - scrollable_area->ScrollPositionToOffset(snap_point.value()); - } - - scrollable_area->SetScrollOffset( - new_offset, mojom::blink::ScrollType::kProgrammatic, scroll_behavior); - } else { - FloatPoint new_position(scrollable_area->ScrollPosition().X(), - scrollable_area->ScrollPosition().Y()); - if (scroll_to_options->hasLeft()) { - new_position.SetX(ScrollableArea::NormalizeNonFiniteScroll( - scroll_to_options->left()) * - box->Style()->EffectiveZoom()); - } - if (scroll_to_options->hasTop()) { - new_position.SetY( - ScrollableArea::NormalizeNonFiniteScroll(scroll_to_options->top()) * - box->Style()->EffectiveZoom()); - } - - std::unique_ptr<cc::SnapSelectionStrategy> strategy = - cc::SnapSelectionStrategy::CreateForEndPosition( - gfx::ScrollOffset(new_position), scroll_to_options->hasLeft(), - scroll_to_options->hasTop()); - new_position = - scrollable_area->GetSnapPositionAndSetTarget(*strategy).value_or( - new_position); - scrollable_area->ScrollToAbsolutePosition(new_position, scroll_behavior); + ScrollOffset new_offset = scrollable_area->GetScrollOffset(); + if (scroll_to_options->hasLeft()) { + new_offset.SetWidth( + ScrollableArea::NormalizeNonFiniteScroll(scroll_to_options->left()) * + box->Style()->EffectiveZoom()); } + if (scroll_to_options->hasTop()) { + new_offset.SetHeight( + ScrollableArea::NormalizeNonFiniteScroll(scroll_to_options->top()) * + box->Style()->EffectiveZoom()); + } + + std::unique_ptr<cc::SnapSelectionStrategy> strategy = + cc::SnapSelectionStrategy::CreateForEndPosition( + gfx::ScrollOffset( + scrollable_area->ScrollOffsetToPosition(new_offset)), + scroll_to_options->hasLeft(), scroll_to_options->hasTop()); + base::Optional<FloatPoint> snap_point = + scrollable_area->GetSnapPositionAndSetTarget(*strategy); + if (snap_point.has_value()) { + new_offset = scrollable_area->ScrollPositionToOffset(snap_point.value()); + } + + scrollable_area->SetScrollOffset( + new_offset, mojom::blink::ScrollType::kProgrammatic, scroll_behavior); } }
diff --git a/third_party/blink/renderer/core/editing/visible_position.cc b/third_party/blink/renderer/core/editing/visible_position.cc index d271f495..8d5860f 100644 --- a/third_party/blink/renderer/core/editing/visible_position.cc +++ b/third_party/blink/renderer/core/editing/visible_position.cc
@@ -82,49 +82,36 @@ DocumentLifecycle::DisallowTransitionScope disallow_transition( document.Lifecycle()); - // Find the canonical position with a backward preference. - const PositionWithAffinityTemplate<Strategy> backward_position = - SnapBackward(position_with_affinity.GetPosition()); - if (backward_position.IsNull()) + const PositionTemplate<Strategy> deep_position = + CanonicalPositionOf(position_with_affinity.GetPosition()); + if (deep_position.IsNull()) return VisiblePositionTemplate<Strategy>(); - const PositionWithAffinityTemplate<Strategy> backward_position_upstream( - backward_position.GetPosition(), TextAffinity::kUpstream); - const PositionWithAffinityTemplate<Strategy> backward_position_downstream( - backward_position.GetPosition(), TextAffinity::kDownstream); + const PositionWithAffinityTemplate<Strategy> downstream_position( + deep_position); + if (position_with_affinity.Affinity() == TextAffinity::kDownstream) + return VisiblePositionTemplate<Strategy>(downstream_position); if (RuntimeEnabledFeatures::BidiCaretAffinityEnabled() && - NGInlineFormattingContextOf(backward_position.GetPosition())) { - if (position_with_affinity.Affinity() == TextAffinity::kDownstream) - return VisiblePositionTemplate<Strategy>(backward_position_downstream); + NGInlineFormattingContextOf(deep_position)) { // When not at a line wrap or bidi boundary, make sure to end up with // |TextAffinity::Downstream| affinity. - if (AbsoluteCaretBoundsOf(backward_position_upstream) == - AbsoluteCaretBoundsOf(backward_position_downstream)) { - return VisiblePositionTemplate<Strategy>(backward_position_downstream); + const PositionWithAffinityTemplate<Strategy> upstream_position( + deep_position, TextAffinity::kUpstream); + + if (AbsoluteCaretBoundsOf(downstream_position) != + AbsoluteCaretBoundsOf(upstream_position)) { + return VisiblePositionTemplate<Strategy>(upstream_position); } - return VisiblePositionTemplate<Strategy>(backward_position_upstream); + return VisiblePositionTemplate<Strategy>(downstream_position); } - // Find the canonical position with a forward preference. If backward_position - // has a downstream affinity, it means that we couldn't find any backward - // candidate, so they must be equal and we can avoid calling SnapForward(). - // The forward canonical position can't be null because we already checked - // that the backward one is not null. - const PositionWithAffinityTemplate<Strategy> forward_position = - backward_position.Affinity() == TextAffinity::kDownstream - ? backward_position - : SnapForward(position_with_affinity.GetPosition()); - DCHECK(forward_position.IsNotNull()); - - // When not at a line wrap, make sure to end up with the backward canonical - // position with |TextAffinity::Downstream| affinity. - if (InSameLine(backward_position_upstream, forward_position)) - return VisiblePositionTemplate<Strategy>(backward_position_downstream); - if (position_with_affinity.Affinity() == TextAffinity::kUpstream) - return VisiblePositionTemplate<Strategy>(backward_position_upstream); - if (StartOfLine(forward_position).IsNull()) - return VisiblePositionTemplate<Strategy>(backward_position_downstream); - return VisiblePositionTemplate<Strategy>(forward_position); + // When not at a line wrap, make sure to end up with + // |TextAffinity::Downstream| affinity. + const PositionWithAffinityTemplate<Strategy> upstream_position( + deep_position, TextAffinity::kUpstream); + if (InSameLine(downstream_position, upstream_position)) + return VisiblePositionTemplate<Strategy>(downstream_position); + return VisiblePositionTemplate<Strategy>(upstream_position); } template <typename Strategy>
diff --git a/third_party/blink/renderer/core/editing/visible_position_test.cc b/third_party/blink/renderer/core/editing/visible_position_test.cc index 36547fc..46cb89b 100644 --- a/third_party/blink/renderer/core/editing/visible_position_test.cc +++ b/third_party/blink/renderer/core/editing/visible_position_test.cc
@@ -157,35 +157,19 @@ EXPECT_EQ(Position(one->firstChild(), 0), CanonicalPositionOf(Position(one, 0))); EXPECT_EQ(Position(one->firstChild(), 0), - SnapBackward(Position(one, 0)).GetPosition()); - EXPECT_EQ(Position(one->firstChild(), 0), - SnapForward(Position(one, 0)).GetPosition()); - EXPECT_EQ(Position(one->firstChild(), 0), CreateVisiblePosition(Position(one, 0)).DeepEquivalent()); EXPECT_EQ(Position(one->firstChild(), 2), CanonicalPositionOf(Position(two, 0))); EXPECT_EQ(Position(one->firstChild(), 2), - SnapBackward(Position(two, 0)).GetPosition()); - EXPECT_EQ(Position(two->firstChild(), 0), - SnapForward(Position(two, 0)).GetPosition()); - EXPECT_EQ(Position(one->firstChild(), 2), CreateVisiblePosition(Position(two, 0)).DeepEquivalent()); EXPECT_EQ(PositionInFlatTree(five->firstChild(), 2), CanonicalPositionOf(PositionInFlatTree(one, 0))); EXPECT_EQ(PositionInFlatTree(five->firstChild(), 2), - SnapBackward(PositionInFlatTree(one, 0)).GetPosition()); - EXPECT_EQ(PositionInFlatTree(one->firstChild(), 0), - SnapForward(PositionInFlatTree(one, 0)).GetPosition()); - EXPECT_EQ(PositionInFlatTree(five->firstChild(), 2), CreateVisiblePosition(PositionInFlatTree(one, 0)).DeepEquivalent()); EXPECT_EQ(PositionInFlatTree(four->firstChild(), 2), CanonicalPositionOf(PositionInFlatTree(two, 0))); EXPECT_EQ(PositionInFlatTree(four->firstChild(), 2), - SnapBackward(PositionInFlatTree(two, 0)).GetPosition()); - EXPECT_EQ(PositionInFlatTree(two->firstChild(), 0), - SnapForward(PositionInFlatTree(two, 0)).GetPosition()); - EXPECT_EQ(PositionInFlatTree(four->firstChild(), 2), CreateVisiblePosition(PositionInFlatTree(two, 0)).DeepEquivalent()); }
diff --git a/third_party/blink/renderer/core/editing/visible_units.cc b/third_party/blink/renderer/core/editing/visible_units.cc index 78c03b1..f308a02 100644 --- a/third_party/blink/renderer/core/editing/visible_units.cc +++ b/third_party/blink/renderer/core/editing/visible_units.cc
@@ -75,7 +75,32 @@ } template <typename PositionType> -static PositionType SnapFallbackTemplate(const PositionType& position) { +static PositionType CanonicalPosition(const PositionType& position) { + // Sometimes updating selection positions can be extremely expensive and + // occur frequently. Often calling preventDefault on mousedown events can + // avoid doing unnecessary text selection work. http://crbug.com/472258. + TRACE_EVENT0("input", "VisibleUnits::canonicalPosition"); + + // FIXME (9535): Canonicalizing to the leftmost candidate means that if + // we're at a line wrap, we will ask layoutObjects to paint downstream + // carets for other layoutObjects. To fix this, we need to either a) add + // code to all paintCarets to pass the responsibility off to the appropriate + // layoutObject for VisiblePosition's like these, or b) canonicalize to the + // rightmost candidate unless the affinity is upstream. + if (position.IsNull()) + return PositionType(); + + DCHECK(position.GetDocument()); + DCHECK(!position.GetDocument()->NeedsLayoutTreeUpdate()); + + const PositionType& backward_candidate = MostBackwardCaretPosition(position); + if (IsVisuallyEquivalentCandidate(backward_candidate)) + return backward_candidate; + + const PositionType& forward_candidate = MostForwardCaretPosition(position); + if (IsVisuallyEquivalentCandidate(forward_candidate)) + return forward_candidate; + // When neither upstream or downstream gets us to a candidate // (upstream/downstream won't leave blocks or enter new ones), we search // forward and backward until we find one. @@ -128,93 +153,12 @@ return next; } -template <typename Strategy> -static PositionWithAffinityTemplate<Strategy> SnapBackwardTemplate( - const PositionTemplate<Strategy>& position) { - // Sometimes updating selection positions can be extremely expensive and - // occur frequently. Often calling preventDefault on mousedown events can - // avoid doing unnecessary text selection work. http://crbug.com/472258. - TRACE_EVENT0("input", "VisibleUnits::SnapBackward"); - - if (position.IsNull()) - return PositionWithAffinityTemplate<Strategy>(); - - DCHECK(position.GetDocument()); - DCHECK(!position.GetDocument()->NeedsLayoutTreeUpdate()); - - const PositionTemplate<Strategy>& candidate1 = - MostBackwardCaretPosition(position); - if (IsVisuallyEquivalentCandidate(candidate1)) { - return PositionWithAffinityTemplate<Strategy>(candidate1, - TextAffinity::kUpstream); - } - - const PositionTemplate<Strategy>& candidate2 = - MostForwardCaretPosition(position); - if (IsVisuallyEquivalentCandidate(candidate2)) { - return PositionWithAffinityTemplate<Strategy>(candidate2, - TextAffinity::kDownstream); - } - - return PositionWithAffinityTemplate<Strategy>(SnapFallbackTemplate(position), - TextAffinity::kDownstream); -} - -PositionWithAffinity SnapBackward(const Position& position) { - return SnapBackwardTemplate(position); -} - -PositionInFlatTreeWithAffinity SnapBackward( - const PositionInFlatTree& position) { - return SnapBackwardTemplate(position); -} - -template <typename Strategy> -static PositionWithAffinityTemplate<Strategy> SnapForwardTemplate( - const PositionTemplate<Strategy>& position) { - // Sometimes updating selection positions can be extremely expensive and - // occur frequently. Often calling preventDefault on mousedown events can - // avoid doing unnecessary text selection work. http://crbug.com/472258. - TRACE_EVENT0("input", "VisibleUnits::SnapForward"); - - if (position.IsNull()) - return PositionWithAffinityTemplate<Strategy>(); - - DCHECK(position.GetDocument()); - DCHECK(!position.GetDocument()->NeedsLayoutTreeUpdate()); - - const PositionTemplate<Strategy>& candidate1 = - MostForwardCaretPosition(position); - if (IsVisuallyEquivalentCandidate(candidate1)) { - return PositionWithAffinityTemplate<Strategy>(candidate1, - TextAffinity::kDownstream); - } - - const PositionTemplate<Strategy>& candidate2 = - MostBackwardCaretPosition(position); - if (IsVisuallyEquivalentCandidate(candidate2)) { - return PositionWithAffinityTemplate<Strategy>(candidate2, - TextAffinity::kDownstream); - } - - return PositionWithAffinityTemplate<Strategy>(SnapFallbackTemplate(position), - TextAffinity::kDownstream); -} - -PositionWithAffinity SnapForward(const Position& position) { - return SnapForwardTemplate(position); -} - -PositionInFlatTreeWithAffinity SnapForward(const PositionInFlatTree& position) { - return SnapForwardTemplate(position); -} - Position CanonicalPositionOf(const Position& position) { - return SnapBackward(position).GetPosition(); + return CanonicalPosition(position); } PositionInFlatTree CanonicalPositionOf(const PositionInFlatTree& position) { - return SnapBackward(position).GetPosition(); + return CanonicalPosition(position); } template <typename Strategy>
diff --git a/third_party/blink/renderer/core/editing/visible_units.h b/third_party/blink/renderer/core/editing/visible_units.h index 16fa1fb5..3c32ec2 100644 --- a/third_party/blink/renderer/core/editing/visible_units.h +++ b/third_party/blink/renderer/core/editing/visible_units.h
@@ -92,12 +92,6 @@ // If true, adjacent candidates are visually distinct. CORE_EXPORT bool EndsOfNodeAreVisuallyDistinctPositions(const Node*); -CORE_EXPORT PositionWithAffinity SnapBackward(const Position&); -CORE_EXPORT PositionInFlatTreeWithAffinity -SnapBackward(const PositionInFlatTree&); -CORE_EXPORT PositionWithAffinity SnapForward(const Position&); -CORE_EXPORT PositionInFlatTreeWithAffinity -SnapForward(const PositionInFlatTree&); CORE_EXPORT Position CanonicalPositionOf(const Position&); CORE_EXPORT PositionInFlatTree CanonicalPositionOf(const PositionInFlatTree&); @@ -162,17 +156,11 @@ CORE_EXPORT VisiblePosition StartOfLine(const VisiblePosition&); CORE_EXPORT VisiblePositionInFlatTree StartOfLine(const VisiblePositionInFlatTree&); -CORE_EXPORT PositionWithAffinity StartOfLine(const PositionWithAffinity&); -CORE_EXPORT PositionInFlatTreeWithAffinity -StartOfLine(const PositionInFlatTreeWithAffinity&); // TODO(yosin) Return values of |VisiblePosition| version of |endOfLine()| with // shadow tree isn't defined well. We should not use it for shadow tree. CORE_EXPORT VisiblePosition EndOfLine(const VisiblePosition&); CORE_EXPORT VisiblePositionInFlatTree EndOfLine(const VisiblePositionInFlatTree&); -CORE_EXPORT PositionWithAffinity EndOfLine(const PositionWithAffinity&); -CORE_EXPORT PositionInFlatTreeWithAffinity -EndOfLine(const PositionInFlatTreeWithAffinity&); CORE_EXPORT bool InSameLine(const VisiblePosition&, const VisiblePosition&); CORE_EXPORT bool InSameLine(const VisiblePositionInFlatTree&, const VisiblePositionInFlatTree&);
diff --git a/third_party/blink/renderer/core/editing/visible_units_line.cc b/third_party/blink/renderer/core/editing/visible_units_line.cc index 44c6b8b..96d9af5 100644 --- a/third_party/blink/renderer/core/editing/visible_units_line.cc +++ b/third_party/blink/renderer/core/editing/visible_units_line.cc
@@ -313,8 +313,6 @@ vis_pos, c.GetPosition()); } -} // namespace - PositionWithAffinity StartOfLine(const PositionWithAffinity& current_position) { return StartOfLineAlgorithm<EditingStrategy>(current_position); } @@ -324,6 +322,8 @@ return StartOfLineAlgorithm<EditingInFlatTreeStrategy>(current_position); } +} // namespace + // FIXME: Rename this function to reflect the fact it ignores bidi levels. VisiblePosition StartOfLine(const VisiblePosition& current_position) { DCHECK(current_position.IsValid()) << current_position; @@ -394,11 +394,11 @@ candidate_position, current_position.GetPosition()); } -PositionWithAffinity EndOfLine(const PositionWithAffinity& position) { +static PositionWithAffinity EndOfLine(const PositionWithAffinity& position) { return EndOfLineAlgorithm<EditingStrategy>(position); } -PositionInFlatTreeWithAffinity EndOfLine( +static PositionInFlatTreeWithAffinity EndOfLine( const PositionInFlatTreeWithAffinity& position) { return EndOfLineAlgorithm<EditingInFlatTreeStrategy>(position); }
diff --git a/third_party/blink/renderer/core/editing/visible_units_line_test.cc b/third_party/blink/renderer/core/editing/visible_units_line_test.cc index 3d9c9f3..c1dfc5a 100644 --- a/third_party/blink/renderer/core/editing/visible_units_line_test.cc +++ b/third_party/blink/renderer/core/editing/visible_units_line_test.cc
@@ -121,12 +121,8 @@ PositionInFlatTree(seven, 7), EndOfLine(CreateVisiblePositionInFlatTree(*one, 1)).DeepEquivalent()); - EXPECT_EQ(Position(seven, 7), EndOfLine(CreateVisiblePositionInDOMTree( - *two, 0, TextAffinity::kUpstream)) - .DeepEquivalent()); EXPECT_EQ( - // The result on legacy layout is broken and not worth fixing. - LayoutNGEnabled() ? Position(two, 2) : Position(five, 5), + Position(seven, 7), EndOfLine(CreateVisiblePositionInDOMTree(*two, 0)).DeepEquivalent()); EXPECT_EQ( PositionInFlatTree(two, 2), @@ -143,11 +139,6 @@ EXPECT_EQ( // The result on legacy layout is broken and not worth fixing. LayoutNGEnabled() ? Position(two, 2) : Position(five, 5), - EndOfLine( - CreateVisiblePositionInDOMTree(*three, 0, TextAffinity::kUpstream)) - .DeepEquivalent()); - EXPECT_EQ( - Position(four, 4), EndOfLine(CreateVisiblePositionInDOMTree(*three, 0)).DeepEquivalent()); EXPECT_EQ( PositionInFlatTree(four, 4), @@ -213,9 +204,11 @@ EXPECT_FALSE(IsEndOfLine(CreateVisiblePositionInDOMTree(*one, 1))); EXPECT_FALSE(IsEndOfLine(CreateVisiblePositionInFlatTree(*one, 1))); - EXPECT_TRUE(IsEndOfLine( - CreateVisiblePositionInFlatTree(*two, 2, TextAffinity::kUpstream))); - EXPECT_FALSE(IsEndOfLine(CreateVisiblePositionInDOMTree(*two, 2))); + // The result on legacy layout is broken and not worth fixing. + if (LayoutNGEnabled()) + EXPECT_TRUE(IsEndOfLine(CreateVisiblePositionInFlatTree(*two, 2))); + else + EXPECT_FALSE(IsEndOfLine(CreateVisiblePositionInDOMTree(*two, 2))); EXPECT_TRUE(IsEndOfLine(CreateVisiblePositionInFlatTree(*two, 2))); EXPECT_FALSE(IsEndOfLine(CreateVisiblePositionInDOMTree(*three, 3))); @@ -269,14 +262,10 @@ EXPECT_FALSE(IsLogicalEndOfLine(CreateVisiblePositionInFlatTree(*one, 1))); // The result in legacy layout is broken and not worth fixing. - if (LayoutNGEnabled()) { - EXPECT_TRUE(IsLogicalEndOfLine( - CreateVisiblePositionInDOMTree(*two, 2, TextAffinity::kUpstream))); - } else { - EXPECT_FALSE(IsLogicalEndOfLine( - CreateVisiblePositionInDOMTree(*two, 2, TextAffinity::kUpstream))); - } - EXPECT_FALSE(IsLogicalEndOfLine(CreateVisiblePositionInDOMTree(*two, 2))); + if (LayoutNGEnabled()) + EXPECT_TRUE(IsLogicalEndOfLine(CreateVisiblePositionInDOMTree(*two, 2))); + else + EXPECT_FALSE(IsLogicalEndOfLine(CreateVisiblePositionInDOMTree(*two, 2))); EXPECT_TRUE(IsLogicalEndOfLine(CreateVisiblePositionInFlatTree(*two, 2))); EXPECT_FALSE(IsLogicalEndOfLine(CreateVisiblePositionInDOMTree(*three, 3))); @@ -326,25 +315,15 @@ InSameLine(PositionWithAffinityInDOMTree(*two->firstChild(), 0), PositionWithAffinityInDOMTree(*four->firstChild(), 0))); - EXPECT_TRUE(InSameLine( - CreateVisiblePositionInDOMTree(*one, 0), - CreateVisiblePositionInDOMTree(*two, 0, TextAffinity::kUpstream))); - EXPECT_FALSE(InSameLine(CreateVisiblePositionInDOMTree(*one, 0), - CreateVisiblePositionInDOMTree(*two, 0))); - EXPECT_TRUE(InSameLine(CreateVisiblePositionInDOMTree(*one->firstChild(), 0), - CreateVisiblePositionInDOMTree( - *two->firstChild(), 0, TextAffinity::kUpstream))); - EXPECT_FALSE( + EXPECT_TRUE(InSameLine(CreateVisiblePositionInDOMTree(*one, 0), + CreateVisiblePositionInDOMTree(*two, 0))); + EXPECT_TRUE( InSameLine(CreateVisiblePositionInDOMTree(*one->firstChild(), 0), CreateVisiblePositionInDOMTree(*two->firstChild(), 0))); EXPECT_FALSE( InSameLine(CreateVisiblePositionInDOMTree(*one->firstChild(), 0), CreateVisiblePositionInDOMTree(*five->firstChild(), 0))); EXPECT_FALSE( - InSameLine(CreateVisiblePositionInDOMTree(*two->firstChild(), 0, - TextAffinity::kUpstream), - CreateVisiblePositionInDOMTree(*four->firstChild(), 0))); - EXPECT_TRUE( InSameLine(CreateVisiblePositionInDOMTree(*two->firstChild(), 0), CreateVisiblePositionInDOMTree(*four->firstChild(), 0))); @@ -401,9 +380,7 @@ EXPECT_FALSE(IsStartOfLine(CreateVisiblePositionInDOMTree(*two, 0))); EXPECT_FALSE(IsStartOfLine(CreateVisiblePositionInFlatTree(*two, 0))); - EXPECT_FALSE(IsStartOfLine( - CreateVisiblePositionInDOMTree(*three, 0, TextAffinity::kUpstream))); - EXPECT_TRUE(IsStartOfLine(CreateVisiblePositionInDOMTree(*three, 0))); + EXPECT_FALSE(IsStartOfLine(CreateVisiblePositionInDOMTree(*three, 0))); EXPECT_TRUE(IsStartOfLine(CreateVisiblePositionInFlatTree(*three, 0))); EXPECT_FALSE(IsStartOfLine(CreateVisiblePositionInDOMTree(*four, 0))); @@ -458,11 +435,6 @@ .DeepEquivalent()); EXPECT_EQ(Position(seven, 7), - LogicalEndOfLine(CreateVisiblePositionInDOMTree( - *two, 0, TextAffinity::kUpstream)) - .DeepEquivalent()); - // The result on legacy layout is broken and not worth fixing. - EXPECT_EQ(LayoutNGEnabled() ? Position(two, 2) : Position(five, 5), LogicalEndOfLine(CreateVisiblePositionInDOMTree(*two, 0)) .DeepEquivalent()); EXPECT_EQ(PositionInFlatTree(two, 2), @@ -480,10 +452,6 @@ // DOM VisiblePosition canonicalization moves input position to (two, 2), // which yields wrong results in both legacy layout and LayoutNG. EXPECT_EQ(LayoutNGEnabled() ? Position(two, 2) : Position(five, 5), - LogicalEndOfLine(CreateVisiblePositionInDOMTree( - *three, 0, TextAffinity::kUpstream)) - .DeepEquivalent()); - EXPECT_EQ(Position(four, 4), LogicalEndOfLine(CreateVisiblePositionInDOMTree(*three, 0)) .DeepEquivalent()); EXPECT_EQ(PositionInFlatTree(four, 4), @@ -554,10 +522,6 @@ .DeepEquivalent()); EXPECT_EQ(Position(one, 0), - LogicalStartOfLine(CreateVisiblePositionInDOMTree( - *two, 0, TextAffinity::kUpstream)) - .DeepEquivalent()); - EXPECT_EQ(Position(five, 0), LogicalStartOfLine(CreateVisiblePositionInDOMTree(*two, 0)) .DeepEquivalent()); EXPECT_EQ(PositionInFlatTree(five, 0), @@ -572,21 +536,15 @@ .DeepEquivalent()); EXPECT_EQ(Position(five, 0), - LogicalStartOfLine(CreateVisiblePositionInDOMTree( - *three, 0, TextAffinity::kUpstream)) - .DeepEquivalent()); - EXPECT_EQ(Position(three, 0), LogicalStartOfLine(CreateVisiblePositionInDOMTree(*three, 0)) .DeepEquivalent()); EXPECT_EQ(PositionInFlatTree(three, 0), LogicalStartOfLine(CreateVisiblePositionInFlatTree(*three, 1)) .DeepEquivalent()); - EXPECT_EQ(Position(three, 0), - LogicalStartOfLine(CreateVisiblePositionInDOMTree( - *four, 1, TextAffinity::kUpstream)) - .DeepEquivalent()); - EXPECT_EQ(Position(three, 0), + // TODO(yosin) logicalStartOfLine(four, 1) -> (two, 2) is a broken result. + // We keep it as a marker for future change. + EXPECT_EQ(Position(two, 2), LogicalStartOfLine(CreateVisiblePositionInDOMTree(*four, 1)) .DeepEquivalent()); EXPECT_EQ(PositionInFlatTree(three, 0), @@ -653,11 +611,8 @@ PositionInFlatTree(one, 0), StartOfLine(CreateVisiblePositionInFlatTree(*one, 1)).DeepEquivalent()); - EXPECT_EQ(Position(one, 0), StartOfLine(CreateVisiblePositionInDOMTree( - *two, 0, TextAffinity::kUpstream)) - .DeepEquivalent()); EXPECT_EQ( - Position(five, 0), + Position(one, 0), StartOfLine(CreateVisiblePositionInDOMTree(*two, 0)).DeepEquivalent()); EXPECT_EQ( PositionInFlatTree(five, 0), @@ -670,23 +625,17 @@ PositionInFlatTree(five, 0), StartOfLine(CreateVisiblePositionInFlatTree(*two, 1)).DeepEquivalent()); - EXPECT_EQ(Position(five, 0), - StartOfLine(CreateVisiblePositionInDOMTree(*three, 0, - TextAffinity::kUpstream)) - .DeepEquivalent()); EXPECT_EQ( - Position(three, 0), + Position(five, 0), StartOfLine(CreateVisiblePositionInDOMTree(*three, 0)).DeepEquivalent()); EXPECT_EQ( PositionInFlatTree(three, 0), StartOfLine(CreateVisiblePositionInFlatTree(*three, 1)).DeepEquivalent()); - EXPECT_EQ(Position(three, 0), - StartOfLine(CreateVisiblePositionInDOMTree(*four, 1, - TextAffinity::kUpstream)) - .DeepEquivalent()); + // TODO(yosin) startOfLine(four, 1) -> (two, 2) is a broken result. We keep + // it as a marker for future change. EXPECT_EQ( - Position(three, 0), + Position(two, 2), StartOfLine(CreateVisiblePositionInDOMTree(*four, 1)).DeepEquivalent()); EXPECT_EQ( PositionInFlatTree(three, 0),
diff --git a/third_party/blink/renderer/core/editing/visible_units_paragraph.cc b/third_party/blink/renderer/core/editing/visible_units_paragraph.cc index 03ad84b..2c8f3a3a 100644 --- a/third_party/blink/renderer/core/editing/visible_units_paragraph.cc +++ b/third_party/blink/renderer/core/editing/visible_units_paragraph.cc
@@ -147,10 +147,8 @@ const VisiblePositionTemplate<Strategy>& visible_position, EditingBoundaryCrossingRule boundary_crossing_rule) { DCHECK(visible_position.IsValid()) << visible_position; - return CreateVisiblePosition( - StartOfParagraphAlgorithm(visible_position.DeepEquivalent(), - boundary_crossing_rule), - TextAffinity::kDownstream); + return CreateVisiblePosition(StartOfParagraphAlgorithm( + visible_position.DeepEquivalent(), boundary_crossing_rule)); } template <typename Strategy> @@ -247,10 +245,8 @@ const VisiblePositionTemplate<Strategy>& visible_position, EditingBoundaryCrossingRule boundary_crossing_rule) { DCHECK(visible_position.IsValid()) << visible_position; - return CreateVisiblePosition( - EndOfParagraphAlgorithm(visible_position.DeepEquivalent(), - boundary_crossing_rule), - TextAffinity::kUpstream); + return CreateVisiblePosition(EndOfParagraphAlgorithm( + visible_position.DeepEquivalent(), boundary_crossing_rule)); } template <typename Strategy>
diff --git a/third_party/blink/renderer/core/editing/visible_units_test.cc b/third_party/blink/renderer/core/editing/visible_units_test.cc index aa3a50f..69ef2db 100644 --- a/third_party/blink/renderer/core/editing/visible_units_test.cc +++ b/third_party/blink/renderer/core/editing/visible_units_test.cc
@@ -113,66 +113,25 @@ EXPECT_EQ(Position(), CanonicalPositionOf(Position(GetDocument().documentElement(), 0))); - EXPECT_EQ( - Position(), - SnapBackward(Position(GetDocument().documentElement(), 0)).GetPosition()); - EXPECT_EQ( - Position(), - SnapForward(Position(GetDocument().documentElement(), 0)).GetPosition()); EXPECT_EQ(Position(one->firstChild(), 0), CanonicalPositionOf(Position(one, 0))); - EXPECT_EQ(Position(one->firstChild(), 0), - SnapBackward(Position(one, 0)).GetPosition()); - EXPECT_EQ(Position(one->firstChild(), 0), - SnapForward(Position(one, 0)).GetPosition()); - EXPECT_EQ(Position(one->firstChild(), 1), CanonicalPositionOf(Position(one, 1))); - EXPECT_EQ(Position(one->firstChild(), 1), - SnapBackward(Position(one, 1)).GetPosition()); - EXPECT_EQ(Position(one->firstChild(), 1), - SnapForward(Position(one, 1)).GetPosition()); EXPECT_EQ(Position(one->firstChild(), 0), CanonicalPositionOf(Position(one->firstChild(), 0))); - EXPECT_EQ(Position(one->firstChild(), 0), - SnapBackward(Position(one->firstChild(), 0)).GetPosition()); - EXPECT_EQ(Position(one->firstChild(), 0), - SnapForward(Position(one->firstChild(), 0)).GetPosition()); - EXPECT_EQ(Position(one->firstChild(), 1), CanonicalPositionOf(Position(one->firstChild(), 1))); - EXPECT_EQ(Position(one->firstChild(), 1), - SnapBackward(Position(one->firstChild(), 1)).GetPosition()); - EXPECT_EQ(Position(one->firstChild(), 1), - SnapForward(Position(one->firstChild(), 1)).GetPosition()); EXPECT_EQ(Position(html, 0), CanonicalPositionOf(Position(html, 0))); - EXPECT_EQ(Position(html, 0), SnapBackward(Position(html, 0)).GetPosition()); - EXPECT_EQ(Position(html, 0), SnapForward(Position(html, 0)).GetPosition()); - EXPECT_EQ(Position(html, 1), CanonicalPositionOf(Position(html, 1))); - EXPECT_EQ(Position(html, 1), SnapBackward(Position(html, 1)).GetPosition()); - EXPECT_EQ(Position(html, 1), SnapForward(Position(html, 1)).GetPosition()); - EXPECT_EQ(Position(html, 2), CanonicalPositionOf(Position(html, 2))); - EXPECT_EQ(Position(html, 2), SnapBackward(Position(html, 2)).GetPosition()); - EXPECT_EQ(Position(html, 2), SnapForward(Position(html, 2)).GetPosition()); EXPECT_EQ(Position(two->firstChild(), 0), CanonicalPositionOf(Position(two, 0))); - EXPECT_EQ(Position(two->firstChild(), 0), - SnapBackward(Position(two, 0)).GetPosition()); - EXPECT_EQ(Position(two->firstChild(), 0), - SnapForward(Position(two, 0)).GetPosition()); - EXPECT_EQ(Position(two->firstChild(), 2), CanonicalPositionOf(Position(two, 1))); - EXPECT_EQ(Position(two->firstChild(), 2), - SnapBackward(Position(two, 1)).GetPosition()); - EXPECT_EQ(Position(two->firstChild(), 2), - SnapForward(Position(two, 1)).GetPosition()); } // For http://crbug.com/695317 @@ -180,20 +139,13 @@ SetBodyContent("<input>123"); Element* const input = GetDocument().QuerySelector("input"); - Position position = - Position::FirstPositionInNode(*GetDocument().documentElement()); - EXPECT_EQ(Position::BeforeNode(*input), CanonicalPositionOf(position)); - EXPECT_EQ(Position::BeforeNode(*input), SnapBackward(position).GetPosition()); - EXPECT_EQ(Position::BeforeNode(*input), SnapForward(position).GetPosition()); + EXPECT_EQ(Position::BeforeNode(*input), + CanonicalPositionOf(Position::FirstPositionInNode( + *GetDocument().documentElement()))); - PositionInFlatTree pos_in_flat_tree = - PositionInFlatTree::FirstPositionInNode(*GetDocument().documentElement()); EXPECT_EQ(PositionInFlatTree::BeforeNode(*input), - CanonicalPositionOf(pos_in_flat_tree)); - EXPECT_EQ(PositionInFlatTree::BeforeNode(*input), - SnapBackward(pos_in_flat_tree).GetPosition()); - EXPECT_EQ(PositionInFlatTree::BeforeNode(*input), - SnapForward(pos_in_flat_tree).GetPosition()); + CanonicalPositionOf(PositionInFlatTree::FirstPositionInNode( + *GetDocument().documentElement()))); } TEST_F(VisibleUnitsTest, characterBefore) { @@ -805,12 +757,8 @@ Node* paragraph = GetDocument().QuerySelector("p"); Node* text = paragraph->firstChild(); - EXPECT_EQ(Position(text, 2), - CanonicalPositionOf(Position::BeforeNode(*paragraph))); - EXPECT_EQ(Position(text, 2), - SnapBackward(Position::BeforeNode(*paragraph)).GetPosition()); - EXPECT_EQ(Position(text, 2), - SnapForward(Position::BeforeNode(*paragraph)).GetPosition()); + Position start = CanonicalPositionOf(Position::BeforeNode(*paragraph)); + EXPECT_EQ(Position(text, 2), start); } TEST_F(VisibleUnitsTest, MostForwardCaretPositionWithInvisibleFirstLetter) {
diff --git a/third_party/blink/renderer/core/editing/visible_units_word_test.cc b/third_party/blink/renderer/core/editing/visible_units_word_test.cc index 343fde7..2dc0001e 100644 --- a/third_party/blink/renderer/core/editing/visible_units_word_test.cc +++ b/third_party/blink/renderer/core/editing/visible_units_word_test.cc
@@ -233,13 +233,8 @@ StartOfWordPosition( CreateVisiblePositionInFlatTree(*two, 1).DeepEquivalent())) .DeepEquivalent()); - EXPECT_EQ(Position(three, 0), - CreateVisiblePosition( - StartOfWordPosition(CreateVisiblePositionInDOMTree( - *three, 1, TextAffinity::kUpstream) - .DeepEquivalent())) - .DeepEquivalent()); - EXPECT_EQ(Position(three, 0), + // DOM tree canonicalization moves the result to a wrong position. + EXPECT_EQ(Position(two, 2), CreateVisiblePosition( StartOfWordPosition( CreateVisiblePositionInDOMTree(*three, 1).DeepEquivalent()))
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc index 9503246..e146da4 100644 --- a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc +++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
@@ -43,6 +43,7 @@ #include "third_party/blink/public/common/privacy_budget/identifiability_metric_builder.h" #include "third_party/blink/public/common/privacy_budget/identifiability_metrics.h" #include "third_party/blink/public/common/privacy_budget/identifiability_study_participation.h" +#include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h" #include "third_party/blink/public/common/privacy_budget/identifiable_surface.h" #include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h" #include "third_party/blink/public/mojom/gpu/gpu.mojom-blink.h" @@ -315,6 +316,17 @@ const CanvasContextCreationAttributesCore& attributes) { auto* old_contents_cc_layer = ContentsCcLayer(); auto* result = GetCanvasRenderingContextInternal(type, attributes); + + if (ukm_params_ && IdentifiabilityStudySettings::Get()->IsTypeAllowed( + IdentifiableSurface::Type::kCanvasRenderingContext)) { + IdentifiabilityMetricBuilder(ukm_params_->source_id) + .Set(IdentifiableSurface::FromTypeAndToken( + IdentifiableSurface::Type::kCanvasRenderingContext, + CanvasRenderingContext::ContextTypeFromId(type)), + !!result) + .Record(ukm_params_->ukm_recorder); + } + if (ContentsCcLayer() != old_contents_cc_layer) OnContentsCcLayerChanged(); return result; @@ -333,13 +345,6 @@ // Log the aliased context type used. if (!context_) { - if (IsUserInIdentifiabilityStudy()) { - RecordIdentifiabilityMetric( - IdentifiableSurface::FromTypeAndToken( - blink::IdentifiableSurface::Type::kWebFeature, - blink::WebFeature::kCanvasRenderingContext), - context_type); - } UMA_HISTOGRAM_ENUMERATION("Blink.Canvas.ContextType", context_type); }
diff --git a/third_party/blink/renderer/modules/BUILD.gn b/third_party/blink/renderer/modules/BUILD.gn index 694ff382..92e39b8d 100644 --- a/third_party/blink/renderer/modules/BUILD.gn +++ b/third_party/blink/renderer/modules/BUILD.gn
@@ -213,12 +213,6 @@ "netinfo/testing/internals_net_info.h", "peerconnection/adapters/test/mock_ice_transport_adapter.h", "peerconnection/adapters/test/mock_ice_transport_adapter_cross_thread_factory.h", - "peerconnection/adapters/test/mock_p2p_quic_packet_transport.h", - "peerconnection/adapters/test/mock_p2p_quic_stream.h", - "peerconnection/adapters/test/mock_p2p_quic_stream_delegate.h", - "peerconnection/adapters/test/mock_p2p_quic_transport.h", - "peerconnection/adapters/test/mock_p2p_quic_transport_delegate.h", - "peerconnection/adapters/test/mock_p2p_quic_transport_factory.h", "peerconnection/testing/fake_resource_listener.cc", "peerconnection/testing/fake_resource_listener.h", "peerconnection/testing/internals_rtc_certificate.cc", @@ -394,9 +388,6 @@ "payments/payment_test_helper.cc", "payments/payment_test_helper.h", "payments/payments_validators_test.cc", - "peerconnection/adapters/p2p_quic_stream_unittest.cc", - "peerconnection/adapters/p2p_quic_transport_test.cc", - "peerconnection/adapters/quic_packet_transport_adapter_test.cc", "peerconnection/byte_buffer_queue_test.cc", "peerconnection/call_setup_state_tracker_unittest.cc", "peerconnection/media_stream_remote_video_source_test.cc", @@ -413,9 +404,6 @@ "peerconnection/rtc_ice_transport_test.h", "peerconnection/rtc_peer_connection_handler_test.cc", "peerconnection/rtc_peer_connection_test.cc", - "peerconnection/rtc_quic_stream_test.cc", - "peerconnection/rtc_quic_transport_test.cc", - "peerconnection/rtc_quic_transport_test.h", "peerconnection/rtc_rtp_receiver_impl_test.cc", "peerconnection/rtc_rtp_sender_impl_test.cc", "peerconnection/rtc_rtp_transceiver_impl_test.cc", @@ -502,7 +490,6 @@ "//media/mojo/mojom", "//media/webrtc:webrtc", "//mojo/public/cpp/bindings", - "//net:quic_test_tools", "//net:test_support", "//services/device/public/cpp:test_support", "//skia",
diff --git a/third_party/blink/renderer/modules/peerconnection/BUILD.gn b/third_party/blink/renderer/modules/peerconnection/BUILD.gn index c4651cf..039fdaf 100644 --- a/third_party/blink/renderer/modules/peerconnection/BUILD.gn +++ b/third_party/blink/renderer/modules/peerconnection/BUILD.gn
@@ -16,34 +16,6 @@ "adapters/ice_transport_host.h", "adapters/ice_transport_proxy.cc", "adapters/ice_transport_proxy.h", - "adapters/p2p_quic_crypto_config_factory.h", - "adapters/p2p_quic_crypto_config_factory_impl.cc", - "adapters/p2p_quic_crypto_config_factory_impl.h", - "adapters/p2p_quic_crypto_stream_factory.h", - "adapters/p2p_quic_crypto_stream_factory_impl.cc", - "adapters/p2p_quic_crypto_stream_factory_impl.h", - "adapters/p2p_quic_packet_transport.h", - "adapters/p2p_quic_stream.h", - "adapters/p2p_quic_stream_impl.cc", - "adapters/p2p_quic_stream_impl.h", - "adapters/p2p_quic_transport.h", - "adapters/p2p_quic_transport_factory.h", - "adapters/p2p_quic_transport_factory_impl.cc", - "adapters/p2p_quic_transport_factory_impl.h", - "adapters/p2p_quic_transport_impl.cc", - "adapters/p2p_quic_transport_impl.h", - "adapters/p2p_quic_transport_stats.cc", - "adapters/p2p_quic_transport_stats.h", - "adapters/quic_packet_transport_adapter.cc", - "adapters/quic_packet_transport_adapter.h", - "adapters/quic_stream_host.cc", - "adapters/quic_stream_host.h", - "adapters/quic_stream_proxy.cc", - "adapters/quic_stream_proxy.h", - "adapters/quic_transport_host.cc", - "adapters/quic_transport_host.h", - "adapters/quic_transport_proxy.cc", - "adapters/quic_transport_proxy.h", "adapters/sctp_transport_proxy.cc", "adapters/sctp_transport_proxy.h", "adapters/web_rtc_cross_thread_copier.cc", @@ -114,12 +86,6 @@ "rtc_peer_connection_ice_error_event.h", "rtc_peer_connection_ice_event.cc", "rtc_peer_connection_ice_event.h", - "rtc_quic_stream.cc", - "rtc_quic_stream.h", - "rtc_quic_stream_event.cc", - "rtc_quic_stream_event.h", - "rtc_quic_transport.cc", - "rtc_quic_transport.h", "rtc_rtp_receiver.cc", "rtc_rtp_receiver.h", "rtc_rtp_receiver_impl.cc",
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter.h b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter.h index 7b0e6ca..f368a99 100644 --- a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter.h +++ b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter.h
@@ -12,8 +12,6 @@ namespace blink { -class P2PQuicPacketTransport; - // Defines the ICE candidate policy the browser uses to surface the permitted // candidates to the application. // https://w3c.github.io/webrtc-pc/#dom-rtcicetransportpolicy @@ -83,10 +81,6 @@ // Adds a remote candidate to potentially start connectivity checks with. // The caller must ensure Start() has already bene called. virtual void AddRemoteCandidate(const cricket::Candidate& candidate) = 0; - - // Gets a P2PQuicPacketTransport that is backed by this ICE connection. The - // returned instance lives the same lifetime as the IceTransportAdapter. - virtual P2PQuicPacketTransport* packet_transport() const = 0; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter_impl.cc b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter_impl.cc index 3214883..7f0bb03 100644 --- a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter_impl.cc +++ b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter_impl.cc
@@ -7,7 +7,6 @@ #include <utility> #include "base/notreached.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/quic_packet_transport_adapter.h" #include "third_party/webrtc/api/ice_transport_factory.h" namespace blink { @@ -43,9 +42,6 @@ // generated so that each peer can calculate a.tiebreaker <= b.tiebreaker // consistently. ice_transport_channel()->SetIceTiebreaker(rtc::CreateRandomId64()); - - quic_packet_transport_adapter_ = - std::make_unique<QuicPacketTransportAdapter>(ice_transport_channel()); } IceTransportAdapterImpl::IceTransportAdapterImpl( @@ -131,10 +127,6 @@ ice_transport_channel()->AddRemoteCandidate(candidate); } -P2PQuicPacketTransport* IceTransportAdapterImpl::packet_transport() const { - return quic_packet_transport_adapter_.get(); -} - void IceTransportAdapterImpl::SetupIceTransportChannel() { if (!ice_transport_channel()) { LOG(ERROR) << "SetupIceTransportChannel called, but ICE transport released";
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter_impl.h b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter_impl.h index be28c9a6..558f229 100644 --- a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter_impl.h +++ b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter_impl.h
@@ -26,8 +26,8 @@ std::unique_ptr<webrtc::AsyncResolverFactory> async_resolver_factory); // Create an IceTransportAdapter for an existing |ice_transport_channel| - // object. In this case, |port_allocator_|, |async_resolver_factory_| and - // |quic_packet_transport_adapter_| are not used (and null). + // object. In this case, |port_allocator_|, |async_resolver_factory_| is not + // used (and null). IceTransportAdapterImpl( Delegate* delegate, rtc::scoped_refptr<webrtc::IceTransportInterface> ice_transport_channel); @@ -46,7 +46,6 @@ void HandleRemoteRestart( const cricket::IceParameters& new_remote_parameters) override; void AddRemoteCandidate(const cricket::Candidate& candidate) override; - P2PQuicPacketTransport* packet_transport() const override; private: cricket::IceTransportInternal* ice_transport_channel() { @@ -66,7 +65,6 @@ std::unique_ptr<cricket::PortAllocator> port_allocator_; std::unique_ptr<webrtc::AsyncResolverFactory> async_resolver_factory_; rtc::scoped_refptr<webrtc::IceTransportInterface> ice_transport_channel_; - std::unique_ptr<P2PQuicPacketTransport> quic_packet_transport_adapter_; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_config_factory.h b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_config_factory.h deleted file mode 100644 index fb37bf0..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_config_factory.h +++ /dev/null
@@ -1,33 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_P2P_QUIC_CRYPTO_CONFIG_FACTORY_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_P2P_QUIC_CRYPTO_CONFIG_FACTORY_H_ - -#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h" -#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h" - -namespace blink { - -// Builds the crypto configurations to be used by the P2PQuicTransport. -class P2PQuicCryptoConfigFactory { - public: - virtual ~P2PQuicCryptoConfigFactory() = default; - - // Creates the client crypto configuration to be used by a - // quic::QuicCryptoClientStream. This includes a ProofVerifier object that - // verifies the server's certificate and is used in the QUIC handshake. - virtual std::unique_ptr<quic::QuicCryptoClientConfig> - CreateClientCryptoConfig() = 0; - - // Creates the server crypto configuration to be used by a - // quic::QuicCryptoServerStream. This includes a ProofSource object that gives - // the server's certificate. - virtual std::unique_ptr<quic::QuicCryptoServerConfig> - CreateServerCryptoConfig() = 0; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_P2P_QUIC_CRYPTO_CONFIG_FACTORY_H_
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_config_factory_impl.cc b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_config_factory_impl.cc deleted file mode 100644 index 5af9c17..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_config_factory_impl.cc +++ /dev/null
@@ -1,140 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/third_party/quiche/src/quic/core/crypto/proof_source.h" -#include "net/third_party/quiche/src/quic/core/crypto/proof_verifier.h" - -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_config_factory_impl.h" - -namespace blink { - -namespace { - -// Length of HKDF input keying material, equal to its number of bytes. -// https://tools.ietf.org/html/rfc5869#section-2.2. -const size_t kInputKeyingMaterialLength = 32; - -// TODO(https://crbug.com/874300): Implement a secure QUIC handshake, meaning -// that both side's certificates are verified. This can be done by creating a -// P2PProofSource and P2PProofVerifier, and removing these objects once the -// TLS 1.3 handshake is implemented for QUIC. -// - The self signed certificate fingerprint matches the remote -// fingerprint that was signaled. -// - The peer owns the certificate, by verifying the signature of the hash of -// the handshake context. -// -// Ignores the peer's credentials (taken from quic/quartc). -class InsecureProofVerifier : public quic::ProofVerifier { - public: - InsecureProofVerifier() {} - ~InsecureProofVerifier() override {} - - // ProofVerifier override. - quic::QuicAsyncStatus VerifyProof( - const std::string& hostname, - const uint16_t port, - const std::string& server_config, - quic::QuicTransportVersion transport_version, - quiche::QuicheStringPiece chlo_hash, - const std::vector<std::string>& certs, - const std::string& cert_sct, - const std::string& signature, - const quic::ProofVerifyContext* context, - std::string* error_details, - std::unique_ptr<quic::ProofVerifyDetails>* verify_details, - std::unique_ptr<quic::ProofVerifierCallback> callback) override { - return quic::QUIC_SUCCESS; - } - - quic::QuicAsyncStatus VerifyCertChain( - const std::string& hostname, - const uint16_t port, - const std::vector<std::string>& certs, - const std::string& ocsp_response, - const std::string& cert_sct, - const quic::ProofVerifyContext* context, - std::string* error_details, - std::unique_ptr<quic::ProofVerifyDetails>* details, - std::unique_ptr<quic::ProofVerifierCallback> callback) override { - return quic::QUIC_SUCCESS; - } - - std::unique_ptr<quic::ProofVerifyContext> CreateDefaultContext() override { - return nullptr; - } -}; - -} // namespace - -// Used by QuicCryptoServerConfig to provide dummy proof credentials -// (taken from quic/quartc). -class DummyProofSource : public quic::ProofSource { - public: - DummyProofSource() {} - ~DummyProofSource() override {} - - // ProofSource override. - void GetProof(const quic::QuicSocketAddress& server_addr, - const quic::QuicSocketAddress& client_addr, - const std::string& hostname, - const std::string& server_config, - quic::QuicTransportVersion transport_version, - quiche::QuicheStringPiece chlo_hash, - std::unique_ptr<Callback> callback) override { - quic::QuicCryptoProof proof; - proof.signature = "Dummy signature"; - proof.leaf_cert_scts = "Dummy timestamp"; - callback->Run(true, GetCertChain(server_addr, client_addr, hostname), proof, - nullptr /* details */); - } - - quic::QuicReferenceCountedPointer<Chain> GetCertChain( - const quic::QuicSocketAddress& server_address, - const quic::QuicSocketAddress& client_address, - const std::string& hostname) override { - std::vector<std::string> certs; - certs.push_back("Dummy cert"); - return quic::QuicReferenceCountedPointer<Chain>( - new quic::ProofSource::Chain(certs)); - } - void ComputeTlsSignature( - const quic::QuicSocketAddress& server_address, - const quic::QuicSocketAddress& client_address, - const std::string& hostname, - uint16_t signature_algorithm, - quiche::QuicheStringPiece in, - std::unique_ptr<SignatureCallback> callback) override { - callback->Run(true, "Dummy signature", nullptr); - } - - TicketCrypter* GetTicketCrypter() override { return nullptr; } -}; - -P2PQuicCryptoConfigFactoryImpl::P2PQuicCryptoConfigFactoryImpl( - quic::QuicRandom* const random_generator) - : random_generator_(random_generator) {} - -std::unique_ptr<quic::QuicCryptoClientConfig> -P2PQuicCryptoConfigFactoryImpl::CreateClientCryptoConfig() { - std::unique_ptr<quic::ProofVerifier> proof_verifier( - new InsecureProofVerifier); - return std::make_unique<quic::QuicCryptoClientConfig>( - std::move(proof_verifier)); -} - -std::unique_ptr<quic::QuicCryptoServerConfig> -P2PQuicCryptoConfigFactoryImpl::CreateServerCryptoConfig() { - // Generate a random source address token secret every time since this is - // a transient client. - char source_address_token_secret[kInputKeyingMaterialLength]; - random_generator_->RandBytes(source_address_token_secret, - kInputKeyingMaterialLength); - std::unique_ptr<quic::ProofSource> proof_source(new DummyProofSource); - return std::make_unique<quic::QuicCryptoServerConfig>( - std::string(source_address_token_secret, kInputKeyingMaterialLength), - random_generator_, std::move(proof_source), - quic::KeyExchangeSource::Default()); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_config_factory_impl.h b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_config_factory_impl.h deleted file mode 100644 index 349a6690..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_config_factory_impl.h +++ /dev/null
@@ -1,43 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_P2P_QUIC_CRYPTO_CONFIG_FACTORY_IMPL_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_P2P_QUIC_CRYPTO_CONFIG_FACTORY_IMPL_H_ - -#include "net/third_party/quiche/src/quic/core/crypto/proof_source.h" -#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h" -#include "third_party/blink/renderer/modules/modules_export.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_config_factory.h" -#include "third_party/webrtc/rtc_base/rtc_certificate.h" - -namespace blink { - -// An abstraction for building the crypto configurations to be used by the -// P2PQuicTransport. -class MODULES_EXPORT P2PQuicCryptoConfigFactoryImpl final - : public P2PQuicCryptoConfigFactory { - public: - P2PQuicCryptoConfigFactoryImpl( - quic::QuicRandom* const random_generator); - - ~P2PQuicCryptoConfigFactoryImpl() override {} - - // P2PQuicCryptoConfigFactory overrides. - // - // Creates a client config that accepts any remote certificate. - std::unique_ptr<quic::QuicCryptoClientConfig> CreateClientCryptoConfig() - override; - // Creates a server config with a DummyProofSource. - std::unique_ptr<quic::QuicCryptoServerConfig> CreateServerCryptoConfig() - override; - - private: - // TODO(crbug.com/874296): Add certificate(s) to create a proof source - // that comes from the self signed certificate given to the RTCQuicTransport. - quic::QuicRandom* const random_generator_; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_P2P_QUIC_CRYPTO_CONFIG_FACTORY_IMPL_H_
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_stream_factory.h b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_stream_factory.h deleted file mode 100644 index c4516cf..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_stream_factory.h +++ /dev/null
@@ -1,34 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_P2P_QUIC_CRYPTO_STREAM_FACTORY_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_P2P_QUIC_CRYPTO_STREAM_FACTORY_H_ - -#include "net/third_party/quiche/src/quic/core/quic_crypto_client_stream.h" -#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream_base.h" - -namespace blink { - -// Builds the crypto stream to be used by the P2PQuicTransport. -class P2PQuicCryptoStreamFactory { - public: - virtual ~P2PQuicCryptoStreamFactory() = default; - - virtual std::unique_ptr<quic::QuicCryptoClientStream> - CreateClientCryptoStream( - quic::QuicSession* session, - quic::QuicCryptoClientConfig* crypto_config, - quic::QuicCryptoClientStream::ProofHandler* proof_handler) = 0; - - virtual std::unique_ptr<quic::QuicCryptoServerStreamBase> - CreateServerCryptoStream( - const quic::QuicCryptoServerConfig* crypto_config, - quic::QuicCompressedCertsCache* compressed_certs_cache, - quic::QuicSession* session, - quic::QuicCryptoServerStreamBase::Helper* helper) = 0; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_P2P_QUIC_CRYPTO_STREAM_FACTORY_H_
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_stream_factory_impl.cc b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_stream_factory_impl.cc deleted file mode 100644 index 29550e82..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_stream_factory_impl.cc +++ /dev/null
@@ -1,37 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_stream_factory_impl.h" -#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream_base.h" - -namespace blink { - -std::unique_ptr<quic::QuicCryptoClientStream> -P2PQuicCryptoStreamFactoryImpl::CreateClientCryptoStream( - quic::QuicSession* session, - quic::QuicCryptoClientConfig* crypto_config, - quic::QuicCryptoClientStream::ProofHandler* proof_handler) { - // The QuicServerId is not important since we are communicating with a peer - // endpoint and the connection is on top of ICE. - quic::QuicServerId server_id( - /*host=*/"", - /*port=*/0, - /*privacy_mode_enabled=*/false); - return std::make_unique<quic::QuicCryptoClientStream>( - server_id, session, - crypto_config->proof_verifier()->CreateDefaultContext(), crypto_config, - proof_handler, /*has_application_state = */ true); -} - -std::unique_ptr<quic::QuicCryptoServerStreamBase> -P2PQuicCryptoStreamFactoryImpl::CreateServerCryptoStream( - const quic::QuicCryptoServerConfig* crypto_config, - quic::QuicCompressedCertsCache* compressed_certs_cache, - quic::QuicSession* session, - quic::QuicCryptoServerStreamBase::Helper* helper) { - return quic::CreateCryptoServerStream(crypto_config, compressed_certs_cache, - session, helper); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_stream_factory_impl.h b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_stream_factory_impl.h deleted file mode 100644 index e5ef3fa..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_stream_factory_impl.h +++ /dev/null
@@ -1,36 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_P2P_QUIC_CRYPTO_STREAM_FACTORY_IMPL_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_P2P_QUIC_CRYPTO_STREAM_FACTORY_IMPL_H_ - -#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream_base.h" -#include "third_party/blink/renderer/modules/modules_export.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_stream_factory.h" - -namespace blink { - -// The default factory for creating crypto streams to be used by the -// P2PQuicTransport. -class MODULES_EXPORT P2PQuicCryptoStreamFactoryImpl final - : public P2PQuicCryptoStreamFactory { - public: - ~P2PQuicCryptoStreamFactoryImpl() override {} - - // P2PQuicCryptoStreamFactory overrides. - std::unique_ptr<quic::QuicCryptoClientStream> CreateClientCryptoStream( - quic::QuicSession* session, - quic::QuicCryptoClientConfig* crypto_config, - quic::QuicCryptoClientStream::ProofHandler* proof_handler) override; - - std::unique_ptr<quic::QuicCryptoServerStreamBase> CreateServerCryptoStream( - const quic::QuicCryptoServerConfig* crypto_config, - quic::QuicCompressedCertsCache* compressed_certs_cache, - quic::QuicSession* session, - quic::QuicCryptoServerStreamBase::Helper* helper) override; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_P2P_QUIC_CRYPTO_STREAM_FACTORY_IMPL_H_
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_packet_transport.h b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_packet_transport.h deleted file mode 100644 index 9157ce8..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_packet_transport.h +++ /dev/null
@@ -1,69 +0,0 @@ -// Copyright 2018 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_PEERCONNECTION_ADAPTERS_P2P_QUIC_PACKET_TRANSPORT_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_P2P_QUIC_PACKET_TRANSPORT_H_ - -#include "net/third_party/quiche/src/quic/core/quic_packet_writer.h" -#include "net/third_party/quiche/src/quic/core/quic_types.h" -#include "net/third_party/quiche/src/quic/platform/api/quic_export.h" - -namespace blink { - -// This is the interface for the underlying packet transport used by the -// P2PQuicTransport for receiving and writing data. The standard -// implementation of this interface uses an ICE transport. -// -// This object should be run entirely on the webrtc worker thread. -class P2PQuicPacketTransport { - public: - // This is subclassed by the P2PQuicTransport so that it can receive incoming - // data. The standard case is for this to be the P2PQuicTransport. - // The P2PQuicPacketTransport will outlive the ReceiveDelegate. - class ReceiveDelegate { - public: - virtual ~ReceiveDelegate() = default; - virtual void OnPacketDataReceived(const char* data, size_t data_len) = 0; - }; - - // This is subclassed by the Writer, so that it is aware when the - // P2PQuicPacketTransport is ready to write data. The - // P2PQuicPacketTransport will outlive the WriteObserver. - class WriteObserver { - public: - virtual ~WriteObserver() = default; - virtual void OnCanWrite() = 0; - }; - - struct QuicPacket { - // This is taken from the quic::QuicConnection, and 0 means that it is not - // set. Packet numbers are used to provide metadata to the implementation of - // the P2PQuicPacketTransport, but this number is not used by the QUIC - // library itself. - uint64_t packet_number; - const char* buffer; - size_t buf_len; - }; - - virtual ~P2PQuicPacketTransport() = default; - - // Called by the P2PQuicPacketWriter (in quic_transport_factory_impl.cc) when - // writing QUIC packets to the network. Return the number of written bytes. - // Return 0 if the write is blocked. - virtual int WritePacket(const QuicPacket& packet) = 0; - // Sets the ReceiveDelegate for receiving packets. - // Since the ReceiveDelegate has a shorter lifetime than the - // P2PQuicPacketTransport, it must unset itself upon destruction. - virtual void SetReceiveDelegate(ReceiveDelegate* receive_delegate) = 0; - // Sets the WriteObserver for obsererving when it can write to the - // P2PQuicPacketTransport. Since the WriteObserver has a shorter lifetime than - // the P2PQuicPacketTransport, it must unset itself upon destruction. - virtual void SetWriteObserver(WriteObserver* write_observer) = 0; - // Returns true if the P2PQuicPacketTransport can write. - virtual bool Writable() = 0; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_P2P_QUIC_PACKET_TRANSPORT_H_
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream.h b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream.h deleted file mode 100644 index c3ce1dfe..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream.h +++ /dev/null
@@ -1,87 +0,0 @@ -// Copyright 2018 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_PEERCONNECTION_ADAPTERS_P2P_QUIC_STREAM_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_P2P_QUIC_STREAM_H_ - -#include <stdint.h> - -#include "third_party/blink/renderer/platform/wtf/vector.h" - -namespace blink { - -// The bidirectional QUIC stream object to be used by the RTCQuicStream Web -// API. See: https://w3c.github.io/webrtc-quic/#quicstream* -// -// Lifetime: The P2PQuicStream is owned by the P2PQuicTransport, and can be -// deleted after the stream is closed for reading and writing. This can happen -// in 3 ways: 1) OnRemoteReset has been fired. 2) Calling Reset(). 3) Both -// a FIN bit has been sent with WriteData(_, true) and OnRemoteFinish has been -// fired. -class P2PQuicStream { - public: - // Receives callbacks for receiving RST_STREAM frames or a STREAM_FRAME with - // the FIN bit set. The Delegate should be subclassed by an object that can - // post the task to the main JS thread. The delegate's lifetime should outlive - // this P2PQuicStream. - class Delegate { - public: - virtual ~Delegate() {} - - // Called when the stream receives a RST_STREAM frame from the remote side. - // This means the stream is closed and can no longer read or write, and is - // deleted by the quic::QuicSession. - virtual void OnRemoteReset() {} - - // Called when the P2PQuicStream has received data from the remote side. - // If |fin| is set to true that means that the FIN bit has been received - // and the Delegate will no longer receive data with OnDataReceived. - // If the stream has already finished writing, then upon receiving the FIN - // bit the stream can no longer read or write and is deleted by the - // quic::QuicSession. - virtual void OnDataReceived(Vector<uint8_t> data, bool fin) {} - - // Called when data written with WriteData() has been consumed by QUIC. - // - // This will happen immediately after calling WriteData(), unless QUIC has - // buffered the data in which case it will be fired when the stream is no - // longer write blocked and the data is consumed. |amount| specifies how - // much data was consumed in bytes. - virtual void OnWriteDataConsumed(uint32_t amount) {} - }; - - virtual ~P2PQuicStream() = default; - - // Sends a RST_STREAM frame to the remote side. This closes the P2PQuicStream - // for reading & writing and it will be deleted by the quic::QuicSession. When - // the remote side receives the RST_STREAM frame it will close the stream for - // reading and writing and send a RST_STREAM frame back. Calling Reset() will - // not trigger OnRemoteReset to be called locally when the RST_STREAM frame is - // received from the remote side, because the local stream is already closed. - virtual void Reset() = 0; - - // Marks received data of size |amount| as being consumed by the Delegate. - // This is used in conjuction with Delegate::OnDataReceived, to let the - // P2PQuicStream know that received data has been consumed. This allows the - // P2PQuicStream to send back pressure to the send side, if the Delegate - // cannot receive more data. - virtual void MarkReceivedDataConsumed(uint32_t amount) = 0; - - // Writes |data| to a STREAM frame and gives it to QUIC to be buffered or sent - // to the remote endpoint. Once that data has been sent Delegate::OnDataSent() - // will be fired. Specifying |fin| to true will mark the STREAM frame with the - // FIN bit set, which notifies the remote side that this stream is done - // writing. After sending the FIN bit, the P2PQuicStream can no longer write. - // Once the P2PQuicStream has sent AND received the FIN bit it will be closed - // for reading and writing and deleted by the quic::QuicSession. - virtual void WriteData(Vector<uint8_t> data, bool fin) = 0; - - // Sets the delegate object. In the case that the Delegate does not outlive - // the P2PQuicStream object, it must unset itself before destructing. - virtual void SetDelegate(Delegate* delegate) = 0; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_P2P_QUIC_STREAM_H_
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream_impl.cc b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream_impl.cc deleted file mode 100644 index 4f234cb..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream_impl.cc +++ /dev/null
@@ -1,168 +0,0 @@ -// Copyright 2018 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/peerconnection/adapters/p2p_quic_stream_impl.h" - -#include <utility> -#include "net/third_party/quiche/src/quic/core/quic_error_codes.h" -#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h" - -namespace blink { - -P2PQuicStreamImpl::P2PQuicStreamImpl(quic::QuicStreamId id, - quic::QuicSession* session, - uint32_t delegate_read_buffer_size, - uint32_t write_buffer_size) - : quic::QuicStream(id, session, /*is_static=*/false, quic::BIDIRECTIONAL), - delegate_read_buffer_size_(delegate_read_buffer_size), - write_buffer_size_(write_buffer_size) { - DCHECK_GT(delegate_read_buffer_size_, 0u); - DCHECK_GT(write_buffer_size_, 0u); -} - -P2PQuicStreamImpl::P2PQuicStreamImpl(quic::PendingStream* pending, - quic::QuicSession* session, - uint32_t delegate_read_buffer_size, - uint32_t write_buffer_size) - : quic::QuicStream(pending, - session, - quic::BIDIRECTIONAL, - /*is_static=*/false), - delegate_read_buffer_size_(delegate_read_buffer_size), - write_buffer_size_(write_buffer_size) { - DCHECK_GT(delegate_read_buffer_size_, 0u); - DCHECK_GT(write_buffer_size_, 0u); -} - -P2PQuicStreamImpl::~P2PQuicStreamImpl() {} - -void P2PQuicStreamImpl::OnDataAvailable() { - if (!sequencer()->HasBytesToRead() && sequencer()->IsClosed()) { - // We have consumed all data from the sequencer up to the FIN bit. This can - // only occur by receiving an empty STREAM frame with the FIN bit set. - quic::QuicStream::OnFinRead(); - consumed_fin_ = true; - if (delegate_) { - delegate_->OnDataReceived({}, /*fin=*/true); - } - } - - uint32_t delegate_read_buffer_available = - delegate_read_buffer_size_ - delegate_read_buffered_amount_; - uint32_t total_read_amount = - std::min(static_cast<uint32_t>(sequencer()->ReadableBytes()), - delegate_read_buffer_available); - // Nothing to do if the delegate's read buffer can't fit anymore data, - // or the sequencer doesn't have any data available to be read. - if (total_read_amount == 0 || consumed_fin_) { - return; - } - Vector<uint8_t> data(total_read_amount); - uint32_t current_data_offset = 0; - struct iovec iov; - - // Read data from the quic::QuicStreamSequencer until we have exhausted the - // data, or have read at least the amount of the delegate's read buffer size. - while (sequencer()->GetReadableRegion(&iov)) { - uint32_t read_amount = static_cast<uint32_t>(iov.iov_len); - if (read_amount == 0) { - // Read everything available from the quic::QuicStreamSequencer. - DCHECK_EQ(current_data_offset, total_read_amount); - break; - } - // Limit the |consume_amount| by the amount available in the delegate's read - // buffer. - uint32_t consume_amount = std::min( - read_amount, delegate_read_buffer_available - current_data_offset); - memcpy(data.data() + current_data_offset, iov.iov_base, consume_amount); - sequencer()->MarkConsumed(consume_amount); - current_data_offset += consume_amount; - if (read_amount > consume_amount) { - // The delegate cannot store more data in its read buffer. - DCHECK_EQ(current_data_offset, total_read_amount); - break; - } - } - - bool fin = !sequencer()->HasBytesToRead() && sequencer()->IsClosed(); - delegate_read_buffered_amount_ += data.size(); - DCHECK(delegate_read_buffer_size_ >= delegate_read_buffered_amount_); - if (fin) { - quic::QuicStream::OnFinRead(); - consumed_fin_ = fin; - } - if (delegate_) { - delegate_->OnDataReceived(std::move(data), fin); - } -} - -void P2PQuicStreamImpl::OnStreamDataConsumed( - quic::QuicByteCount bytes_consumed) { - // We should never consume more than has been written. - DCHECK_GE(write_buffered_amount_, bytes_consumed); - QuicStream::OnStreamDataConsumed(bytes_consumed); - if (bytes_consumed > 0) { - write_buffered_amount_ -= bytes_consumed; - if (delegate_) { - delegate_->OnWriteDataConsumed(SafeCast<uint32_t>(bytes_consumed)); - } - } -} - -void P2PQuicStreamImpl::Reset() { - if (rst_sent()) { - // No need to reset twice. This could have already been sent as consequence - // of receiving a RST_STREAM frame. - return; - } - quic::QuicStream::Reset(quic::QuicRstStreamErrorCode::QUIC_STREAM_CANCELLED); -} - -void P2PQuicStreamImpl::MarkReceivedDataConsumed(uint32_t amount) { - DCHECK_GE(delegate_read_buffered_amount_, amount); - delegate_read_buffered_amount_ -= amount; - if (sequencer()->HasBytesToRead() || !consumed_fin_) { - OnDataAvailable(); - } -} - -void P2PQuicStreamImpl::WriteData(Vector<uint8_t> data, bool fin) { - // It is up to the delegate to not write more data than the - // |write_buffer_size_|. - DCHECK_GE(write_buffer_size_, data.size() + write_buffered_amount_); - write_buffered_amount_ += data.size(); - QuicStream::WriteOrBufferData( - quiche::QuicheStringPiece(reinterpret_cast<const char*>(data.data()), - data.size()), - fin, nullptr); -} - -void P2PQuicStreamImpl::SetDelegate(P2PQuicStream::Delegate* delegate) { - delegate_ = delegate; -} - -void P2PQuicStreamImpl::OnStreamReset(const quic::QuicRstStreamFrame& frame) { - // Calling this on the QuicStream will ensure that the stream is closed - // for reading and writing and we send a RST frame to the remote side if - // we have not already. - quic::QuicStream::OnStreamReset(frame); - if (delegate_) { - delegate_->OnRemoteReset(); - } -} - -void P2PQuicStreamImpl::OnClose() { - closed_ = true; - quic::QuicStream::OnClose(); -} - -bool P2PQuicStreamImpl::IsClosedForTesting() { - return closed_; -} - -uint32_t P2PQuicStreamImpl::DelegateReadBufferedAmountForTesting() { - return delegate_read_buffered_amount_; -} - -} // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream_impl.h b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream_impl.h deleted file mode 100644 index d5a8e98..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream_impl.h +++ /dev/null
@@ -1,102 +0,0 @@ -// Copyright 2018 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_PEERCONNECTION_ADAPTERS_P2P_QUIC_STREAM_IMPL_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_P2P_QUIC_STREAM_IMPL_H_ - -#include "net/third_party/quiche/src/quic/core/quic_session.h" -#include "third_party/blink/renderer/modules/modules_export.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream.h" - -namespace blink { - -class MODULES_EXPORT P2PQuicStreamImpl final : public quic::QuicStream, - public P2PQuicStream { - public: - P2PQuicStreamImpl(quic::QuicStreamId id, - quic::QuicSession* session, - uint32_t delegate_read_buffer_size, - uint32_t write_buffer_size); - P2PQuicStreamImpl(quic::PendingStream* pending, - quic::QuicSession* session, - uint32_t delegate_read_buffer_size, - uint32_t write_buffer_size); - ~P2PQuicStreamImpl() override; - // P2PQuicStream overrides - void SetDelegate(P2PQuicStream::Delegate* delegate) override; - - void Reset() override; - - void WriteData(Vector<uint8_t> data, bool fin) override; - - void MarkReceivedDataConsumed(uint32_t amount) override; - - // For testing purposes. This is returns true after quic::QuicStream::OnClose - bool IsClosedForTesting(); - - // For testing purposes. This exposes the amount of received data that the - // P2PQuicStream is aware is buffered by the delegate. - uint32_t DelegateReadBufferedAmountForTesting(); - - // quic::QuicStream overrides. - // - // Right now this marks the data as consumed and drops it. - // TODO(https://crbug.com/874296): We need to update this function for - // reading and consuming data properly while the main JavaScript thread is - // busy. See: - // https://w3c.github.io/webrtc-quic/#dom-rtcquicstream-waitforreadable - void OnDataAvailable() override; - // Called by the quic::QuicSession when receiving a RST_STREAM frame from the - // remote side. This closes the stream for reading & writing (if not already - // closed), and sends a RST_STREAM frame if one has not been sent yet. - void OnStreamReset(const quic::QuicRstStreamFrame& frame) override; - // Called by the quic::QuicSession. This means the stream is closed for - // reading - // and writing, and can now be deleted by the quic::QuicSession. - void OnClose() override; - - protected: - // quic::QuicStream overrides. - // - // Called when written data (from WriteData()) is consumed by QUIC. This means - // the data has either been sent across the wire, or it has been turned into a - // packet and queued if the socket is unexpectedly blocked. - void OnStreamDataConsumed(quic::QuicByteCount bytes_consumed) override; - - private: - using quic::QuicStream::Reset; - - // Must either outlive the P2PQuicStream or unset itself upon destruction. - Delegate* delegate_; - - // The read buffer size of the delegate. The |delegate_read_buffered_amount_| - // must never exceed this value (enforced by the P2PQuicStreamImpl). - const uint32_t delegate_read_buffer_size_; - // The maximum size allowed to be buffered write side. The - // |write_buffered_amount_| must never exceed this value, and it is up - // to the delegate to enforce this. - const uint32_t write_buffer_size_; - // How much total data has been received and given to the delegate, - // but not yet consumed by the delegate. This value gets increased when data - // is received from the QUIC library in OnDataAvailable() and and decreased - // when the delegate updates that data has been read with - // MarkReceivedDataConsumed(). - uint32_t delegate_read_buffered_amount_ = 0; - // How much data is buffered by the QUIC library, but has not yet - // been sent. This value gets increased when WriteData() is called - // and decreased when OnDataConsumed() gets called by the QUIC library, - // due to the data being sent. - uint32_t write_buffered_amount_ = 0; - - // Set after OnClose gets called. - bool closed_ = false; - - // This is set after the sequencer is closed due to the P2PQuicStream - // consuming all of the sequencer's data up to the FIN bit. - bool consumed_fin_ = false; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_P2P_QUIC_STREAM_IMPL_H_
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream_unittest.cc b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream_unittest.cc deleted file mode 100644 index 844c5bb..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream_unittest.cc +++ /dev/null
@@ -1,566 +0,0 @@ -// Copyright 2018 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/peerconnection/adapters/p2p_quic_stream.h" -#include "net/test/gtest_util.h" -#include "net/third_party/quiche/src/quic/core/quic_data_writer.h" -#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream_impl.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/test/mock_p2p_quic_stream_delegate.h" - -namespace blink { - -namespace { - -using testing::_; -using testing::ElementsAre; -using testing::ElementsAreArray; -using testing::Invoke; -using testing::InvokeWithoutArgs; - -const uint32_t kDefaultStreamWriteBufferSize = 1024; -const uint32_t kDefaultStreamDelegateReadBufferSize = 1024; -const quic::QuicStreamId kStreamId = 5; -const uint8_t kSomeData[] = {'h', 'o', 'w', 'd', 'y'}; -const uint8_t kMoreData[] = {'m', 'o', 'r', 'e'}; - -} // namespace - -// Unit tests for the P2PQuicStream, using a mock QuicSession, which allows -// us to isolate testing the behaviors of reading a writing. -class P2PQuicStreamTest : public testing::Test { - public: - P2PQuicStreamTest() { - // TODO(crbug/1070747): Fix tests for IETF QUIC. - quic::test::DisableQuicVersionsWithTls(); - connection_ = new quic::test::MockQuicConnection( - &connection_helper_, &alarm_factory_, quic::Perspective::IS_CLIENT); - session_ = std::make_unique<quic::test::MockQuicSession>(connection_); - session_->Initialize(); - // DCHECKS get hit when the clock is at 0. - connection_helper_.AdvanceTime(quic::QuicTime::Delta::FromSeconds(1)); - } - - ~P2PQuicStreamTest() override {} - - void InitializeStream( - uint32_t delegate_read_buffer_size = kDefaultStreamDelegateReadBufferSize, - uint32_t write_buffer_size = kDefaultStreamWriteBufferSize) { - stream_ = - new P2PQuicStreamImpl(kStreamId, session_.get(), - delegate_read_buffer_size, write_buffer_size); - stream_->SetDelegate(&delegate_); - // The session takes the ownership of the stream. - session_->ActivateStream(std::unique_ptr<P2PQuicStreamImpl>(stream_)); - } - - template <wtf_size_t Size> - static quiche::QuicheStringPiece StringPieceFromArray( - const uint8_t (&array)[Size]) { - return quiche::QuicheStringPiece(reinterpret_cast<const char*>(array), - Size); - } - - template <wtf_size_t Size> - static Vector<uint8_t> VectorFromArray(const uint8_t (&array)[Size]) { - Vector<uint8_t> vector; - vector.Append(array, Size); - return vector; - } - - quic::test::MockQuicConnectionHelper connection_helper_; - quic::test::MockAlarmFactory alarm_factory_; - // Owned by the |session_|. - quic::test::MockQuicConnection* connection_; - // The MockQuicSession allows us to see data that is being written and control - // whether the data is being "sent across" or blocked. - std::unique_ptr<quic::test::MockQuicSession> session_; - MockP2PQuicStreamDelegate delegate_; - // Owned by |session_|. - P2PQuicStreamImpl* stream_; -}; - -TEST_F(P2PQuicStreamTest, StreamSendsFinAndCanNoLongerWrite) { - InitializeStream(); - EXPECT_CALL(*session_, - WritevData(kStreamId, 0u, 0u, quic::StreamSendingState::FIN, - quic::NOT_RETRANSMISSION, _)) - .WillOnce(InvokeWithoutArgs([this]() { - return session_->ConsumeData(stream_->id(), 0u, 0u, - quic::StreamSendingState::FIN, - quic::NOT_RETRANSMISSION, QUICHE_NULLOPT); - })); - - stream_->WriteData({}, /*fin=*/true); - - EXPECT_TRUE(stream_->fin_sent()); - EXPECT_TRUE(stream_->write_side_closed()); - EXPECT_FALSE(stream_->reading_stopped()); -} - -TEST_F(P2PQuicStreamTest, StreamResetSendsRst) { - InitializeStream(); - EXPECT_CALL(*session_, SendRstStream(kStreamId, _, _, _)); - stream_->Reset(); - EXPECT_TRUE(stream_->rst_sent()); -} - -// Tests that when a stream receives a stream frame with the FIN bit set it -// will fire the appropriate callback and close the stream for reading. -TEST_F(P2PQuicStreamTest, StreamOnStreamFrameWithFin) { - InitializeStream(); - EXPECT_CALL(delegate_, OnDataReceived(_, /*fin=*/true)); - - quic::QuicStreamFrame fin_frame(kStreamId, /*fin=*/true, 0, 0); - stream_->OnStreamFrame(fin_frame); - - EXPECT_TRUE(stream_->reading_stopped()); - EXPECT_FALSE(stream_->write_side_closed()); -} - -// Tests that when a stream receives a stream frame with the FIN bit set after -// it has written the FIN bit, then the stream will close. -TEST_F(P2PQuicStreamTest, StreamClosedAfterSendingThenReceivingFin) { - InitializeStream(); - EXPECT_CALL(*session_, - WritevData(kStreamId, 0u, 0u, _, quic::NOT_RETRANSMISSION, _)) - .WillOnce(InvokeWithoutArgs([this]() { - return session_->ConsumeData(stream_->id(), 0u, 0u, - quic::StreamSendingState::FIN, - quic::NOT_RETRANSMISSION, QUICHE_NULLOPT); - })); - - stream_->WriteData({}, /*fin=*/true); - EXPECT_FALSE(stream_->IsClosedForTesting()); - - quic::QuicStreamFrame fin_frame(stream_->id(), /*fin=*/true, 0, 0); - stream_->OnStreamFrame(fin_frame); - - EXPECT_TRUE(stream_->reading_stopped()); - EXPECT_TRUE(stream_->write_side_closed()); - EXPECT_TRUE(stream_->IsClosedForTesting()); -} - -// Tests that when a stream writes a FIN bit after receiving a stream frame with -// the FIN bit then the stream will close. -TEST_F(P2PQuicStreamTest, StreamClosedAfterReceivingThenSendingFin) { - InitializeStream(); - quic::QuicStreamFrame fin_frame(stream_->id(), /*fin=*/true, 0, 0); - stream_->OnStreamFrame(fin_frame); - EXPECT_FALSE(stream_->IsClosedForTesting()); - - EXPECT_CALL(*session_, - WritevData(kStreamId, 0u, 0u, quic::StreamSendingState::FIN, - quic::NOT_RETRANSMISSION, _)) - .WillOnce(InvokeWithoutArgs([this]() { - return session_->ConsumeData(stream_->id(), 0u, 0u, - quic::StreamSendingState::FIN, - quic::NOT_RETRANSMISSION, QUICHE_NULLOPT); - })); - - stream_->WriteData({}, /*fin=*/true); - - EXPECT_TRUE(stream_->IsClosedForTesting()); -} - -// Tests that when a stream writes some data with the FIN bit set, and receives -// data with the FIN bit set it will become closed. -TEST_F(P2PQuicStreamTest, StreamClosedAfterWritingAndReceivingDataWithFin) { - InitializeStream(); - EXPECT_CALL(*session_, - WritevData(kStreamId, - /*write_length=*/base::size(kSomeData), _, _, _, _)) - .WillOnce(Invoke( - [this](quic::QuicStreamId id, size_t write_length, - quic::QuicStreamOffset offset, quic::StreamSendingState state, - quic::TransmissionType type, - quiche::QuicheOptional<quic::EncryptionLevel> level) { - // WritevData does not pass the data. The data is saved to the - // stream, so we must grab it before it's consumed, in order to - // check that it's what was written. - std::string data_consumed_by_quic(write_length, 'a'); - quic::QuicDataWriter writer(write_length, &data_consumed_by_quic[0], - quiche::NETWORK_BYTE_ORDER); - stream_->WriteStreamData(offset, write_length, &writer); - - EXPECT_THAT(data_consumed_by_quic, ElementsAreArray(kSomeData)); - EXPECT_EQ(quic::StreamSendingState::FIN, state); - return quic::QuicConsumedData( - write_length, state != quic::StreamSendingState::NO_FIN); - })); - - stream_->WriteData(VectorFromArray(kSomeData), - /*fin=*/true); - EXPECT_FALSE(stream_->IsClosedForTesting()); - - quic::QuicStreamFrame fin_frame_with_data(stream_->id(), /*fin=*/true, 0, - StringPieceFromArray(kSomeData)); - stream_->OnStreamFrame(fin_frame_with_data); - - EXPECT_TRUE(stream_->reading_stopped()); - EXPECT_TRUE(stream_->write_side_closed()); - EXPECT_TRUE(stream_->IsClosedForTesting()); -} - -// Tests that when a stream receives a RST_STREAM frame it will fire the -// appropriate callback and the stream will become closed. -TEST_F(P2PQuicStreamTest, StreamClosedAfterReceivingReset) { - InitializeStream(); - EXPECT_CALL(delegate_, OnRemoteReset()); - - quic::QuicRstStreamFrame rst_frame(quic::kInvalidControlFrameId, kStreamId, - quic::QUIC_STREAM_CANCELLED, 0); - if (!VersionHasIetfQuicFrames(connection_->version().transport_version)) { - // Google RST_STREAM closes the stream in both directions. A RST_STREAM - // is then sent to the peer to communicate the final byte offset. - EXPECT_CALL(*session_, - SendRstStream(kStreamId, quic::QUIC_RST_ACKNOWLEDGEMENT, 0, _)); - } - stream_->OnStreamReset(rst_frame); - if (VersionHasIetfQuicFrames(connection_->version().transport_version)) { - // In IETF QUIC, the RST_STREAM only closes the stream in one direction. - // A STOP_SENDING frame in require to induce the a RST_STREAM being - // send to close the other direction. - EXPECT_CALL(*connection_, SendControlFrame(_)); - EXPECT_CALL(*connection_, OnStreamReset(kStreamId, testing::_)); - quic::QuicStopSendingFrame stop_sending_frame( - quic::kInvalidControlFrameId, kStreamId, quic::QUIC_STREAM_NO_ERROR); - session_->OnStopSendingFrame(stop_sending_frame); - } - - EXPECT_TRUE(stream_->IsClosedForTesting()); -} - -// Tests that data written to the P2PQuicStream will appropriately get written -// to the underlying QUIC library. -TEST_F(P2PQuicStreamTest, StreamWritesData) { - InitializeStream(); - EXPECT_CALL(*session_, - WritevData(kStreamId, - /*write_length=*/base::size(kSomeData), _, _, _, _)) - .WillOnce(Invoke( - [this](quic::QuicStreamId id, size_t write_length, - quic::QuicStreamOffset offset, quic::StreamSendingState state, - quic::TransmissionType type, - quiche::QuicheOptional<quic::EncryptionLevel> level) { - // quic::QuicSession::WritevData does not pass the data. The data is - // saved to the stream, so we must grab it before it's consumed, in - // order to check that it's what was written. - std::string data_consumed_by_quic(write_length, 'a'); - quic::QuicDataWriter writer(write_length, &data_consumed_by_quic[0], - quiche::NETWORK_BYTE_ORDER); - stream_->WriteStreamData(offset, write_length, &writer); - - EXPECT_THAT(data_consumed_by_quic, ElementsAreArray(kSomeData)); - EXPECT_EQ(quic::StreamSendingState::NO_FIN, state); - return quic::QuicConsumedData( - write_length, state != quic::StreamSendingState::NO_FIN); - })); - EXPECT_CALL(delegate_, OnWriteDataConsumed(base::size(kSomeData))); - - stream_->WriteData(VectorFromArray(kSomeData), /*fin=*/false); -} - -// Tests that data written to the P2PQuicStream will appropriately get written -// to the underlying QUIC library with the FIN bit set. -TEST_F(P2PQuicStreamTest, StreamWritesDataWithFin) { - InitializeStream(); - EXPECT_CALL(*session_, - WritevData(kStreamId, - /*write_length=*/base::size(kSomeData), _, _, _, _)) - .WillOnce(Invoke( - [this](quic::QuicStreamId id, size_t write_length, - quic::QuicStreamOffset offset, quic::StreamSendingState state, - quic::TransmissionType type, - quiche::QuicheOptional<quic::EncryptionLevel> level) { - // WritevData does not pass the data. The data is saved to the - // stream, so we must grab it before it's consumed, in order to - // check that it's what was written. - std::string data_consumed_by_quic(write_length, 'a'); - quic::QuicDataWriter writer(write_length, &data_consumed_by_quic[0], - quiche::NETWORK_BYTE_ORDER); - stream_->WriteStreamData(offset, write_length, &writer); - - EXPECT_THAT(data_consumed_by_quic, ElementsAreArray(kSomeData)); - EXPECT_EQ(quic::StreamSendingState::FIN, state); - return quic::QuicConsumedData( - write_length, state != quic::StreamSendingState::NO_FIN); - })); - EXPECT_CALL(delegate_, OnWriteDataConsumed(base::size(kSomeData))); - - stream_->WriteData(VectorFromArray(kSomeData), /*fin=*/true); -} - -// Tests that when written data is not consumed by QUIC (due to buffering), -// the OnWriteDataConsumed will not get fired. -TEST_F(P2PQuicStreamTest, StreamWritesDataAndNotConsumedByQuic) { - InitializeStream(); - EXPECT_CALL(delegate_, OnWriteDataConsumed(_)).Times(0); - EXPECT_CALL(*session_, - WritevData(kStreamId, - /*write_length=*/base::size(kSomeData), _, _, _, _)) - .WillOnce(Invoke([](quic::QuicStreamId id, size_t write_length, - quic::QuicStreamOffset offset, - quic::StreamSendingState state, - quic::TransmissionType type, - quiche::QuicheOptional<quic::EncryptionLevel> level) { - // We mock that the QUIC library is not consuming the data, meaning it's - // being buffered. In this case, the OnWriteDataConsumed() callback - // should not be called. - return quic::QuicConsumedData(/*bytes_consumed=*/0, - quic::StreamSendingState::NO_FIN); - })); - - stream_->WriteData(VectorFromArray(kSomeData), /*fin=*/true); -} - -// Tests that OnWriteDataConsumed() is fired with the amount consumed by QUIC. -// This tests the case when amount consumed by QUIC is less than what is written -// with P2PQuicStream::WriteData. This can happen when QUIC is receiving back -// pressure from the receive side, and its "send window" is smaller than the -// amount attempted to be written. -TEST_F(P2PQuicStreamTest, StreamWritesDataAndPartiallyConsumedByQuic) { - InitializeStream(); - size_t amount_consumed_by_quic = 2; - EXPECT_CALL(delegate_, OnWriteDataConsumed(amount_consumed_by_quic)); - EXPECT_CALL(*session_, - WritevData(kStreamId, - /*write_length=*/base::size(kSomeData), _, _, _, _)) - .WillOnce(Invoke( - [&amount_consumed_by_quic]( - quic::QuicStreamId id, size_t write_length, - quic::QuicStreamOffset offset, quic::StreamSendingState state, - quic::TransmissionType type, - quiche::QuicheOptional<quic::EncryptionLevel> level) { - // We mock that the QUIC library is only consuming some of the data, - // meaning the rest is being buffered. - return quic::QuicConsumedData( - /*bytes_consumed=*/amount_consumed_by_quic, - quic::StreamSendingState::NO_FIN); - })); - - stream_->WriteData(VectorFromArray(kSomeData), /*fin=*/true); -} - -// Tests if a P2PQuicStream receives data it will appropriately fire the -// OnDataReceived callback to the delegate. -TEST_F(P2PQuicStreamTest, StreamReceivesData) { - InitializeStream(); - quic::QuicStreamFrame stream_frame(stream_->id(), /*fin=*/false, 0, - StringPieceFromArray(kSomeData)); - - EXPECT_CALL(delegate_, OnDataReceived(VectorFromArray(kSomeData), - /*fin=*/false)); - - stream_->OnStreamFrame(stream_frame); -} - -// Tests that when received data is marked consumed it is appropriately -// reflected in the P2PQuicStream's view of the delegate read buffer size. -TEST_F(P2PQuicStreamTest, MarkConsumedData) { - InitializeStream(); - quic::QuicStreamFrame stream_frame(stream_->id(), /*fin=*/false, 0, - StringPieceFromArray(kSomeData)); - - EXPECT_CALL(delegate_, OnDataReceived(_, _)); - stream_->OnStreamFrame(stream_frame); - // At this point the application has received data but not marked is as - // consumed, so from the P2PQuicStream perspective that data has been - // buffered. - EXPECT_EQ(base::size(kSomeData), - stream_->DelegateReadBufferedAmountForTesting()); - - stream_->MarkReceivedDataConsumed(base::size(kSomeData)); - EXPECT_EQ(0u, stream_->DelegateReadBufferedAmountForTesting()); -} - -// Tests that if the delegate's read buffer is "full" from the -// P2PQuicStream's perspective, then getting more data will not fire the -// OnDataReceived callback. -TEST_F(P2PQuicStreamTest, StreamReceivesDataWithFullReadBuffer) { - // The P2PQuicStream is created with a delegate read buffer size equal - // to the size of the data that is being received. - InitializeStream(/*delegate_read_buffer_size=*/base::size(kSomeData)); - quic::QuicStreamFrame stream_frame(stream_->id(), /*fin=*/false, 0, - StringPieceFromArray(kSomeData)); - - EXPECT_CALL(delegate_, OnDataReceived(_, _)).Times(1); - stream_->OnStreamFrame(stream_frame); - EXPECT_EQ(base::size(kSomeData), - stream_->DelegateReadBufferedAmountForTesting()); - - // Delegate read buffer is now full. Receiving more data should not fire the - // callback. - quic::QuicStreamFrame new_stream_frame(stream_->id(), /*fin=*/false, - /*offset=*/base::size(kSomeData), - StringPieceFromArray(kMoreData)); - stream_->OnStreamFrame(new_stream_frame); - EXPECT_EQ(base::size(kSomeData), - stream_->DelegateReadBufferedAmountForTesting()); -} - -// Tests that if the delegate's read buffer is "full" from the -// P2PQuicStream's perspective, and then getting an empty STREAM frame with the -// FIN bit set, will fire Delegate::OnDataReceived with fin set to true. -TEST_F(P2PQuicStreamTest, StreamReceivesFinWithFullReadBuffer) { - // The P2PQuicStream is created with a delegate read buffer size equal - // to the size of the data that is being received. - InitializeStream(/*delegate_read_buffer_size=*/base::size(kSomeData)); - quic::QuicStreamFrame stream_frame(stream_->id(), /*fin=*/false, 0, - StringPieceFromArray(kSomeData)); - - EXPECT_CALL(delegate_, OnDataReceived(ElementsAreArray(kSomeData), - /*fin=*/false)) - .Times(1); - stream_->OnStreamFrame(stream_frame); - EXPECT_EQ(base::size(kSomeData), - stream_->DelegateReadBufferedAmountForTesting()); - - // Delegate read buffer is now full, but because the STREAM frame with the FIN - // bit doesn't contain any data, it means that all data has been consumed from - // the sequencer up to the FIN bit. This fires OnDataReceived with the - // fin=true. - EXPECT_CALL(delegate_, OnDataReceived(_, true)).Times(1); - quic::QuicStreamFrame new_stream_frame(stream_->id(), /*fin=*/true, - /*offset=*/base::size(kSomeData), 0); - stream_->OnStreamFrame(new_stream_frame); - EXPECT_EQ(base::size(kSomeData), - stream_->DelegateReadBufferedAmountForTesting()); -} - -// Tests that when the delegate's read buffer is "full" from the -// P2PQuicStream's perspective, the Delegate::OnDataReceived callback is -// fired after the received data is marked as consumed by the delegate. -TEST_F(P2PQuicStreamTest, StreamDataConsumedWithFullDelegateReadBuffer) { - // The P2PQuicStream is created with a delegate read buffer size equal - // to the size of the data that is being received. - InitializeStream(/*delegate_read_buffer_size=*/base::size(kSomeData)); - quic::QuicStreamFrame stream_frame(stream_->id(), /*fin=*/false, 0, - StringPieceFromArray(kSomeData)); - - EXPECT_CALL(delegate_, OnDataReceived(ElementsAreArray(kSomeData), - /*fin=*/false)) - .Times(1); - stream_->OnStreamFrame(stream_frame); - EXPECT_EQ(base::size(kSomeData), - stream_->DelegateReadBufferedAmountForTesting()); - - // Delegate read buffer is now full. Receiving more data should not fire the - // callback. - quic::QuicStreamFrame new_stream_frame(stream_->id(), /*fin=*/true, - /*offset=*/base::size(kSomeData), - StringPieceFromArray(kMoreData)); - stream_->OnStreamFrame(new_stream_frame); - EXPECT_EQ(base::size(kSomeData), - stream_->DelegateReadBufferedAmountForTesting()); - - // Marking the original data as consumed should fire the new data to be - // received. - EXPECT_CALL(delegate_, OnDataReceived(ElementsAreArray(kMoreData), - /*fin=*/true)) - .Times(1); - stream_->MarkReceivedDataConsumed(base::size(kSomeData)); - EXPECT_EQ(base::size(kMoreData), - stream_->DelegateReadBufferedAmountForTesting()); -} - -// Tests that when receiving more data than available in the delegate read -// buffer, that the delegate will get an OnDataReceived callback for the amount -// available in its buffer. Then later when the delegate marks the data as -// consumed it will get another OnDataReceived callback. -TEST_F(P2PQuicStreamTest, StreamReceivesMoreDataThanDelegateReadBufferSize) { - const uint8_t kData[] = {'s', 'o', 'm', 'e', 'd', 'a', 't', 'a'}; - // The P2PQuicStream is created with a delegate read buffer size equal - // to half of the data being sent. - InitializeStream(/*delegate_read_buffer_size=*/4); - quic::QuicStreamFrame stream_frame(stream_->id(), /*fin=*/true, 0, - StringPieceFromArray(kData)); - - // Upon receiving the stream frame the Delegate should receive "some", because - // that's all it has space to buffer. - EXPECT_CALL(delegate_, OnDataReceived(ElementsAre('s', 'o', 'm', 'e'), - /*fin=*/false)) - .Times(1); - stream_->OnStreamFrame(stream_frame); - EXPECT_EQ(4u, stream_->DelegateReadBufferedAmountForTesting()); - - // Upon consuming 2 bytes of data, the delegate should receive the next part - // of the message - "da". - EXPECT_CALL(delegate_, OnDataReceived(ElementsAre('d', 'a'), /*fin=*/false)) - .Times(1); - stream_->MarkReceivedDataConsumed(2); - EXPECT_EQ(4u, stream_->DelegateReadBufferedAmountForTesting()); - - // After consuming 4 bytes of data (all received data thus far), the delegate - // should receive the next part of the message - "ta" and the FIN bit. - EXPECT_CALL(delegate_, OnDataReceived(ElementsAre('t', 'a'), /*fin=*/true)) - .Times(1); - stream_->MarkReceivedDataConsumed(4); - // Just the last data received ("ta") is held in the delegate's read buffer. - EXPECT_EQ(2u, stream_->DelegateReadBufferedAmountForTesting()); -} - -// Tests that after a delegate unsets itself, it will no longer receive the -// OnWriteDataConsumed callback. -TEST_F(P2PQuicStreamTest, UnsetDelegateDoesNotFireOnWriteDataConsumed) { - InitializeStream(); - stream_->SetDelegate(nullptr); - // Mock out the QuicSession to get the QuicStream::OnStreamDataConsumed - // callback to fire. - EXPECT_CALL(*session_, - WritevData(kStreamId, - /*write_length=*/base::size(kSomeData), _, _, _, _)) - .WillOnce(Invoke([](quic::QuicStreamId id, size_t write_length, - quic::QuicStreamOffset offset, - quic::StreamSendingState state, - quic::TransmissionType type, - quiche::QuicheOptional<quic::EncryptionLevel> level) { - return quic::QuicConsumedData( - write_length, state != quic::StreamSendingState::NO_FIN); - })); - - EXPECT_CALL(delegate_, OnWriteDataConsumed(_)).Times(0); - - stream_->WriteData(VectorFromArray(kSomeData), /*fin=*/false); -} - -// Tests that after a delegate unsets itself, it will no longer receive the -// OnRemoteReset callback. -TEST_F(P2PQuicStreamTest, UnsetDelegateDoesNotFireOnRemoteReset) { - InitializeStream(); - stream_->SetDelegate(nullptr); - EXPECT_CALL(delegate_, OnRemoteReset()).Times(0); - - quic::QuicRstStreamFrame rst_frame(quic::kInvalidControlFrameId, kStreamId, - quic::QUIC_STREAM_CANCELLED, 0); - stream_->OnStreamReset(rst_frame); -} - -// Tests that after a delegate unsets itself, it will no longer receive the -// OnDataReceived callback when receiving a stream frame with data and no FIN -// bit. -TEST_F(P2PQuicStreamTest, UnsetDelegateDoesNotFireOnDataReceivedWithData) { - InitializeStream(); - stream_->SetDelegate(nullptr); - - EXPECT_CALL(delegate_, OnDataReceived(_, _)).Times(0); - - quic::QuicStreamFrame stream_frame(stream_->id(), /*fin=*/false, 0, - StringPieceFromArray(kSomeData)); - stream_->OnStreamFrame(stream_frame); -} - -// Tests that after a delegate unsets itself, it will no longer receive the -// OnDataReceived callback when receiving a stream frame with the FIN bit. -TEST_F(P2PQuicStreamTest, UnsetDelegateDoesNotFireOnDataReceivedWithFin) { - InitializeStream(); - stream_->SetDelegate(nullptr); - - EXPECT_CALL(delegate_, OnDataReceived(_, _)).Times(0); - - quic::QuicStreamFrame stream_frame(stream_->id(), /*fin=*/true, 0, {}); - stream_->OnStreamFrame(stream_frame); -} -} // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport.h b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport.h deleted file mode 100644 index a93498d..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport.h +++ /dev/null
@@ -1,142 +0,0 @@ -// Copyright 2018 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_PEERCONNECTION_ADAPTERS_P2P_QUIC_TRANSPORT_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_P2P_QUIC_TRANSPORT_H_ - -#include "base/check_op.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_stats.h" -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" -#include "third_party/blink/renderer/platform/wtf/vector.h" -#include "third_party/webrtc/rtc_base/ssl_fingerprint.h" - -namespace blink { - -class P2PQuicStream; - -// Includes any relevant parameters that were negotiated in the QUIC handshake. -// Used in the P2PQuicTransport::Delegate::OnConnected callback. -struct P2PQuicNegotiatedParams final { - // If datagrams were negotiated to be supported. - bool datagrams_supported() const { return max_datagram_length_.has_value(); } - - void set_max_datagram_length(uint16_t max_datagram_length) { - DCHECK_GT(max_datagram_length, 0); - max_datagram_length_ = max_datagram_length; - } - - uint16_t max_datagram_length() const { - DCHECK(datagrams_supported()); - return max_datagram_length_.value_or(0); - } - - private: - // According to draft-pauly-quic-datagram-02#section-3, this should be - // negotiated as a transport parameter, although in the QUICHE implementation - // it is based upon the QUIC version (determines packet header size) and - // default max packet size (1350 bytes). - base::Optional<uint16_t> max_datagram_length_; -}; - -// Used by the RTCQuicTransport Web API. This transport creates and manages -// streams, handles negotiation, state changes and errors. Every -// P2PQuicTransport function maps directly to a method in the RTCQuicTransport -// Web API, i.e. RTCQuicTransport::stop() --> -// P2PQuicTransport::Stop(). This allows posting just one task across -// thread boundaries to execute a function. -// -// This object should be run entirely on the webrtc worker thread. -class P2PQuicTransport { - USING_FAST_MALLOC(P2PQuicTransport); - - public: - // A config used when starting the QUIC handshake. - struct StartConfig final { - explicit StartConfig( - Vector<std::unique_ptr<rtc::SSLFingerprint>> remote_fingerprints_in) - : remote_fingerprints(std::move(remote_fingerprints_in)) { - DCHECK_GT(remote_fingerprints.size(), 0u); - } - - explicit StartConfig(const std::string pre_shared_key_in) - : pre_shared_key(pre_shared_key_in) { - DCHECK(!pre_shared_key.empty()); - } - - // These fingerprints are used to verify the self signed remote certificate - // used in the QUIC handshake. See: - // https://w3c.github.io/webrtc-quic/#quic-transport* - Vector<std::unique_ptr<rtc::SSLFingerprint>> remote_fingerprints; - - // The pre shared key to be used in the handshake. - const std::string pre_shared_key; - }; - - // Used for receiving callbacks from the P2PQuicTransport regarding QUIC - // connection changes, handshake success/failures and new QuicStreams being - // added from the remote side. - class Delegate { - public: - virtual ~Delegate() = default; - // Called when receiving a close frame from the remote side, due to - // calling P2PQuicTransport::Stop(). - virtual void OnRemoteStopped() {} - // Called when the connection is closed due to a QUIC error. This can happen - // locally by the framer, or remotely by the peer. - virtual void OnConnectionFailed(const std::string& error_details, - bool from_remote) {} - // Called when the crypto handshake has completed and fingerprints have been - // verified. - virtual void OnConnected(P2PQuicNegotiatedParams negotiated_params) {} - - // Called when the datagram has been consumed by the QUIC library and sent - // on the network. - virtual void OnDatagramSent() {} - - // Called when we receive a datagram from the remote side. - virtual void OnDatagramReceived(Vector<uint8_t> datagram) {} - - // Called when an incoming stream is received from the remote side. This - // stream is owned by the P2PQuicTransport. Its lifetime is managed by the - // P2PQuicTransport, and can be deleted when: - // - The P2PQuicStream becomes closed for reading and writing. - // - Stop() is called. - // - The P2PQuicTransport is deleted. - virtual void OnStream(P2PQuicStream* stream) {} - }; - - virtual ~P2PQuicTransport() = default; - - // Closes the QuicConnection and sends a close frame to the remote side. - // This will trigger P2PQuicTransport::Delegate::OnRemoteClosed() on the - // remote side. This must not be called before Start(). - virtual void Stop() = 0; - - // Starts the QUIC handshake negotiation. If this is a client perspective - // this means initiating the QUIC handshake with a CHLO, while for - // a server perspective this means now listening and responding to a CHLO. - virtual void Start(StartConfig config) = 0; - - // Creates a new outgoing stream. This stream is owned by the - // P2PQuicTransport. Its lifetime is managed by the P2PQuicTransport, - // and can be deleted when: - // - The P2PQuicStream becomes closed for reading and writing. - // - Stop() is called. - // - The P2PQuicTransport is deleted. - virtual P2PQuicStream* CreateStream() = 0; - - // Gets the associated stats. These are QUIC connection level stats. - virtual P2PQuicTransportStats GetStats() const = 0; - - // Sends datagram. If the QUIC connection is write blocked due to congestion - // control the message will be buffered and sent once it is unblocked. Once - // the datagram has been sent, Delegate::OnDatagramSent will be called. - virtual void SendDatagram(Vector<uint8_t> datagram) = 0; - - // TODO(https://crbug.com/874296): Consider adding a getter for the - // local fingerprints of the certificate(s) set in the constructor. -}; -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_P2P_QUIC_TRANSPORT_H_
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_factory.h b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_factory.h deleted file mode 100644 index 7c65328b..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_factory.h +++ /dev/null
@@ -1,75 +0,0 @@ -// Copyright 2018 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_PEERCONNECTION_ADAPTERS_P2P_QUIC_TRANSPORT_FACTORY_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_P2P_QUIC_TRANSPORT_FACTORY_H_ - -#include "third_party/blink/renderer/modules/modules_export.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_packet_transport.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport.h" -#include "third_party/webrtc/api/scoped_refptr.h" -#include "third_party/webrtc/rtc_base/rtc_certificate.h" - -namespace blink { - -// A simple config object for creating a P2PQuicTransport. Its constructor -// guarantees that the required configuration for creating a P2PQuicTransport -// are part of the P2PQuicTransportConfig. -struct P2PQuicTransportConfig final { - // This object is only moveable. - explicit P2PQuicTransportConfig( - quic::Perspective perspective, - const Vector<rtc::scoped_refptr<rtc::RTCCertificate>> certificates_in, - uint32_t stream_delegate_read_buffer_size_in, - uint32_t stream_write_buffer_size_in) - : perspective(perspective), - certificates(certificates_in), - stream_delegate_read_buffer_size(stream_delegate_read_buffer_size_in), - stream_write_buffer_size(stream_write_buffer_size_in) { - DCHECK_GT(stream_delegate_read_buffer_size, 0u); - DCHECK_GT(stream_write_buffer_size, 0u); - } - - // Client or server. - quic::Perspective perspective; - // The certificates are owned by the P2PQuicTransport. These come from - // blink::RTCCertificates: https://www.w3.org/TR/webrtc/#dom-rtccertificate - // This can be empty if pre shared keys are being used to establish a - // connection. - const Vector<rtc::scoped_refptr<rtc::RTCCertificate>> certificates; - // The amount that the delegate can store in its read buffer. This is a - // mandatory field that must be set to ensure that the - // P2PQuicStream::Delegate will not give the delegate more data than it can - // store. - const uint32_t stream_delegate_read_buffer_size; - // The amount that the P2PQuicStream will allow to buffer. This is a mandatory - // field that must be set to ensure that the client of the P2PQuicStream does - // not write more data than can be buffered. - const uint32_t stream_write_buffer_size; -}; - -// For creating a P2PQuicTransport. This factory should be injected into -// whichever object plans to own and use a P2PQuicTransport. The -// P2PQuicTransportFactory needs to outlive the P2PQuicTransport it creates. -// -// This object should be run entirely on the webrtc worker thread. -class P2PQuicTransportFactory { - public: - virtual ~P2PQuicTransportFactory() = default; - - // Creates the P2PQuicTransport. This should be called on the same - // thread that the P2PQuicTransport will be used on. - // |delegate| receives callbacks from the P2PQuicTransport on the same thread. - // It must outlive the P2PQuicTransport. - // |packet_transport| is used to send and receive UDP packets. It must outlive - // the P2PQuicTransport. - virtual std::unique_ptr<P2PQuicTransport> CreateQuicTransport( - P2PQuicTransport::Delegate* delegate, - P2PQuicPacketTransport* packet_transport, - const P2PQuicTransportConfig& config) = 0; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_P2P_QUIC_TRANSPORT_FACTORY_H_
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_factory_impl.cc b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_factory_impl.cc deleted file mode 100644 index 6954e02..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_factory_impl.cc +++ /dev/null
@@ -1,41 +0,0 @@ -// Copyright 2018 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/peerconnection/adapters/p2p_quic_transport_factory_impl.h" -#include "net/third_party/quiche/src/quic/core/quic_connection_id.h" -#include "net/third_party/quiche/src/quic/core/quic_packet_writer.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_config_factory_impl.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_stream_factory_impl.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_packet_transport.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_impl.h" -#include "third_party/webrtc/rtc_base/rtc_certificate.h" - -namespace blink { - -P2PQuicTransportFactoryImpl::P2PQuicTransportFactoryImpl( - quic::QuicClock* clock, - std::unique_ptr<quic::QuicAlarmFactory> alarm_factory) - : clock_(clock), alarm_factory_(std::move(alarm_factory)) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); -} - -// The P2PQuicTransportImpl is created with Chromium specific QUIC objects: -// QuicClock, QuicRandom, QuicConnectionHelper and QuicAlarmFactory. -std::unique_ptr<P2PQuicTransport> -P2PQuicTransportFactoryImpl::CreateQuicTransport( - P2PQuicTransport::Delegate* delegate, - P2PQuicPacketTransport* packet_transport, - const P2PQuicTransportConfig& config) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(delegate); - DCHECK(packet_transport); - - quic::QuicRandom* quic_random = quic::QuicRandom::GetInstance(); - return P2PQuicTransportImpl::Create( - clock_, alarm_factory_.get(), quic_random, delegate, packet_transport, - std::move(config), - std::make_unique<P2PQuicCryptoConfigFactoryImpl>(quic_random), - std::make_unique<P2PQuicCryptoStreamFactoryImpl>()); -} -} // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_factory_impl.h b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_factory_impl.h deleted file mode 100644 index ec9fcc7c..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_factory_impl.h +++ /dev/null
@@ -1,45 +0,0 @@ -// Copyright 2018 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_PEERCONNECTION_ADAPTERS_P2P_QUIC_TRANSPORT_FACTORY_IMPL_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_P2P_QUIC_TRANSPORT_FACTORY_IMPL_H_ - -#include "net/third_party/quiche/src/quic/core/quic_connection.h" -#include "third_party/blink/renderer/modules/modules_export.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_factory.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_impl.h" - -namespace blink { - -// For creating a P2PQuicTransportImpl to be used for the blink Web API - -// RTCQuicTransport. -// -// This object should be run entirely on the webrtc worker thread. -class MODULES_EXPORT P2PQuicTransportFactoryImpl final - : public P2PQuicTransportFactory { - public: - P2PQuicTransportFactoryImpl( - quic::QuicClock* clock, - std::unique_ptr<quic::QuicAlarmFactory> alarm_factory); - ~P2PQuicTransportFactoryImpl() override {} - - // QuicTransportFactoryInterface override. - std::unique_ptr<P2PQuicTransport> CreateQuicTransport( - P2PQuicTransport::Delegate* delegate, - P2PQuicPacketTransport* packet_transport, - const P2PQuicTransportConfig& config) override; - - private: - // This is used to create a QuicChromiumConnectionHelper for the session. - // Should outlive the P2PQuicTransportFactoryImpl. - quic::QuicClock* clock_; - // Used for alarms that drive the underlying QUIC library. Should use the same - // clock as |clock_|. - std::unique_ptr<quic::QuicAlarmFactory> alarm_factory_; - THREAD_CHECKER(thread_checker_); -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_P2P_QUIC_TRANSPORT_FACTORY_IMPL_H_
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_impl.cc b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_impl.cc deleted file mode 100644 index 54053d6a..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_impl.cc +++ /dev/null
@@ -1,620 +0,0 @@ -// Copyright 2018 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/peerconnection/adapters/p2p_quic_transport_impl.h" - -#include "net/quic/quic_chromium_connection_helper.h" -#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h" -#include "net/third_party/quiche/src/quic/core/quic_config.h" -#include "net/third_party/quiche/src/quic/core/quic_types.h" -#include "net/third_party/quiche/src/quic/core/quic_utils.h" -#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h" -#include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h" -#include "net/third_party/quiche/src/quic/platform/api/quic_mem_slice_storage.h" -#include "net/third_party/quiche/src/quic/tools/quic_simple_crypto_server_stream_helper.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_stream_factory.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_stats.h" - -namespace blink { - -namespace { - -static const char kClosingDetails[] = "Application closed connection."; - -// QUIC's default is 100. Setting this value to 10000 allows room for QUIC to -// not refuse new incoming streams in the case that an application wants to send -// a small chunk of data per stream (and immediately close) unreliably. -uint32_t kMaxIncomingDynamicStreams = 10000; - -// The P2PQuicPacketWriter is a private helper class that implements the -// QuicPacketWriter using a P2PQuicPacketTransport. This allows us to -// connect our own packet transport for writing into the QuicConnection. -// The normal case is using an ICE transport (packet_transport) for writing. -class P2PQuicPacketWriter : public quic::QuicPacketWriter, - public P2PQuicPacketTransport::WriteObserver { - public: - P2PQuicPacketWriter(P2PQuicPacketTransport* packet_transport) - : packet_transport_(packet_transport) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(packet_transport_); - packet_transport_->SetWriteObserver(this); - } - - // This way the packet transport knows it no longer has a write observer and - // can DCHECK this on destruction. - ~P2PQuicPacketWriter() override { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - packet_transport_->SetWriteObserver(nullptr); - } - - // Sets the QuicConnection (which owns this packet writer). This allows us - // to get the packet numbers of QUIC packets we write. The QuicConnection - // is created with a quic::QuicPacketWriter, so we can't set the connection - // in the constructor. - void InitializeWithQuicConnection(quic::QuicConnection* connection) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(connection); - if (packet_transport_->Writable()) { - SetWritable(); - } - connection_ = connection; - } - - // quic::QuicPacketWriter overrides. - - // Writes a QUIC packet to the network with the packet number as additional - // packet info. - quic::WriteResult WritePacket(const char* buffer, - size_t buf_len, - const quic::QuicIpAddress& self_address, - const quic::QuicSocketAddress& peer_address, - quic::PerPacketOptions* options) override { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(connection_); - if (IsWriteBlocked()) { - return quic::WriteResult(quic::WRITE_STATUS_BLOCKED, EWOULDBLOCK); - } - - P2PQuicPacketTransport::QuicPacket packet; - packet.packet_number = - connection_->packet_creator().packet_number().ToUint64(); - packet.buffer = buffer; - packet.buf_len = buf_len; - int bytes_written = packet_transport_->WritePacket(packet); - if (bytes_written <= 0) { - writable_ = false; - return quic::WriteResult(quic::WRITE_STATUS_BLOCKED, EWOULDBLOCK); - } - return quic::WriteResult(quic::WRITE_STATUS_OK, bytes_written); - } - - bool IsWriteBlocked() const override { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - return !writable_; - } - - quic::QuicByteCount GetMaxPacketSize( - const quic::QuicSocketAddress& peer_address) const override { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - // This can be configured later. - return 1200; - } - - void SetWritable() override { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - writable_ = true; - } - - bool SupportsReleaseTime() const override { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - return false; - } - - bool IsBatchMode() const override { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - return false; - } - - quic::QuicPacketBuffer GetNextWriteLocation( - const quic::QuicIpAddress& self_address, - const quic::QuicSocketAddress& peer_address) override { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - return {nullptr, nullptr}; - } - - quic::WriteResult Flush() override { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - return quic::WriteResult(quic::WRITE_STATUS_OK, 0); - } - - // P2PQuicPacketTransport::WriteDelegate override. - void OnCanWrite() override { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - SetWritable(); - connection_->OnCanWrite(); - } - - private: - // The packet transport is owned by the P2PQuicSession, not the - // BlinkPacketWriter. - P2PQuicPacketTransport* packet_transport_; - // The QuicConnection owns this packet writer and will outlive it. - quic::QuicConnection* connection_; - - bool writable_ = false; - THREAD_CHECKER(thread_checker_); -}; - -// Creates the QuicConnection for the QuicSession. Currently this connection -// uses a dummy address and ID. The |packet_writer| is a basic implementation -// using the QuicTransportConfig::packet_transport for writing. The |helper| -// and |alarm_factory| should be chromium specific implementations. -std::unique_ptr<quic::QuicConnection> CreateQuicConnection( - quic::Perspective perspective, - quic::QuicConnectionHelperInterface* helper, - quic::QuicPacketWriter* packet_writer, - quic::QuicAlarmFactory* alarm_factory) { - quic::QuicIpAddress ip; - ip.FromString("0.0.0.0"); - quic::QuicSocketAddress dummy_address(ip, 0 /* Port */); - quic::QuicConnectionId dummy_connection_id; - char connection_id_bytes[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - dummy_connection_id = - quic::QuicConnectionId(connection_id_bytes, sizeof(connection_id_bytes)); - return std::make_unique<quic::QuicConnection>( - dummy_connection_id, quic::QuicSocketAddress(), dummy_address, helper, - alarm_factory, packet_writer, /* owns_writer */ true, perspective, - quic::ParsedQuicVersionVector{quic::CurrentSupportedVersions()[0]}); -} - -// A dummy helper for a server crypto stream that accepts all client hellos -// and generates a random connection ID. -class DummyCryptoServerStreamHelper - : public quic::QuicCryptoServerStreamBase::Helper { - public: - explicit DummyCryptoServerStreamHelper(quic::QuicRandom* random) {} - - ~DummyCryptoServerStreamHelper() override {} - - bool CanAcceptClientHello(const quic::CryptoHandshakeMessage& message, - const quic::QuicSocketAddress& client_address, - const quic::QuicSocketAddress& peer_address, - const quic::QuicSocketAddress& self_address, - std::string* error_details) const override { - return true; - } -}; -} // namespace - -std::unique_ptr<P2PQuicTransportImpl> P2PQuicTransportImpl::Create( - quic::QuicClock* clock, - quic::QuicAlarmFactory* alarm_factory, - quic::QuicRandom* quic_random, - P2PQuicTransport::Delegate* delegate, - P2PQuicPacketTransport* packet_transport, - const P2PQuicTransportConfig& config, - std::unique_ptr<P2PQuicCryptoConfigFactory> crypto_config_factory, - std::unique_ptr<P2PQuicCryptoStreamFactory> crypto_stream_factory) { - DCHECK(delegate); - DCHECK(packet_transport); - DCHECK(crypto_config_factory); - DCHECK(crypto_stream_factory); - - // The P2PQuicSession owns these chromium specific objects required - // by the QuicConnection. These outlive the QuicConnection itself. - std::unique_ptr<net::QuicChromiumConnectionHelper> helper = - std::make_unique<net::QuicChromiumConnectionHelper>(clock, quic_random); - - P2PQuicPacketWriter* packet_writer = - new P2PQuicPacketWriter(packet_transport); - std::unique_ptr<quic::QuicConnection> quic_connection = CreateQuicConnection( - config.perspective, helper.get(), packet_writer, alarm_factory); - // It's okay for the quic::QuicConnection to have a P2PQuicPacketWriter before - // the P2PQuicPacketWriter is initialized, because the P2QuicPacketWriter - // won't be writable until this occurs. - packet_writer->InitializeWithQuicConnection(quic_connection.get()); - - // QUIC configurations for the session are specified here. - // TODO(shampson): Consider setting larger initial flow control window sizes - // so that the default limit doesn't cause initial undersending. - quic::QuicConfig quic_config; - quic_config.SetMaxBidirectionalStreamsToSend(kMaxIncomingDynamicStreams); - quic_config.SetMaxUnidirectionalStreamsToSend(kMaxIncomingDynamicStreams); - // The handshake network timeouts are configured to large values to prevent - // the QUIC connection from being closed on a slow connection. This can occur - // if signaling is slow and one side begins the handshake early. - // See ICE related bug: bugs.webrtc.org/9869. - // - // This timeout is from time of creation of the quic::QuicConnection object to - // the completion of the handshake. It must be larger than the idle time. - quic_config.set_max_time_before_crypto_handshake( - quic::QuicTime::Delta::FromSeconds(50)); - // This is the timeout for idle time in the handshake. This value allows - // time for slow signaling to complete. - quic_config.set_max_idle_time_before_crypto_handshake( - quic::QuicTime::Delta::FromSeconds(30)); - return std::make_unique<P2PQuicTransportImpl>( - delegate, packet_transport, std::move(config), std::move(helper), - std::move(quic_connection), quic_config, std::move(crypto_config_factory), - std::move(crypto_stream_factory), clock); -} - -P2PQuicTransportImpl::P2PQuicTransportImpl( - Delegate* delegate, - P2PQuicPacketTransport* packet_transport, - const P2PQuicTransportConfig& p2p_transport_config, - std::unique_ptr<quic::QuicConnectionHelperInterface> helper, - std::unique_ptr<quic::QuicConnection> connection, - const quic::QuicConfig& quic_config, - std::unique_ptr<P2PQuicCryptoConfigFactory> crypto_config_factory, - std::unique_ptr<P2PQuicCryptoStreamFactory> crypto_stream_factory, - quic::QuicClock* clock) - : quic::QuicSession(connection.get(), - nullptr /* visitor */, - quic_config, - quic::CurrentSupportedVersions(), - /*expected_num_static_unidirectional_streams = */ 0), - helper_(std::move(helper)), - connection_(std::move(connection)), - crypto_config_factory_(std::move(crypto_config_factory)), - crypto_stream_factory_(std::move(crypto_stream_factory)), - perspective_(p2p_transport_config.perspective), - packet_transport_(packet_transport), - delegate_(delegate), - clock_(clock), - stream_delegate_read_buffer_size_( - p2p_transport_config.stream_delegate_read_buffer_size), - stream_write_buffer_size_(p2p_transport_config.stream_write_buffer_size) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(delegate_); - DCHECK(crypto_config_factory_); - DCHECK(crypto_stream_factory_); - DCHECK(clock_); - DCHECK(packet_transport_); - DCHECK_GT(stream_delegate_read_buffer_size_, 0u); - DCHECK_GT(stream_write_buffer_size_, 0u); - if (!p2p_transport_config.certificates.IsEmpty()) { - // TODO(https://crbug.com/874296): The web API accepts multiple - // certificates, and we might want to pass these down to let QUIC decide on - // what to use. - certificate_ = p2p_transport_config.certificates[0]; - } - switch (perspective_) { - case quic::Perspective::IS_CLIENT: { - crypto_client_config_ = - crypto_config_factory_->CreateClientCryptoConfig(); - break; - } - case quic::Perspective::IS_SERVER: { - crypto_server_config_ = - crypto_config_factory_->CreateServerCryptoConfig(); - break; - } - default: - NOTREACHED(); - break; - } -} - -P2PQuicTransportImpl::~P2PQuicTransportImpl() { - packet_transport_->SetReceiveDelegate(nullptr); -} - -void P2PQuicTransportImpl::Stop() { - // This shouldn't be called before Start(). - DCHECK(crypto_stream_); - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - if (IsClosed()) { - return; - } - // The error code used for the connection closing is - // quic::QUIC_CONNECTION_CANCELLED. This allows us to distinguish that the - // application closed the connection, as opposed to it closing from a - // failure/error. - connection_->CloseConnection( - quic::QuicErrorCode::QUIC_CONNECTION_CANCELLED, kClosingDetails, - quic::ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); -} - -void P2PQuicTransportImpl::Start(StartConfig config) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - // Either the remote fingerprints are being verified or a pre shared key is - // set. - DCHECK((certificate_ && !config.remote_fingerprints.IsEmpty()) || - !config.pre_shared_key.empty()); - DCHECK(!crypto_stream_); - - remote_fingerprints_ = std::move(config.remote_fingerprints); - switch (perspective_) { - case quic::Perspective::IS_CLIENT: { - crypto_client_config_->set_pre_shared_key(config.pre_shared_key); - break; - } - case quic::Perspective::IS_SERVER: { - crypto_server_config_->set_pre_shared_key(config.pre_shared_key); - break; - } - default: - NOTREACHED(); - break; - } - - InitializeCryptoStream(); - - if (perspective_ == quic::Perspective::IS_CLIENT) { - quic::QuicCryptoClientStream* client_crypto_stream = - static_cast<quic::QuicCryptoClientStream*>(crypto_stream_.get()); - client_crypto_stream->CryptoConnect(); - } - // Now that crypto streams are setup we are ready to receive QUIC packets. - packet_transport_->SetReceiveDelegate(this); -} - -void P2PQuicTransportImpl::OnPacketDataReceived(const char* data, - size_t data_len) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - // Received data from the |packet_transport_|. Create a QUIC packet and send - // it to be processed by the QuicSession/Connection. - quic::QuicReceivedPacket packet(data, data_len, clock_->Now()); - ProcessUdpPacket(connection()->self_address(), connection()->peer_address(), - packet); -} - -quic::QuicCryptoStream* P2PQuicTransportImpl::GetMutableCryptoStream() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - return crypto_stream_.get(); -} - -const quic::QuicCryptoStream* P2PQuicTransportImpl::GetCryptoStream() const { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - return crypto_stream_.get(); -} - -P2PQuicStreamImpl* P2PQuicTransportImpl::CreateStream() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - return CreateOutgoingBidirectionalStream(); -} - -P2PQuicTransportStats P2PQuicTransportImpl::GetStats() const { - P2PQuicTransportStats stats(connection_->GetStats()); - stats.num_incoming_streams_created = num_incoming_streams_created_; - stats.num_outgoing_streams_created = num_outgoing_streams_created_; - stats.num_datagrams_lost = num_datagrams_lost_; - return stats; -} - -void P2PQuicTransportImpl::SendDatagram(Vector<uint8_t> datagram) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(CanSendDatagram()); - DCHECK_LT(datagram.size(), - quic::QuicSession::GetCurrentLargestMessagePayload()); - - if (!datagram_buffer_.empty()) { - // We are currently write blocked, just add to the buffer. - datagram_buffer_.push(std::move(datagram)); - return; - } - if (!TrySendDatagram(datagram)) { - datagram_buffer_.push(std::move(datagram)); - } -} - -bool P2PQuicTransportImpl::CanSendDatagram() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - return IsEncryptionEstablished() && - (connection()->version().SupportsMessageFrames()) && !IsClosed(); -} - -P2PQuicStreamImpl* P2PQuicTransportImpl::CreateOutgoingBidirectionalStream() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - num_outgoing_streams_created_++; - P2PQuicStreamImpl* stream = - CreateStreamInternal(GetNextOutgoingBidirectionalStreamId()); - ActivateStream(std::unique_ptr<P2PQuicStreamImpl>(stream)); - return stream; -} - -P2PQuicStreamImpl* P2PQuicTransportImpl::CreateIncomingStream( - quic::QuicStreamId id) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - num_incoming_streams_created_++; - P2PQuicStreamImpl* stream = CreateStreamInternal(id); - ActivateStream(std::unique_ptr<P2PQuicStreamImpl>(stream)); - delegate_->OnStream(stream); - return stream; -} - -P2PQuicStreamImpl* P2PQuicTransportImpl::CreateIncomingStream( - quic::PendingStream* pending) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - num_incoming_streams_created_++; - P2PQuicStreamImpl* stream = CreateStreamInternal(pending); - ActivateStream(std::unique_ptr<P2PQuicStreamImpl>(stream)); - delegate_->OnStream(stream); - return stream; -} - -P2PQuicStreamImpl* P2PQuicTransportImpl::CreateStreamInternal( - quic::QuicStreamId id) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(crypto_stream_); - DCHECK(IsEncryptionEstablished()); - DCHECK(!IsClosed()); - return new P2PQuicStreamImpl(id, this, stream_delegate_read_buffer_size_, - stream_write_buffer_size_); -} - -P2PQuicStreamImpl* P2PQuicTransportImpl::CreateStreamInternal( - quic::PendingStream* pending) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(crypto_stream_); - DCHECK(IsEncryptionEstablished()); - DCHECK(!IsClosed()); - return new P2PQuicStreamImpl(pending, this, stream_delegate_read_buffer_size_, - stream_write_buffer_size_); -} - -bool P2PQuicTransportImpl::TrySendDatagram(Vector<uint8_t>& datagram) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(CanSendDatagram()); - DCHECK_LT(datagram.size(), - quic::QuicSession::GetCurrentLargestMessagePayload()); - - struct iovec iov = {datagram.data(), datagram.size()}; - quic::QuicMemSliceStorage storage( - &iov, 1, connection()->helper()->GetStreamSendBufferAllocator(), - datagram.size()); - quic::MessageResult result = QuicSession::SendMessage(storage.ToSpan()); - switch (result.status) { - case quic::MESSAGE_STATUS_BLOCKED: - return false; - case quic::MESSAGE_STATUS_SUCCESS: - delegate_->OnDatagramSent(); - return true; - case quic::MESSAGE_STATUS_ENCRYPTION_NOT_ESTABLISHED: - case quic::MESSAGE_STATUS_INTERNAL_ERROR: - case quic::MESSAGE_STATUS_TOO_LARGE: - case quic::MESSAGE_STATUS_UNSUPPORTED: - break; - } - // Anything besides blocked/success should never happen. - LOG(ERROR) << "Unexpected result with QuicSession::SendMessage: " - << result.status; - NOTREACHED(); - return false; -} - -void P2PQuicTransportImpl::InitializeCryptoStream() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(!crypto_stream_); - // TODO(shampson): If the P2PQuicTransportImpl is subclassed into a client - // and server class we can call this as a virtual function and not need this - // switch statement. - switch (perspective_) { - case quic::Perspective::IS_CLIENT: { - DCHECK(crypto_client_config_); - crypto_stream_ = crypto_stream_factory_->CreateClientCryptoStream( - /*QuicSession=*/this, crypto_client_config_.get(), - /*ProofHandler=*/this); - QuicSession::Initialize(); - break; - } - case quic::Perspective::IS_SERVER: { - DCHECK(crypto_server_config_); - // Provide server with serialized config string to prove ownership. - quic::QuicCryptoServerConfig::ConfigOptions options; - // The |message| is used to handle the return value of AddDefaultConfig - // which is raw pointer of the CryptoHandshakeMessage. - std::unique_ptr<quic::CryptoHandshakeMessage> message( - crypto_server_config_->AddDefaultConfig( - helper_->GetRandomGenerator(), helper_->GetClock(), options)); - compressed_certs_cache_.reset(new quic::QuicCompressedCertsCache( - quic::QuicCompressedCertsCache::kQuicCompressedCertsCacheSize)); - server_stream_helper_ = std::make_unique<DummyCryptoServerStreamHelper>( - helper_->GetRandomGenerator()); - - crypto_stream_ = crypto_stream_factory_->CreateServerCryptoStream( - crypto_server_config_.get(), compressed_certs_cache_.get(), this, - server_stream_helper_.get()); - QuicSession::Initialize(); - break; - } - default: - NOTREACHED(); - break; - } -} - -void P2PQuicTransportImpl::SetDefaultEncryptionLevel( - quic::EncryptionLevel level) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - QuicSession::SetDefaultEncryptionLevel(level); - if (level == quic::ENCRYPTION_FORWARD_SECURE) { - DCHECK(IsEncryptionEstablished()); - DCHECK(OneRttKeysAvailable()); - P2PQuicNegotiatedParams negotiated_params; - // The guaranteed largest message payload will not change throughout the - // connection. - uint16_t max_datagram_length = - quic::QuicSession::GetGuaranteedLargestMessagePayload(); - if (max_datagram_length > 0) { - // Datagrams are supported in this case. - negotiated_params.set_max_datagram_length(max_datagram_length); - } - delegate_->OnConnected(negotiated_params); - } -} - -void P2PQuicTransportImpl::OnTlsHandshakeComplete() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - QuicSession::OnTlsHandshakeComplete(); - DCHECK(IsEncryptionEstablished()); - DCHECK(OneRttKeysAvailable()); - P2PQuicNegotiatedParams negotiated_params; - // The guaranteed largest message payload will not change throughout the - // connection. - uint16_t max_datagram_length = - quic::QuicSession::GetGuaranteedLargestMessagePayload(); - if (max_datagram_length > 0) { - // Datagrams are supported in this case. - negotiated_params.set_max_datagram_length(max_datagram_length); - } - delegate_->OnConnected(negotiated_params); -} - -void P2PQuicTransportImpl::OnCanWrite() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - while (!datagram_buffer_.empty()) { - if (TrySendDatagram(datagram_buffer_.front())) { - datagram_buffer_.pop(); - } else { - // Keep the message in the buffer to be written when we can write again. - return; - } - } - - // We have successfully sent all buffered datagrams. - QuicSession::OnCanWrite(); -} - -void P2PQuicTransportImpl::OnMessageReceived( - quiche::QuicheStringPiece message) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - // This will never overflow because of the datagram size limit. - Vector<uint8_t> datagram(static_cast<wtf_size_t>(message.size())); - memcpy(datagram.data(), message.data(), message.size()); - delegate_->OnDatagramReceived(std::move(datagram)); -} - -void P2PQuicTransportImpl::OnMessageLost(quic::QuicMessageId message_id) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - num_datagrams_lost_++; -} - -void P2PQuicTransportImpl::OnConnectionClosed( - const quic::QuicConnectionCloseFrame& frame, - quic::ConnectionCloseSource source) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - const quic::QuicErrorCode error = frame.quic_error_code; - const std::string& error_details = frame.error_details; - quic::QuicSession::OnConnectionClosed(frame, source); - if (error != quic::QuicErrorCode::QUIC_CONNECTION_CANCELLED) { - delegate_->OnConnectionFailed( - error_details, source == quic::ConnectionCloseSource::FROM_PEER); - } else if (source == quic::ConnectionCloseSource::FROM_PEER) { - // This connection was closed by the application of the remote side. - delegate_->OnRemoteStopped(); - } -} - -bool P2PQuicTransportImpl::ShouldKeepConnectionAlive() const { - return GetNumActiveStreams() > 0; -} - -bool P2PQuicTransportImpl::IsClosed() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - return !connection_->connected(); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_impl.h b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_impl.h deleted file mode 100644 index 37c38e3..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_impl.h +++ /dev/null
@@ -1,231 +0,0 @@ -// Copyright 2018 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_PEERCONNECTION_ADAPTERS_P2P_QUIC_TRANSPORT_IMPL_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_P2P_QUIC_TRANSPORT_IMPL_H_ - -#include <queue> -#include "base/threading/thread_checker.h" -#include "net/quic/quic_chromium_connection_helper.h" -#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h" -#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h" -#include "net/third_party/quiche/src/quic/core/quic_connection.h" -#include "net/third_party/quiche/src/quic/core/quic_crypto_client_stream.h" -#include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream_base.h" -#include "net/third_party/quiche/src/quic/core/quic_packet_writer.h" -#include "net/third_party/quiche/src/quic/core/quic_session.h" -#include "net/third_party/quiche/src/quic/tools/quic_simple_crypto_server_stream_helper.h" -#include "third_party/blink/renderer/modules/modules_export.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_config_factory.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_stream_factory.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_stream_factory_impl.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_packet_transport.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream_impl.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_factory.h" -#include "third_party/webrtc/rtc_base/rtc_certificate.h" - -namespace blink { - -// The P2PQuicTransportImpl subclasses the quic::QuicSession in order to expose -// QUIC as a P2P transport. This specific subclass implements the crypto -// handshake for a peer to peer connection, which requires verifying the remote -// certificate's fingerprint, but otherwise exposes a raw quic::QuicSession. -// -// At a high level, the quic::QuicConnection manages the actual connection -// between two endpoints, while the quic::QuicSession owns and manages the -// quic::QuicStreams. The quic::QuicSession also handles the negotiation between -// endpoints, session control (reset, window updates, control frames, etc.), and -// callbacks from either the connection (quic::QuicConnectionVisitorInterface), -// frames being acked or lost (quic::SessionNotifierInterface), or handshake -// state changes. -// -// This object should be run entirely on the webrtc worker thread. -class MODULES_EXPORT P2PQuicTransportImpl final - : public quic::QuicSession, - public P2PQuicTransport, - public P2PQuicPacketTransport::ReceiveDelegate, - public quic::QuicCryptoClientStream::ProofHandler { - public: - // Creates the necessary QUIC and Chromium specific objects before - // creating P2PQuicTransportImpl. - static std::unique_ptr<P2PQuicTransportImpl> Create( - quic::QuicClock* clock, - quic::QuicAlarmFactory* alarm_factory, - quic::QuicRandom* quic_random, - Delegate* delegate, - P2PQuicPacketTransport* packet_transport, - const P2PQuicTransportConfig& config, - std::unique_ptr<P2PQuicCryptoConfigFactory> crypto_config_factory, - std::unique_ptr<P2PQuicCryptoStreamFactory> crypto_stream_factory); - - P2PQuicTransportImpl( - Delegate* delegate, - P2PQuicPacketTransport* packet_transport, - const P2PQuicTransportConfig& p2p_transport_config, - std::unique_ptr<quic::QuicConnectionHelperInterface> helper, - std::unique_ptr<quic::QuicConnection> connection, - const quic::QuicConfig& quic_config, - std::unique_ptr<P2PQuicCryptoConfigFactory> crypto_config_factory, - std::unique_ptr<P2PQuicCryptoStreamFactory> crypto_stream_factory, - quic::QuicClock* clock); - - ~P2PQuicTransportImpl() override; - - // P2PQuicTransport overrides. - void Stop() override; - // This handshake is currently insecure in the case of using remote - // fingerprints to verify the remote certificate. For a secure handshake, set - // the pre_shared_key attribute of the |config| before calling this. This - // function must be called before creating any streams. - // - // TODO(https://crbug.com/874300): Verify both the client and server - // certificates with the signaled remote fingerprints. Until the TLS 1.3 - // handshake is supported in the QUIC core library we can only verify the - // server's certificate, but not the client's. - void Start(StartConfig config) override; - // Creates an outgoing stream that is owned by the quic::QuicSession. - P2PQuicStreamImpl* CreateStream() override; - P2PQuicTransportStats GetStats() const override; - // This should not be called until the transport has become connected, and - // cannot be called with a |datagram| larger than the maximum size given in - // GetGuaranteedLargestMessagePayload(). Once the datagram has been sent, - // Delegate::OnDatagramSent will be called. If Delegate::OnDatagramSent is not - // immediately called, it can be assumed that the datagram is buffered due to - // congestion control. - void SendDatagram(Vector<uint8_t> datagram) override; - - // Returns true if a datagram can be sent on the transport. - bool CanSendDatagram(); - - // quic::QuicSession override. - void OnMessageReceived(quiche::QuicheStringPiece message) override; - void OnMessageLost(quic::QuicMessageId message_id) override; - void OnCanWrite() override; - - // P2PQuicPacketTransport::Delegate override. - void OnPacketDataReceived(const char* data, size_t data_len) override; - - // quic::QuicCryptoClientStream::ProofHandler overrides used in a client - // connection to get certificate verification details. - - // Called when the proof verification completes. This information is used - // for 0 RTT handshakes, which isn't relevant for our P2P handshake. - void OnProofValid( - const quic::QuicCryptoClientConfig::CachedState& cached) override {} - - // Called when proof verification become available. - void OnProofVerifyDetailsAvailable( - const quic::ProofVerifyDetails& verify_details) override {} - - // quic::QuicConnectionVisitorInterface overrides. - void OnConnectionClosed(const quic::QuicConnectionCloseFrame& frame, - quic::ConnectionCloseSource source) override; - bool ShouldKeepConnectionAlive() const override; - - protected: - // quic::QuicSession overrides. - // Creates a new stream initiated from the remote side. The caller does not - // own the stream, so the stream is activated and ownership is moved to the - // quic::QuicSession. - P2PQuicStreamImpl* CreateIncomingStream( - quic::QuicStreamId id) override; - P2PQuicStreamImpl* CreateIncomingStream( - quic::PendingStream* pending) override; - - // Creates a new outgoing stream. The caller does not own the - // stream, so the stream is activated and ownership is moved to the - // quic::QuicSession. - P2PQuicStreamImpl* CreateOutgoingBidirectionalStream(); - - void SetDefaultEncryptionLevel(quic::EncryptionLevel level) override; - void OnTlsHandshakeComplete() override; - - private: - // This is for testing connection failures and handshake failures. - friend class P2PQuicTransportTest; - - // These functions are used for testing. - // - // Returns true if the quic::QuicConnection has been closed remotely or - // locally. - bool IsClosed(); - quic::QuicConnection* connection() { return connection_.get(); } - - // quic::QuicSession overrides. - const quic::QuicCryptoStream* GetCryptoStream() const override; - quic::QuicCryptoStream* GetMutableCryptoStream() override; - - // Creates the crypto stream necessary for handshake negotiation, and - // initializes the parent class (quic::QuicSession). This must be called on - // both sides before communicating between endpoints (Start, Close, etc.). - void InitializeCryptoStream(); - - // Creates a new stream. This helper function is used when we need to create - // a new incoming stream or outgoing stream. - P2PQuicStreamImpl* CreateStreamInternal(quic::QuicStreamId id); - P2PQuicStreamImpl* CreateStreamInternal(quic::PendingStream* pending); - - // Returns true if datagram was sent, false if it was not because of - // congestion control blocking. - bool TrySendDatagram(Vector<uint8_t>& datagram); - - // The server_config and client_config are used for setting up the crypto - // connection. The ownership of these objects or the objects they own - // (quic::ProofSource, quic::ProofVerifier, etc.), are not passed on to the - // QUIC library for the handshake, so we must own them here. A client - // |perspective_| will not have a crypto_server_config and vice versa. - std::unique_ptr<quic::QuicCryptoServerConfig> crypto_server_config_; - std::unique_ptr<quic::QuicCryptoClientConfig> crypto_client_config_; - // Used by server |crypto_stream_| to track most recently compressed certs. - std::unique_ptr<quic::QuicCompressedCertsCache> compressed_certs_cache_; - std::unique_ptr<quic::QuicCryptoServerStreamBase::Helper> - server_stream_helper_; - // Owned by the P2PQuicTransportImpl. |helper_| is placed before - // |connection_| to ensure it outlives it. - std::unique_ptr<quic::QuicConnectionHelperInterface> helper_; - - std::unique_ptr<quic::QuicConnection> connection_; - - // Used to create either a crypto client or server config. - std::unique_ptr<P2PQuicCryptoConfigFactory> crypto_config_factory_; - // Used to create a client or server crypto stream. - std::unique_ptr<P2PQuicCryptoStreamFactory> crypto_stream_factory_; - - std::unique_ptr<quic::QuicCryptoStream> crypto_stream_; - // Crypto certificate information. Note that currently the handshake is - // insecure and these are not used... - rtc::scoped_refptr<rtc::RTCCertificate> certificate_; - Vector<std::unique_ptr<rtc::SSLFingerprint>> remote_fingerprints_; - - bool pre_shared_key_set_ = false; - - quic::Perspective perspective_; - // Outlives the P2PQuicTransport. - P2PQuicPacketTransport* packet_transport_; - P2PQuicTransport::Delegate* delegate_ = nullptr; - // Owned by whatever creates the P2PQuicTransportImpl. The |clock_| needs to - // outlive the P2PQuicTransportImpl. - quic::QuicClock* clock_ = nullptr; - // The size of the stream delegate's read buffer, used when creating - // P2PQuicStreams. - uint32_t stream_delegate_read_buffer_size_; - // Determines the size of the write buffer when P2PQuicStreams. - uint32_t stream_write_buffer_size_; - - // For stats: - uint32_t num_outgoing_streams_created_ = 0; - uint32_t num_incoming_streams_created_ = 0; - // The number reported lost on the network by the quic::QuicSession. - uint32_t num_datagrams_lost_ = 0; - - // Datagrams not yet sent due to congestion control blocking. - std::queue<Vector<uint8_t>> datagram_buffer_; - - THREAD_CHECKER(thread_checker_); -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_P2P_QUIC_TRANSPORT_IMPL_H_
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_stats.cc b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_stats.cc deleted file mode 100644 index edc88dd..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_stats.cc +++ /dev/null
@@ -1,37 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_stats.h" - -namespace blink { - -P2PQuicTransportStats::P2PQuicTransportStats() - : timestamp(base::TimeTicks::Now()) {} - -P2PQuicTransportStats::P2PQuicTransportStats( - const quic::QuicConnectionStats& quic_stats) - : timestamp(base::TimeTicks::Now()), - bytes_sent(quic_stats.bytes_sent), - packets_sent(quic_stats.packets_sent), - stream_bytes_sent(quic_stats.stream_bytes_sent), - stream_bytes_received(quic_stats.stream_bytes_received), - bytes_received(quic_stats.bytes_received), - packets_received(quic_stats.packets_received), - packets_processed(quic_stats.packets_processed), - bytes_retransmitted(quic_stats.bytes_retransmitted), - packets_retransmitted(quic_stats.packets_retransmitted), - packets_lost(quic_stats.packets_lost), - packets_dropped(quic_stats.packets_dropped), - crypto_retransmit_count(quic_stats.crypto_retransmit_count), - min_rtt_us(quic_stats.min_rtt_us), - srtt_us(quic_stats.srtt_us), - max_packet_size(quic_stats.max_packet_size), - max_received_packet_size(quic_stats.max_received_packet_size), - estimated_bandwidth_bps(quic_stats.estimated_bandwidth.ToBitsPerSecond()), - packets_reordered(quic_stats.packets_reordered), - blocked_frames_received(quic_stats.blocked_frames_received), - blocked_frames_sent(quic_stats.blocked_frames_sent), - connectivity_probing_packets_received( - quic_stats.num_connectivity_probing_received) {} -} // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_stats.h b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_stats.h deleted file mode 100644 index 0a4d2d4..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_stats.h +++ /dev/null
@@ -1,81 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_P2P_QUIC_TRANSPORT_STATS_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_P2P_QUIC_TRANSPORT_STATS_H_ - -#include "base/time/time.h" -#include "net/third_party/quiche/src/quic/core/quic_connection_stats.h" -#include "third_party/blink/renderer/modules/modules_export.h" - -namespace blink { - -// These are stats associated with the P2PQuicTransport object. These -// stats are mostly copied from quic::QuicConnectionStats, which includes -// stats for a quic::QuicConnection. These are connection level stats. -// Currently QUIC does not have stats at the stream level. -struct MODULES_EXPORT P2PQuicTransportStats { - P2PQuicTransportStats(); - // Note: The following stats are ignored from the QuicConnectionStats: - // -packets_spuriously_retransmitted - // -bytes_spuriously_retransmitted - // -slowstart_packets_sent - // -slowstart_packets_lost - // -slowstart_bytes_lost - // -loss_timeout_count - // -tlp_count - // -rto_count - // -max_sequence_reordering - // -max_time_reordering_us - // -tcp_loss_events - // -connection_creation_time - explicit P2PQuicTransportStats(const quic::QuicConnectionStats& stats); - ~P2PQuicTransportStats() = default; - - base::TimeTicks timestamp; - // |bytes_sent| includes retransmissions. - uint64_t bytes_sent = 0; - uint64_t packets_sent = 0; - // |stream_bytes_sent| does not include retransmissions. - uint64_t stream_bytes_sent = 0; - uint64_t stream_bytes_received = 0; - - // These include version negotiation and public reset packets. - // - // |bytes_received| includes duplicate data for a stream. - uint64_t bytes_received = 0; - // |packets_received| includes packets which were not processable. - uint64_t packets_received = 0; - uint64_t packets_processed = 0; - - uint64_t bytes_retransmitted = 0; - uint64_t packets_retransmitted = 0; - // Number of packets abandoned as lost by the loss detection algorithm. - uint64_t packets_lost = 0; - uint64_t packets_dropped = 0; - size_t crypto_retransmit_count = 0; - // Minimum RTT in microseconds. - uint64_t min_rtt_us = 0; - // Smoothed RTT in microseconds. - uint64_t srtt_us = 0; - uint64_t max_packet_size = 0; - uint64_t max_received_packet_size = 0; - // Bits per second. - uint64_t estimated_bandwidth_bps = 0; - // Reordering stats for received packets. - // Number of packets received out of packet number order. - uint64_t packets_reordered = 0; - uint64_t blocked_frames_received = 0; - uint64_t blocked_frames_sent = 0; - // Number of connectivity probing packets received by this connection. - uint64_t connectivity_probing_packets_received = 0; - - // The following are stats not taken directly from QuicConnectionStats: - uint32_t num_outgoing_streams_created = 0; - uint32_t num_incoming_streams_created = 0; - uint32_t num_datagrams_lost = 0; -}; -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_P2P_QUIC_TRANSPORT_STATS_H_
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_test.cc b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_test.cc deleted file mode 100644 index e6a4615..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_test.cc +++ /dev/null
@@ -1,1538 +0,0 @@ -// Copyright 2018 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/peerconnection/adapters/p2p_quic_transport.h" -#include "base/bind.h" -#include "net/quic/mock_crypto_client_stream.h" -#include "net/quic/mock_crypto_client_stream_factory.h" -#include "net/quic/quic_chromium_alarm_factory.h" -#include "net/quic/test_task_runner.h" -#include "net/test/gtest_util.h" -#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h" -#include "net/third_party/quiche/src/quic/core/crypto/proof_verifier.h" -#include "net/third_party/quiche/src/quic/core/crypto/quic_compressed_certs_cache.h" -#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h" -#include "net/third_party/quiche/src/quic/core/quic_circular_deque.h" -#include "net/third_party/quiche/src/quic/core/quic_server_id.h" -#include "net/third_party/quiche/src/quic/core/quic_session.h" -#include "net/third_party/quiche/src/quic/platform/api/quic_mem_slice_span.h" -#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h" -#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h" -#include "third_party/blink/public/platform/web_vector.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_config_factory_impl.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_stream_factory_impl.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_packet_transport.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_factory_impl.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_impl.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/test/mock_p2p_quic_packet_transport.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/test/mock_p2p_quic_stream_delegate.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/test/mock_p2p_quic_transport_delegate.h" -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" -#include "third_party/webrtc/rtc_base/rtc_certificate.h" -#include "third_party/webrtc/rtc_base/ssl_fingerprint.h" -#include "third_party/webrtc/rtc_base/ssl_identity.h" - -namespace blink { - -namespace { - -using testing::_; -using testing::ElementsAreArray; -using testing::Eq; -using testing::Invoke; -using testing::InvokeWithoutArgs; -using ::testing::MakePolymorphicAction; -using ::testing::PolymorphicAction; -using testing::Property; -using testing::ResultOf; -using testing::Return; - -const uint8_t kTriggerRemoteStreamPhrase[] = {'o', 'p', 'e', 'n', ' ', 's', - 'e', 's', 'a', 'm', 'e'}; -const uint8_t kMessage[] = {'h', 'o', 'w', 'd', 'y'}; -const uint8_t kMessage2[] = {'p', 'a', 'r', 't', 'n', 'e', 'r'}; -const uint8_t kClientMessage[] = {'h', 'o', 'w', 'd', 'y'}; -const uint8_t kServerMessage[] = {'p', 'a', 'r', 't', 'n', 'e', 'r'}; -const uint32_t kTransportWriteBufferSize = 100 * 1024; -const uint32_t kTransportDelegateReadBufferSize = 100 * 1024; - -template <wtf_size_t Size> -static Vector<uint8_t> VectorFromArray(const uint8_t (&array)[Size]) { - Vector<uint8_t> vector; - vector.Append(array, Size); - return vector; -} - -// A custom gmock Action that fires the given callback. This is used in -// conjuction with the CallbackRunLoop in order to drive the TestTaskRunner -// until callbacks are fired. For example: -// CallbackRunLoop run_loop(runner()); -// EXPECT_CALL(&object, foo()) -// .WillOnce(FireCallback(run_loop.CreateCallback())); -// run_loop.RunUntilCallbacksFired(task_runner); -class FireCallbackAction { - STACK_ALLOCATED(); - - public: - FireCallbackAction(base::RepeatingCallback<void()> callback) - : callback_(callback) {} - - template <typename Result, typename ArgumentTuple> - Result Perform(const ArgumentTuple& args) const { - callback_.Run(); - } - - private: - base::RepeatingCallback<void()> callback_; -}; - -// Returns the custom gmock PolymorphicAction created from the -// FireCallbackAction above. -PolymorphicAction<FireCallbackAction> FireCallback( - base::RepeatingCallback<void()> callback) { - return MakePolymorphicAction(FireCallbackAction(callback)); -} - -// A helper object that can drive a TestTaskRunner's tasks, until -// callbacks are fired. -// -// TODO(https://crbug.com/874296): If the test files get moved to the platform -// directory we will run the tests in a different test environment. In that -// case it will make more sense to use the TestCompletionCallback and the -// RunLoop for driving the test. -class CallbackRunLoop { - STACK_ALLOCATED(); - - public: - CallbackRunLoop(scoped_refptr<net::test::TestTaskRunner> task_runner) - : task_runner_(task_runner) {} - - // Drives the run loop until all created callbacks have been fired. - // This is done using the |task_runner_|, which runs the tasks - // in the correct order and then advances the quic::MockClock to the time the - // task is run. - void RunUntilCallbacksFired() { - while (callback_counter_ != 0) { - ASSERT_GT(task_runner_->GetPostedTasks().size(), 0u); - task_runner_->RunNextTask(); - } - } - - // Creates a callback and increments the |callback_counter_|. The callback, - // when fired, will decrement the counter. This callback must only - // be Run() once (it is a RepeatingCallback because MakePolymorphicAction() - // requires that the action is COPYABLE). - base::RepeatingCallback<void()> CreateCallback() { - callback_counter_++; - return base::BindRepeating(&CallbackRunLoop::OnCallbackFired, - base::Unretained(this)); - } - - private: - void OnCallbackFired() { callback_counter_--; } - - scoped_refptr<net::test::TestTaskRunner> task_runner_; - // Incremented when a callback is created and decremented when the returned - // callback is later Run(). - size_t callback_counter_ = 0; -}; - -// This is a fake packet transport to be used by the P2PQuicTransportImpl. It -// allows to easily connect two packet transports together. We send packets -// asynchronously, by using the same alarm factory that is being used for the -// underlying QUIC library. -class FakePacketTransport : public P2PQuicPacketTransport, - public quic::QuicAlarm::Delegate { - public: - FakePacketTransport(quic::QuicAlarmFactory* alarm_factory, - quic::MockClock* clock) - : alarm_(alarm_factory->CreateAlarm(new AlarmDelegate(this))), - clock_(clock) {} - ~FakePacketTransport() override { - // The write observer should be unset when it is destroyed. - DCHECK(!write_observer_); - } - - // Called by QUIC for writing data to the other side. The flow for writing a - // packet is P2PQuicTransportImpl --> quic::QuicConnection --> - // quic::QuicPacketWriter --> FakePacketTransport. In this case the - // FakePacketTransport just writes directly to the FakePacketTransport on the - // other side. - int WritePacket(const QuicPacket& packet) override { - // For the test there should always be a peer_packet_transport_ connected at - // this point. - if (!peer_packet_transport_) { - return 0; - } - last_packet_num_ = packet.packet_number; - packet_queue_.emplace_back(packet.buffer, packet.buf_len); - alarm_->Cancel(); - // We don't want get 0 RTT. - alarm_->Set(clock_->Now() + quic::QuicTime::Delta::FromMicroseconds(10)); - - return packet.buf_len; - } - - // Sets the P2PQuicTransportImpl as the delegate. - void SetReceiveDelegate( - P2PQuicPacketTransport::ReceiveDelegate* delegate) override { - // We can't set two ReceiveDelegates for one packet transport. - DCHECK(!delegate_ || !delegate); - delegate_ = delegate; - } - - void SetWriteObserver( - P2PQuicPacketTransport::WriteObserver* write_observer) override { - // We can't set two WriteObservers for one packet transport. - DCHECK(!write_observer_ || !write_observer); - write_observer_ = write_observer; - } - - bool Writable() override { return true; } - - // Connects the other FakePacketTransport, so we can write to the peer. - void ConnectPeerTransport(FakePacketTransport* peer_packet_transport) { - DCHECK(!peer_packet_transport_); - peer_packet_transport_ = peer_packet_transport; - } - - // Disconnects the delegate, so we no longer write to it. The test must call - // this before destructing either of the packet transports! - void DisconnectPeerTransport(FakePacketTransport* peer_packet_transport) { - DCHECK(peer_packet_transport_ == peer_packet_transport); - peer_packet_transport_ = nullptr; - } - - // The callback used in order for us to communicate between - // FakePacketTransports. - void OnDataReceivedFromPeer(const char* data, size_t data_len) { - DCHECK(delegate_); - delegate_->OnPacketDataReceived(data, data_len); - } - - uint64_t last_packet_num() { return last_packet_num_; } - - private: - // Wraps the FakePacketTransport so that we can pass in a raw pointer that can - // be reference counted when calling CreateAlarm(). - class AlarmDelegate : public quic::QuicAlarm::Delegate { - public: - explicit AlarmDelegate(FakePacketTransport* packet_transport) - : packet_transport_(packet_transport) {} - - void OnAlarm() override { packet_transport_->OnAlarm(); } - - private: - FakePacketTransport* packet_transport_; - }; - - // Called when we should write any buffered data. - void OnAlarm() override { - // Send the data to the peer at this point. - peer_packet_transport_->OnDataReceivedFromPeer( - packet_queue_.front().c_str(), packet_queue_.front().length()); - packet_queue_.pop_front(); - - // If there's more packets to be sent out, reset the alarm to send it as the - // next task. - if (!packet_queue_.empty()) { - alarm_->Cancel(); - alarm_->Set(clock_->Now()); - } - } - // If async, packets are queued here to send. - quic::QuicCircularDeque<std::string> packet_queue_; - // Alarm used to send data asynchronously. - quic::QuicArenaScopedPtr<quic::QuicAlarm> alarm_; - // The P2PQuicTransportImpl, which sets itself as the delegate in its - // constructor. After receiving data it forwards it along to QUIC. - P2PQuicPacketTransport::ReceiveDelegate* delegate_ = nullptr; - - // The P2PQuicPacketWriter, which sets itself as a write observer - // during the P2PQuicTransportFactoryImpl::CreateQuicTransport. It is - // owned by the QuicConnection and will - P2PQuicPacketTransport::WriteObserver* write_observer_ = nullptr; - - // The other FakePacketTransport that we are writing to. It's the - // responsibility of the test to disconnect this delegate - // (set_delegate(nullptr);) before it is destructed. - FakePacketTransport* peer_packet_transport_ = nullptr; - uint64_t last_packet_num_; - quic::MockClock* clock_; -}; - -// A helper class to bundle test objects together. It keeps track of the -// P2PQuicTransport, P2PQuicStream and the associated delegate objects. This -// also keeps track of when callbacks are expected on the delegate objects, -// which allows running the TestTaskRunner tasks until they have been fired. -class QuicPeerForTest { - USING_FAST_MALLOC(QuicPeerForTest); - - public: - QuicPeerForTest( - std::unique_ptr<FakePacketTransport> packet_transport, - std::unique_ptr<MockP2PQuicTransportDelegate> quic_transport_delegate, - std::unique_ptr<P2PQuicTransportImpl> quic_transport, - rtc::scoped_refptr<rtc::RTCCertificate> certificate) - : packet_transport_(std::move(packet_transport)), - quic_transport_delegate_(std::move(quic_transport_delegate)), - quic_transport_(std::move(quic_transport)), - certificate_(certificate) {} - - // A helper that creates a stream and creates and attaches a delegate. - void CreateStreamWithDelegate() { - stream_ = quic_transport_->CreateStream(); - stream_delegate_ = std::make_unique<MockP2PQuicStreamDelegate>(); - stream_->SetDelegate(stream_delegate_.get()); - stream_id_ = stream_->id(); - } - - // When a remote stream is created via P2PQuicTransport::Delegate::OnStream, - // this is called to set the stream. - void SetStreamAndDelegate( - P2PQuicStreamImpl* stream, - std::unique_ptr<MockP2PQuicStreamDelegate> stream_delegate) { - DCHECK(stream); - stream_ = stream; - stream_id_ = stream->id(); - stream_delegate_ = std::move(stream_delegate); - } - - FakePacketTransport* packet_transport() { return packet_transport_.get(); } - - MockP2PQuicTransportDelegate* quic_transport_delegate() { - return quic_transport_delegate_.get(); - } - - P2PQuicTransportImpl* quic_transport() { return quic_transport_.get(); } - - rtc::scoped_refptr<rtc::RTCCertificate> certificate() { return certificate_; } - - P2PQuicStreamImpl* stream() const { return stream_; } - - MockP2PQuicStreamDelegate* stream_delegate() const { - return stream_delegate_.get(); - } - - quic::QuicStreamId stream_id() const { return stream_id_; } - - private: - std::unique_ptr<FakePacketTransport> packet_transport_; - std::unique_ptr<MockP2PQuicTransportDelegate> quic_transport_delegate_; - // The corresponding delegate to |stream_|. - std::unique_ptr<MockP2PQuicStreamDelegate> stream_delegate_ = nullptr; - // Created as a result of CreateStreamWithDelegate() or RemoteStreamCreated(). - // Owned by the |quic_transport_|. - P2PQuicStreamImpl* stream_ = nullptr; - // The corresponding ID for |stream_|. This can be used to check if the stream - // is closed at the transport level (after the stream object could be - // deleted). - quic::QuicStreamId stream_id_; - std::unique_ptr<P2PQuicTransportImpl> quic_transport_; - rtc::scoped_refptr<rtc::RTCCertificate> certificate_; -}; - -rtc::scoped_refptr<rtc::RTCCertificate> CreateTestCertificate() { - rtc::KeyParams params; - - return rtc::RTCCertificate::Create( - rtc::SSLIdentity::Create("dummy_certificate", params)); -} - -// Allows faking a failing handshake. -class FailingProofVerifierStub : public quic::ProofVerifier { - public: - FailingProofVerifierStub() {} - ~FailingProofVerifierStub() override {} - - // ProofVerifier override. - quic::QuicAsyncStatus VerifyProof( - const std::string& hostname, - const uint16_t port, - const std::string& server_config, - quic::QuicTransportVersion transport_version, - quiche::QuicheStringPiece chlo_hash, - const std::vector<std::string>& certs, - const std::string& cert_sct, - const std::string& signature, - const quic::ProofVerifyContext* context, - std::string* error_details, - std::unique_ptr<quic::ProofVerifyDetails>* verify_details, - std::unique_ptr<quic::ProofVerifierCallback> callback) override { - return quic::QUIC_FAILURE; - } - - quic::QuicAsyncStatus VerifyCertChain( - const std::string& hostname, - const uint16_t port, - const std::vector<std::string>& certs, - const std::string& ocsp_response, - const std::string& cert_sct, - const quic::ProofVerifyContext* context, - std::string* error_details, - std::unique_ptr<quic::ProofVerifyDetails>* details, - std::unique_ptr<quic::ProofVerifierCallback> callback) override { - return quic::QUIC_FAILURE; - } - - std::unique_ptr<quic::ProofVerifyContext> CreateDefaultContext() override { - return nullptr; - } -}; - -// A dummy implementation of a quic::ProofSource. -class ProofSourceStub : public quic::ProofSource { - public: - ProofSourceStub() {} - ~ProofSourceStub() override {} - - // ProofSource override. - void GetProof(const quic::QuicSocketAddress& server_addr, - const quic::QuicSocketAddress& client_addr, - const std::string& hostname, - const std::string& server_config, - quic::QuicTransportVersion transport_version, - quiche::QuicheStringPiece chlo_hash, - std::unique_ptr<Callback> callback) override { - quic::QuicCryptoProof proof; - proof.signature = "Test signature"; - proof.leaf_cert_scts = "Test timestamp"; - callback->Run(true, GetCertChain(server_addr, client_addr, hostname), proof, - nullptr /* details */); - } - - quic::QuicReferenceCountedPointer<Chain> GetCertChain( - const quic::QuicSocketAddress& server_address, - const quic::QuicSocketAddress& client_address, - const std::string& hostname) override { - WebVector<std::string> certs; - certs.emplace_back("Test cert"); - return quic::QuicReferenceCountedPointer<Chain>( - new ProofSource::Chain(certs.ReleaseVector())); - } - void ComputeTlsSignature( - const quic::QuicSocketAddress& server_address, - const quic::QuicSocketAddress& client_address, - const std::string& hostname, - uint16_t signature_algorithm, - quiche::QuicheStringPiece in, - std::unique_ptr<SignatureCallback> callback) override { - callback->Run(true, "Test signature", nullptr); - } - - TicketCrypter* GetTicketCrypter() override { return nullptr; } -}; - -// Creates crypto configs that will fail a QUIC handshake. -class FailingQuicCryptoConfigFactory final : public P2PQuicCryptoConfigFactory { - public: - FailingQuicCryptoConfigFactory(quic::QuicRandom* quic_random) - : quic_random_(quic_random) {} - - std::unique_ptr<quic::QuicCryptoClientConfig> CreateClientCryptoConfig() - override { - return std::make_unique<quic::QuicCryptoClientConfig>( - std::make_unique<FailingProofVerifierStub>()); - } - - std::unique_ptr<quic::QuicCryptoServerConfig> CreateServerCryptoConfig() - override { - return std::make_unique<quic::QuicCryptoServerConfig>( - quic::QuicCryptoServerConfig::TESTING, quic_random_, - std::make_unique<ProofSourceStub>(), - quic::KeyExchangeSource::Default()); - } - - private: - quic::QuicRandom* quic_random_; -}; - -// A CryptoClientStream that bypasses the QUIC handshake and becomes connected. -class ConnectedCryptoClientStream final : public quic::QuicCryptoClientStream { - public: - ConnectedCryptoClientStream( - const quic::QuicServerId& server_id, - quic::QuicSession* session, - std::unique_ptr<quic::ProofVerifyContext> verify_context, - quic::QuicCryptoClientConfig* crypto_config, - quic::QuicCryptoClientStream::ProofHandler* proof_handler) - : quic::QuicCryptoClientStream(server_id, - session, - std::move(verify_context), - crypto_config, - proof_handler, - /*has_application_state = */ true), - session_(session) {} - ~ConnectedCryptoClientStream() override {} - - bool CryptoConnect() override { - encryption_established_ = true; - handshake_confirmed_ = true; - // quic::QuicSession checks that its config has been negotiated after the - // handshake has been confirmed. The easiest way to fake negotiated values - // is to have the config object process a hello message. - quic::QuicConfig config; - config.SetBytesForConnectionIdToSend(quic::PACKET_8BYTE_CONNECTION_ID); - config.SetMaxBidirectionalStreamsToSend( - quic::kDefaultMaxStreamsPerConnection / 2); - config.SetMaxUnidirectionalStreamsToSend( - quic::kDefaultMaxStreamsPerConnection / 2); - quic::CryptoHandshakeMessage message; - config.ToHandshakeMessage(&message, - session()->connection()->transport_version()); - std::string error_details; - session()->config()->ProcessPeerHello(message, quic::CLIENT, - &error_details); - session()->OnConfigNegotiated(); - if (session()->version().UsesTls()) { - session()->OnTlsHandshakeComplete(); - } else { - session()->SetDefaultEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE); - } - session()->DiscardOldEncryptionKey(quic::ENCRYPTION_INITIAL); - session()->NeuterHandshakeData(); - return true; - } - - quic::QuicSession* session() { return session_; } - - bool encryption_established() const override { - return encryption_established_; - } - - bool one_rtt_keys_available() const override { return handshake_confirmed_; } - - private: - bool encryption_established_ = false; - bool handshake_confirmed_ = false; - // Outlives this object. - quic::QuicSession* session_; -}; - -// A P2PQuicCryptoStream factory that uses a ConnectedCryptoClientStream -// test object that can fake a successful connection. -class ConnectedCryptoClientStreamFactory final - : public P2PQuicCryptoStreamFactory { - public: - ~ConnectedCryptoClientStreamFactory() override {} - - std::unique_ptr<quic::QuicCryptoClientStream> CreateClientCryptoStream( - quic::QuicSession* session, - quic::QuicCryptoClientConfig* crypto_config, - quic::QuicCryptoClientStream::ProofHandler* proof_handler) override { - quic::QuicServerId server_id("dummy_host", 12345); - return std::make_unique<ConnectedCryptoClientStream>( - server_id, session, - crypto_config->proof_verifier()->CreateDefaultContext(), crypto_config, - proof_handler); - } - - // Creates a real quic::QuiCryptoServerStream. - std::unique_ptr<quic::QuicCryptoServerStreamBase> CreateServerCryptoStream( - const quic::QuicCryptoServerConfig* crypto_config, - quic::QuicCompressedCertsCache* compressed_certs_cache, - quic::QuicSession* session, - quic::QuicCryptoServerStreamBase::Helper* helper) override { - return quic::CreateCryptoServerStream(crypto_config, compressed_certs_cache, - session, helper); - } -}; - -} // namespace - -// Unit tests for the P2PQuicTransport, using an underlying fake packet -// transport that sends packets directly between endpoints. This also tests -// P2PQuicStreams for test cases that involve two streams connected between -// separate endpoints. This is because the P2PQuicStream is highly coupled to -// the P2PQuicSession for communicating between endpoints, so we would like to -// test it with the real session object. -// -// The test is driven using the quic::TestTaskRunner to run posted tasks until -// callbacks have been fired. -class P2PQuicTransportTest : public testing::Test { - public: - P2PQuicTransportTest() { - // TODO(crbug/1070747): Fix tests for IETF QUIC. - quic::test::DisableQuicVersionsWithTls(); - // Quic crashes if packets are sent at time 0, and the clock defaults to 0. - clock_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(1000)); - quic_random_ = quic::QuicRandom::GetInstance(); - runner_ = base::MakeRefCounted<net::test::TestTaskRunner>(&clock_); - alarm_factory_ = - std::make_unique<net::QuicChromiumAlarmFactory>(runner_.get(), &clock_); - } - - ~P2PQuicTransportTest() override { - // This must be done before desctructing the transports so that we don't - // have any dangling pointers. - client_peer_->packet_transport()->DisconnectPeerTransport( - server_peer_->packet_transport()); - server_peer_->packet_transport()->DisconnectPeerTransport( - client_peer_->packet_transport()); - } - - // Supplying the |client_crypto_factory| and |server_crypto_factory| allows - // testing a failing QUIC handshake. The |client_certificate| and - // |server_certificate| must be the same certificates used in the crypto - // factories. - void Initialize( - std::unique_ptr<P2PQuicCryptoConfigFactory> client_crypto_factory, - std::unique_ptr<P2PQuicCryptoConfigFactory> server_crypto_factory) { - auto client_packet_transport = - std::make_unique<FakePacketTransport>(alarm_factory_.get(), &clock_); - auto server_packet_transport = - std::make_unique<FakePacketTransport>(alarm_factory_.get(), &clock_); - // Connect the transports so that they can speak to each other. - client_packet_transport->ConnectPeerTransport( - server_packet_transport.get()); - server_packet_transport->ConnectPeerTransport( - client_packet_transport.get()); - - rtc::scoped_refptr<rtc::RTCCertificate> client_certificate = - CreateTestCertificate(); - auto client_quic_transport_delegate = - std::make_unique<MockP2PQuicTransportDelegate>(); - P2PQuicTransportConfig client_config( - quic::Perspective::IS_CLIENT, {client_certificate}, - kTransportDelegateReadBufferSize, kTransportWriteBufferSize); - - std::unique_ptr<P2PQuicTransportImpl> client_quic_transport = - P2PQuicTransportImpl::Create( - &clock_, alarm_factory_.get(), quic_random_, - client_quic_transport_delegate.get(), client_packet_transport.get(), - client_config, std::move(client_crypto_factory), - std::make_unique<P2PQuicCryptoStreamFactoryImpl>()); - - client_peer_ = std::make_unique<QuicPeerForTest>( - std::move(client_packet_transport), - std::move(client_quic_transport_delegate), - std::move(client_quic_transport), client_certificate); - - auto server_quic_transport_delegate = - std::make_unique<MockP2PQuicTransportDelegate>(); - - rtc::scoped_refptr<rtc::RTCCertificate> server_certificate = - CreateTestCertificate(); - P2PQuicTransportConfig server_config( - quic::Perspective::IS_SERVER, {server_certificate}, - kTransportDelegateReadBufferSize, kTransportWriteBufferSize); - - std::unique_ptr<P2PQuicTransportImpl> server_quic_transport = - P2PQuicTransportImpl::Create( - &clock_, alarm_factory_.get(), quic_random_, - server_quic_transport_delegate.get(), server_packet_transport.get(), - server_config, std::move(server_crypto_factory), - std::make_unique<P2PQuicCryptoStreamFactoryImpl>()); - - server_peer_ = std::make_unique<QuicPeerForTest>( - std::move(server_packet_transport), - std::move(server_quic_transport_delegate), - std::move(server_quic_transport), server_certificate); - } - - // Connects both peer's underlying packet transports and creates both - // P2PQuicTransportImpls. - void Initialize() { - Initialize(std::make_unique<P2PQuicCryptoConfigFactoryImpl>(quic_random_), - std::make_unique<P2PQuicCryptoConfigFactoryImpl>(quic_random_)); - } - - // Uses a crypto config factory that returns a client configuration that - // will reject the QUIC handshake. This lets us simulate a failng handshake. - void InitializeWithFailingProofVerification() { - Initialize(std::make_unique<FailingQuicCryptoConfigFactory>(quic_random_), - std::make_unique<FailingQuicCryptoConfigFactory>(quic_random_)); - } - - // Drives the test by running the current tasks that are posted. - void RunCurrentTasks() { - size_t posted_tasks_size = runner_->GetPostedTasks().size(); - for (size_t i = 0; i < posted_tasks_size; ++i) { - runner_->RunNextTask(); - } - } - - // Sets up an initial handshake and connection between peers. - // This is done using a pre shared key. - void Connect() { - CallbackRunLoop run_loop(runner()); - EXPECT_CALL(*client_peer_->quic_transport_delegate(), OnConnected(_)) - .WillOnce(FireCallback(run_loop.CreateCallback())); - EXPECT_CALL(*server_peer_->quic_transport_delegate(), OnConnected(_)) - .WillOnce(FireCallback(run_loop.CreateCallback())); - - server_peer_->quic_transport()->Start( - P2PQuicTransport::StartConfig("foobar")); - client_peer_->quic_transport()->Start( - P2PQuicTransport::StartConfig("foobar")); - run_loop.RunUntilCallbacksFired(); - } - - // Creates a P2PQuicStreamImpl on both the client and server side that are - // connected to each other. The client's stream is created with - // P2PQuicTransport::CreateStream, while the server's stream is initiated from - // the remote (client) side, with P2PQuicStream::Delegate::OnStream. This - // allows us to test at an integration level with connected streams. - void SetupConnectedStreams() { - CallbackRunLoop run_loop(runner()); - // We must already have a secure connection before streams are created. - ASSERT_TRUE(client_peer_->quic_transport()->IsEncryptionEstablished()); - ASSERT_TRUE(server_peer_->quic_transport()->IsEncryptionEstablished()); - - client_peer_->CreateStreamWithDelegate(); - ASSERT_TRUE(client_peer_->stream()); - ASSERT_TRUE(client_peer_->stream_delegate()); - - // Send some data to trigger the remote side (server side) to get an - // incoming stream. We capture the stream and set it's delegate when - // OnStream gets called on the mock object. - base::RepeatingCallback<void()> callback = run_loop.CreateCallback(); - QuicPeerForTest* server_peer_ptr = server_peer_.get(); - MockP2PQuicStreamDelegate* stream_delegate = - new MockP2PQuicStreamDelegate(); - P2PQuicStream* server_stream; - EXPECT_CALL(*server_peer_->quic_transport_delegate(), OnStream(_)) - .WillOnce(Invoke([&callback, &server_stream, - &stream_delegate](P2PQuicStream* stream) { - stream->SetDelegate(stream_delegate); - server_stream = stream; - callback.Run(); - })); - - client_peer_->stream()->WriteData( - VectorFromArray(kTriggerRemoteStreamPhrase), - /*fin=*/false); - run_loop.RunUntilCallbacksFired(); - // Set the stream and delegate to the |server_peer_|, so that it can be - // accessed by tests later. - server_peer_ptr->SetStreamAndDelegate( - static_cast<P2PQuicStreamImpl*>(server_stream), - std::unique_ptr<MockP2PQuicStreamDelegate>(stream_delegate)); - ASSERT_TRUE(client_peer_->stream()); - ASSERT_TRUE(client_peer_->stream_delegate()); - } - - void ExpectConnectionNotEstablished() { - EXPECT_FALSE(client_peer_->quic_transport()->IsEncryptionEstablished()); - EXPECT_FALSE(client_peer_->quic_transport()->OneRttKeysAvailable()); - EXPECT_FALSE(server_peer_->quic_transport()->OneRttKeysAvailable()); - EXPECT_FALSE(server_peer_->quic_transport()->IsEncryptionEstablished()); - } - - void ExpectTransportsClosed() { - EXPECT_TRUE(client_peer_->quic_transport()->IsClosed()); - EXPECT_TRUE(server_peer_->quic_transport()->IsClosed()); - } - - // Expects that streams of both the server and client transports are - // closed. - void ExpectStreamsClosed() { - EXPECT_EQ(0u, client_peer_->quic_transport()->GetNumActiveStreams()); - EXPECT_TRUE(client_peer_->quic_transport()->IsClosedStream( - client_peer()->stream_id())); - - EXPECT_EQ(0u, server_peer_->quic_transport()->GetNumActiveStreams()); - EXPECT_TRUE(server_peer()->quic_transport()->IsClosedStream( - server_peer()->stream_id())); - } - - // Exposes these private functions to the test. - bool IsClientClosed() { return client_peer_->quic_transport()->IsClosed(); } - bool IsServerClosed() { return server_peer_->quic_transport()->IsClosed(); } - - QuicPeerForTest* client_peer() { return client_peer_.get(); } - - quic::QuicConnection* client_connection() { - return client_peer_->quic_transport()->connection(); - } - - QuicPeerForTest* server_peer() { return server_peer_.get(); } - - quic::QuicConnection* server_connection() { - return server_peer_->quic_transport()->connection(); - } - - scoped_refptr<net::test::TestTaskRunner> runner() { return runner_; } - - private: - quic::MockClock clock_; - quic::QuicRandom* quic_random_; - // The TestTaskRunner is used by the QUIC library for setting/firing alarms. - // We are able to explicitly run these tasks ourselves with the - // TestTaskRunner. - scoped_refptr<net::test::TestTaskRunner> runner_; - // This is eventually passed down to the QUIC library. - std::unique_ptr<net::QuicChromiumAlarmFactory> alarm_factory_; - - std::unique_ptr<P2PQuicTransportFactoryImpl> quic_transport_factory_; - std::unique_ptr<QuicPeerForTest> client_peer_; - std::unique_ptr<QuicPeerForTest> server_peer_; -}; - -// Tests that we can connect two quic transports using pre shared keys. -TEST_F(P2PQuicTransportTest, HandshakeConnectsPeersWithPreSharedKeys) { - Initialize(); - - CallbackRunLoop run_loop(runner()); - // Datagrams should be supported. - EXPECT_CALL(*client_peer()->quic_transport_delegate(), - OnConnected(Property( - &P2PQuicNegotiatedParams::datagrams_supported, Eq(true)))) - .WillOnce(FireCallback(run_loop.CreateCallback())); - EXPECT_CALL(*server_peer()->quic_transport_delegate(), - OnConnected(Property( - &P2PQuicNegotiatedParams::datagrams_supported, Eq(true)))) - .WillOnce(FireCallback(run_loop.CreateCallback())); - - server_peer()->quic_transport()->Start( - P2PQuicTransport::StartConfig("foobar")); - client_peer()->quic_transport()->Start( - P2PQuicTransport::StartConfig("foobar")); - run_loop.RunUntilCallbacksFired(); - - EXPECT_TRUE(client_peer()->quic_transport()->IsEncryptionEstablished()); - EXPECT_TRUE(client_peer()->quic_transport()->OneRttKeysAvailable()); - EXPECT_TRUE(server_peer()->quic_transport()->OneRttKeysAvailable()); - EXPECT_TRUE(server_peer()->quic_transport()->IsEncryptionEstablished()); -} - -// Tests that we can connect two quic transports using remote certificate -// fingerprints. Note that the fingerprints aren't currently used for -// verification. -TEST_F(P2PQuicTransportTest, HandshakeConnectsPeersWithRemoteCertificates) { - Initialize(); - - CallbackRunLoop run_loop(runner()); - // Datagrams should be supported. - EXPECT_CALL(*client_peer()->quic_transport_delegate(), - OnConnected(Property( - &P2PQuicNegotiatedParams::datagrams_supported, Eq(true)))) - .WillOnce(FireCallback(run_loop.CreateCallback())); - EXPECT_CALL(*server_peer()->quic_transport_delegate(), - OnConnected(Property( - &P2PQuicNegotiatedParams::datagrams_supported, Eq(true)))) - .WillOnce(FireCallback(run_loop.CreateCallback())); - - // Start the handshake with the remote fingerprints. - Vector<std::unique_ptr<rtc::SSLFingerprint>> server_fingerprints; - server_fingerprints.push_back(rtc::SSLFingerprint::CreateUnique( - "sha-256", *server_peer()->certificate()->identity())); - server_peer()->quic_transport()->Start( - P2PQuicTransport::StartConfig(std::move(server_fingerprints))); - - Vector<std::unique_ptr<rtc::SSLFingerprint>> client_fingerprints; - client_fingerprints.push_back(rtc::SSLFingerprint::CreateUnique( - "sha-256", *client_peer()->certificate()->identity())); - client_peer()->quic_transport()->Start( - P2PQuicTransport::StartConfig(std::move(client_fingerprints))); - - run_loop.RunUntilCallbacksFired(); - - EXPECT_TRUE(client_peer()->quic_transport()->IsEncryptionEstablished()); - EXPECT_TRUE(client_peer()->quic_transport()->OneRttKeysAvailable()); - EXPECT_TRUE(server_peer()->quic_transport()->OneRttKeysAvailable()); - EXPECT_TRUE(server_peer()->quic_transport()->IsEncryptionEstablished()); -} - -// Tests the standard case for the server side closing the connection. -TEST_F(P2PQuicTransportTest, ServerStops) { - Initialize(); - Connect(); - CallbackRunLoop run_loop(runner()); - EXPECT_CALL(*client_peer()->quic_transport_delegate(), OnRemoteStopped()) - .WillOnce(FireCallback(run_loop.CreateCallback())); - EXPECT_CALL(*server_peer()->quic_transport_delegate(), OnRemoteStopped()) - .Times(0); - - server_peer()->quic_transport()->Stop(); - run_loop.RunUntilCallbacksFired(); - - ExpectTransportsClosed(); -} - -// Tests the standard case for the client side closing the connection. -TEST_F(P2PQuicTransportTest, ClientStops) { - Initialize(); - Connect(); - CallbackRunLoop run_loop(runner()); - EXPECT_CALL(*server_peer()->quic_transport_delegate(), OnRemoteStopped()) - .WillOnce(FireCallback(run_loop.CreateCallback())); - EXPECT_CALL(*client_peer()->quic_transport_delegate(), OnRemoteStopped()) - .Times(0); - - client_peer()->quic_transport()->Stop(); - run_loop.RunUntilCallbacksFired(); - - ExpectTransportsClosed(); -} - -// Tests that if either side tries to close the connection a second time, it -// will be ignored because the connection has already been closed. -TEST_F(P2PQuicTransportTest, StopAfterStopped) { - Initialize(); - Connect(); - CallbackRunLoop run_loop(runner()); - EXPECT_CALL(*server_peer()->quic_transport_delegate(), OnRemoteStopped()) - .WillOnce(FireCallback(run_loop.CreateCallback())); - client_peer()->quic_transport()->Stop(); - run_loop.RunUntilCallbacksFired(); - - EXPECT_CALL(*server_peer()->quic_transport_delegate(), OnRemoteStopped()) - .Times(0); - EXPECT_CALL(*client_peer()->quic_transport_delegate(), OnRemoteStopped()) - .Times(0); - - client_peer()->quic_transport()->Stop(); - server_peer()->quic_transport()->Stop(); - RunCurrentTasks(); - - ExpectTransportsClosed(); -} - -// Tests that the appropriate callbacks are fired when the handshake fails. -TEST_F(P2PQuicTransportTest, HandshakeFailure) { - InitializeWithFailingProofVerification(); - CallbackRunLoop run_loop(runner()); - EXPECT_CALL(*client_peer()->quic_transport_delegate(), - OnConnectionFailed(_, _)) - .WillOnce(FireCallback(run_loop.CreateCallback())); - EXPECT_CALL(*server_peer()->quic_transport_delegate(), - OnConnectionFailed(_, _)) - .WillOnce(FireCallback(run_loop.CreateCallback())); - - server_peer()->quic_transport()->Start( - P2PQuicTransport::StartConfig("foobar")); - client_peer()->quic_transport()->Start( - P2PQuicTransport::StartConfig("foobar")); - run_loop.RunUntilCallbacksFired(); - - ExpectConnectionNotEstablished(); - ExpectTransportsClosed(); -} - -// Tests that the handshake fails if the pre shared keys don't match. -// In this case the handshake finishes, but the connection fails because packets -// can't be decrypted. -TEST_F(P2PQuicTransportTest, HandshakeFailsBecauseKeysDontMatch) { - Initialize(); - CallbackRunLoop run_loop(runner()); - EXPECT_CALL(*client_peer()->quic_transport_delegate(), - OnConnectionFailed(_, _)) - .WillOnce(FireCallback(run_loop.CreateCallback())); - EXPECT_CALL(*server_peer()->quic_transport_delegate(), - OnConnectionFailed(_, _)) - .WillOnce(FireCallback(run_loop.CreateCallback())); - - server_peer()->quic_transport()->Start( - P2PQuicTransport::StartConfig("foobar")); - client_peer()->quic_transport()->Start( - P2PQuicTransport::StartConfig("barfoo")); - run_loop.RunUntilCallbacksFired(); - - ExpectTransportsClosed(); -} - -// Tests that the appropriate callbacks are fired when the client's connection -// fails after the transports have connected. -TEST_F(P2PQuicTransportTest, ClientConnectionFailureAfterConnected) { - Initialize(); - Connect(); - CallbackRunLoop run_loop(runner()); - EXPECT_CALL(*client_peer()->quic_transport_delegate(), - OnConnectionFailed(_, /*from_remote=*/false)) - .WillOnce(FireCallback(run_loop.CreateCallback())); - EXPECT_CALL(*server_peer()->quic_transport_delegate(), - OnConnectionFailed(_, /*from_remote=*/true)) - .WillOnce(FireCallback(run_loop.CreateCallback())); - - // Close the connection with an internal QUIC error. - client_connection()->CloseConnection( - quic::QuicErrorCode::QUIC_INTERNAL_ERROR, "internal error", - quic::ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); - run_loop.RunUntilCallbacksFired(); - - ExpectTransportsClosed(); -} - -// Tests that the appropriate callbacks are fired when the server's connection -// fails after the transports have connected. -TEST_F(P2PQuicTransportTest, ServerConnectionFailureAfterConnected) { - Initialize(); - Connect(); - CallbackRunLoop run_loop(runner()); - EXPECT_CALL(*client_peer()->quic_transport_delegate(), - OnConnectionFailed(_, /*from_remote=*/true)) - .WillOnce(FireCallback(run_loop.CreateCallback())); - EXPECT_CALL(*server_peer()->quic_transport_delegate(), - OnConnectionFailed(_, /*from_remote=*/false)) - .WillOnce(FireCallback(run_loop.CreateCallback())); - - server_connection()->CloseConnection( - quic::QuicErrorCode::QUIC_INTERNAL_ERROR, "internal error", - quic::ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); - run_loop.RunUntilCallbacksFired(); - - ExpectTransportsClosed(); -} - -// Tests that a silent failure will only close on one side. -TEST_F(P2PQuicTransportTest, ConnectionSilentFailure) { - Initialize(); - Connect(); - CallbackRunLoop run_loop(runner()); - EXPECT_CALL(*client_peer()->quic_transport_delegate(), - OnConnectionFailed(_, _)) - .WillOnce(FireCallback(run_loop.CreateCallback())); - EXPECT_CALL(*server_peer()->quic_transport_delegate(), - OnConnectionFailed(_, _)) - .Times(0); - - client_connection()->CloseConnection( - quic::QuicErrorCode::QUIC_INTERNAL_ERROR, "internal error", - quic::ConnectionCloseBehavior::SILENT_CLOSE); - run_loop.RunUntilCallbacksFired(); - - EXPECT_TRUE(IsClientClosed()); - EXPECT_FALSE(IsServerClosed()); -} - -// Tests that the client transport can create a stream and an incoming stream -// will be created on the remote server. -TEST_F(P2PQuicTransportTest, ClientCreatesStream) { - Initialize(); - Connect(); - CallbackRunLoop run_loop(runner()); - client_peer()->CreateStreamWithDelegate(); - ASSERT_TRUE(client_peer()->stream()); - - RunCurrentTasks(); - - EXPECT_TRUE(client_peer()->quic_transport()->ShouldKeepConnectionAlive()); - EXPECT_FALSE(server_peer()->quic_transport()->ShouldKeepConnectionAlive()); - - // After sending data across it will trigger a stream to be created on the - // server side. - MockP2PQuicStreamDelegate server_stream_delegate; - base::RepeatingCallback<void()> callback = run_loop.CreateCallback(); - EXPECT_CALL(*server_peer()->quic_transport_delegate(), OnStream(_)) - .WillOnce( - Invoke([&callback, &server_stream_delegate](P2PQuicStream* stream) { - ASSERT_TRUE(stream); - // The Delegate must get immediately set to a new incoming stream. - stream->SetDelegate(&server_stream_delegate); - // Allows the run loop to run until this is fired. - callback.Run(); - })); - - client_peer()->stream()->WriteData( - VectorFromArray(kTriggerRemoteStreamPhrase), - /*fin=*/false); - run_loop.RunUntilCallbacksFired(); - - EXPECT_TRUE(server_peer()->quic_transport()->ShouldKeepConnectionAlive()); -} - -// Tests that the server transport can create a stream and an incoming stream -// will be created on the remote client. -TEST_F(P2PQuicTransportTest, ServerCreatesStream) { - Initialize(); - Connect(); - CallbackRunLoop run_loop(runner()); - server_peer()->CreateStreamWithDelegate(); - ASSERT_TRUE(server_peer()->stream()); - - RunCurrentTasks(); - - EXPECT_TRUE(server_peer()->quic_transport()->ShouldKeepConnectionAlive()); - EXPECT_FALSE(client_peer()->quic_transport()->ShouldKeepConnectionAlive()); - - // After sending data across it will trigger a stream to be created on the - // server side. - MockP2PQuicStreamDelegate client_stream_delegate; - base::RepeatingCallback<void()> callback = run_loop.CreateCallback(); - EXPECT_CALL(*client_peer()->quic_transport_delegate(), OnStream(_)) - .WillOnce( - Invoke([&callback, &client_stream_delegate](P2PQuicStream* stream) { - ASSERT_TRUE(stream); - // The Delegate must get immediately set to a new incoming stream. - stream->SetDelegate(&client_stream_delegate); - // Allows the run loop to run until this is fired. - callback.Run(); - })); - - server_peer()->stream()->WriteData( - VectorFromArray(kTriggerRemoteStreamPhrase), - /*fin=*/false); - run_loop.RunUntilCallbacksFired(); - - EXPECT_TRUE(client_peer()->quic_transport()->ShouldKeepConnectionAlive()); -} - -// Tests that when the client transport calls Stop() it closes its outgoing -// stream, which, in turn closes the incoming stream on the server quic -// transport. -TEST_F(P2PQuicTransportTest, ClientClosingConnectionClosesStreams) { - Initialize(); - Connect(); - SetupConnectedStreams(); - - client_peer()->quic_transport()->Stop(); - RunCurrentTasks(); - - ExpectTransportsClosed(); - ExpectStreamsClosed(); -} - -// Tests that when the server transport calls Stop() it closes its incoming -// stream, which, in turn closes the outgoing stream on the client quic -// transport. -// TODO(crbug.com/1056976): re-enable this test when crbug.com/1056976 is fixed. -TEST_F(P2PQuicTransportTest, DISABLED_ServerClosingConnectionClosesStreams) { - Initialize(); - Connect(); - SetupConnectedStreams(); - - server_peer()->quic_transport()->Stop(); - RunCurrentTasks(); - - ExpectTransportsClosed(); - ExpectStreamsClosed(); -} - -// Tests that calling Reset() will close both side's streams for reading and -// writing. -TEST_F(P2PQuicTransportTest, ClientStreamReset) { - Initialize(); - Connect(); - SetupConnectedStreams(); - CallbackRunLoop run_loop(runner()); - - EXPECT_CALL(*server_peer()->stream_delegate(), OnRemoteReset()) - .WillOnce(FireCallback(run_loop.CreateCallback())); - - client_peer()->stream()->Reset(); - run_loop.RunUntilCallbacksFired(); - ExpectStreamsClosed(); -} - -// Tests that calling Reset() will close both side's streams for reading and -// writing. -TEST_F(P2PQuicTransportTest, ServerStreamReset) { - Initialize(); - Connect(); - SetupConnectedStreams(); - CallbackRunLoop run_loop(runner()); - - EXPECT_CALL(*client_peer()->stream_delegate(), OnRemoteReset()) - .WillOnce(FireCallback(run_loop.CreateCallback())); - - server_peer()->stream()->Reset(); - run_loop.RunUntilCallbacksFired(); - - ExpectStreamsClosed(); -} - -// Tests the basic case for sending a FIN bit on both sides. -TEST_F(P2PQuicTransportTest, StreamClosedAfterSendingAndReceivingFin) { - Initialize(); - Connect(); - SetupConnectedStreams(); - CallbackRunLoop run_loop(runner()); - - EXPECT_CALL(*server_peer()->stream_delegate(), - OnDataReceived(_, /*fin=*/true)) - .WillOnce(FireCallback(run_loop.CreateCallback())); - - client_peer()->stream()->WriteData({}, /*fin=*/true); - run_loop.RunUntilCallbacksFired(); - - ASSERT_EQ(1u, server_peer()->quic_transport()->GetNumActiveStreams()); - ASSERT_EQ(1u, client_peer()->quic_transport()->GetNumActiveStreams()); - EXPECT_TRUE(client_peer()->stream()->write_side_closed()); - EXPECT_FALSE(client_peer()->stream()->reading_stopped()); - EXPECT_FALSE(server_peer()->stream()->write_side_closed()); - EXPECT_TRUE(server_peer()->stream()->reading_stopped()); - EXPECT_FALSE(server_peer()->quic_transport()->IsClosedStream( - server_peer()->stream_id())); - EXPECT_FALSE(client_peer()->quic_transport()->IsClosedStream( - client_peer()->stream_id())); - - EXPECT_CALL(*client_peer()->stream_delegate(), - OnDataReceived(_, /*fin=*/true)) - .WillOnce(FireCallback(run_loop.CreateCallback())); - - server_peer()->stream()->WriteData({}, /*fin=*/true); - run_loop.RunUntilCallbacksFired(); - - // This is required so that the client acks the FIN back to the server side - // and the server side removes its zombie streams. - RunCurrentTasks(); - - ASSERT_EQ(0u, server_peer()->quic_transport()->GetNumActiveStreams()); - ASSERT_EQ(0u, client_peer()->quic_transport()->GetNumActiveStreams()); - EXPECT_TRUE(server_peer()->quic_transport()->IsClosedStream( - server_peer()->stream_id())); - EXPECT_TRUE(client_peer()->quic_transport()->IsClosedStream( - client_peer()->stream_id())); -} - -// Tests that if a Reset() is called after sending a FIN bit, both sides close -// down properly. -TEST_F(P2PQuicTransportTest, StreamResetAfterSendingFin) { - Initialize(); - Connect(); - SetupConnectedStreams(); - CallbackRunLoop run_loop(runner()); - - EXPECT_CALL(*server_peer()->stream_delegate(), - OnDataReceived(_, /*fin=*/true)) - .WillOnce(FireCallback(run_loop.CreateCallback())); - - client_peer()->stream()->WriteData({}, /*fin=*/true); - run_loop.RunUntilCallbacksFired(); - - EXPECT_CALL(*server_peer()->stream_delegate(), OnRemoteReset()) - .WillOnce(FireCallback(run_loop.CreateCallback())); - EXPECT_CALL(*client_peer()->stream_delegate(), OnRemoteReset()).Times(0); - - client_peer()->stream()->Reset(); - run_loop.RunUntilCallbacksFired(); - - ExpectStreamsClosed(); -} - -// Tests that if a Reset() is called after receiving a stream frame with the FIN -// bit set from the remote side, both sides close down properly. -TEST_F(P2PQuicTransportTest, StreamResetAfterReceivingFin) { - Initialize(); - Connect(); - SetupConnectedStreams(); - CallbackRunLoop run_loop(runner()); - - EXPECT_CALL(*server_peer()->stream_delegate(), - OnDataReceived(_, /*fin=*/true)) - .WillOnce(FireCallback(run_loop.CreateCallback())); - - client_peer()->stream()->WriteData({}, /*fin=*/true); - run_loop.RunUntilCallbacksFired(); - - EXPECT_CALL(*client_peer()->stream_delegate(), OnRemoteReset()) - .WillOnce(FireCallback(run_loop.CreateCallback())); - EXPECT_CALL(*server_peer()->stream_delegate(), OnRemoteReset()).Times(0); - - // The server stream has received its FIN bit from the remote side, and - // responds with a Reset() to close everything down. - server_peer()->stream()->Reset(); - run_loop.RunUntilCallbacksFired(); - - ExpectStreamsClosed(); -} - -// Tests that when datagrams are sent from each side they are received on the -// other end. -TEST_F(P2PQuicTransportTest, DatagramsSentReceivedOnRemoteSide) { - Initialize(); - Connect(); - CallbackRunLoop run_loop(runner()); - - // We should get the appropriate message on each end. - EXPECT_CALL(*server_peer()->quic_transport_delegate(), - OnDatagramReceived(ElementsAreArray(kClientMessage))) - .WillOnce(FireCallback(run_loop.CreateCallback())); - EXPECT_CALL(*client_peer()->quic_transport_delegate(), - OnDatagramReceived(ElementsAreArray(kServerMessage))) - .WillOnce(FireCallback(run_loop.CreateCallback())); - // The OnDatagramSent callback should fire for each datagram being sent. - EXPECT_CALL(*server_peer()->quic_transport_delegate(), OnDatagramSent()) - .Times(1) - .WillOnce(FireCallback(run_loop.CreateCallback())); - EXPECT_CALL(*client_peer()->quic_transport_delegate(), OnDatagramSent()) - .Times(1) - .WillOnce(FireCallback(run_loop.CreateCallback())); - - server_peer()->quic_transport()->SendDatagram( - VectorFromArray(kServerMessage)); - client_peer()->quic_transport()->SendDatagram( - VectorFromArray(kClientMessage)); - - run_loop.RunUntilCallbacksFired(); -} - -// Tests that when data is sent on a stream it is received on the other end. -TEST_F(P2PQuicTransportTest, StreamDataSentThenReceivedOnRemoteSide) { - Initialize(); - Connect(); - SetupConnectedStreams(); - CallbackRunLoop run_loop(runner()); - - EXPECT_CALL(*server_peer()->stream_delegate(), - OnDataReceived(ElementsAreArray(kMessage), false)) - .WillOnce(FireCallback(run_loop.CreateCallback())); - EXPECT_CALL(*client_peer()->stream_delegate(), - OnWriteDataConsumed(base::size(kMessage))) - .WillOnce(FireCallback(run_loop.CreateCallback())); - - client_peer()->stream()->WriteData(VectorFromArray(kMessage), - /* fin= */ false); - run_loop.RunUntilCallbacksFired(); -} - -// Tests that if both sides have a stream that sends data and FIN bit -// they both close down for reading and writing properly. -TEST_F(P2PQuicTransportTest, StreamDataSentWithFinClosesStreams) { - Initialize(); - Connect(); - SetupConnectedStreams(); - CallbackRunLoop run_loop(runner()); - - EXPECT_CALL(*server_peer()->stream_delegate(), - OnDataReceived(VectorFromArray(kClientMessage), true)) - .WillOnce(FireCallback(run_loop.CreateCallback())); - EXPECT_CALL(*server_peer()->stream_delegate(), - OnWriteDataConsumed(base::size(kServerMessage))) - .WillOnce(FireCallback(run_loop.CreateCallback())); - - EXPECT_CALL(*client_peer()->stream_delegate(), - OnDataReceived(ElementsAreArray(kServerMessage), true)) - .WillOnce(FireCallback(run_loop.CreateCallback())); - EXPECT_CALL(*client_peer()->stream_delegate(), - OnWriteDataConsumed(base::size(kClientMessage))) - .WillOnce(FireCallback(run_loop.CreateCallback())); - - client_peer()->stream()->WriteData(VectorFromArray(kClientMessage), - /*fin=*/true); - server_peer()->stream()->WriteData(VectorFromArray(kServerMessage), - /*fin=*/true); - run_loop.RunUntilCallbacksFired(); - - ExpectStreamsClosed(); -} - -// Tests that the stats returned by the P2PQuicTransportImpl have the correct -// number of incoming and outgoing streams. -TEST_F(P2PQuicTransportTest, GetStatsForNumberOfStreams) { - Initialize(); - Connect(); - - P2PQuicTransportStats client_stats_1 = - client_peer()->quic_transport()->GetStats(); - EXPECT_EQ(0u, client_stats_1.num_incoming_streams_created); - EXPECT_EQ(0u, client_stats_1.num_outgoing_streams_created); - P2PQuicTransportStats server_stats_1 = - server_peer()->quic_transport()->GetStats(); - EXPECT_EQ(0u, server_stats_1.num_incoming_streams_created); - EXPECT_EQ(0u, server_stats_1.num_outgoing_streams_created); - - // Create a stream on the client side and send some data to trigger a stream - // creation on the remote side. - client_peer()->CreateStreamWithDelegate(); - CallbackRunLoop run_loop(runner()); - base::RepeatingCallback<void()> callback = run_loop.CreateCallback(); - MockP2PQuicStreamDelegate server_stream_delegate; - EXPECT_CALL(*server_peer()->quic_transport_delegate(), OnStream(_)) - .WillOnce( - Invoke([&callback, &server_stream_delegate](P2PQuicStream* stream) { - stream->SetDelegate(&server_stream_delegate); - callback.Run(); - })); - client_peer()->stream()->WriteData( - VectorFromArray(kTriggerRemoteStreamPhrase), - /*fin=*/false); - run_loop.RunUntilCallbacksFired(); - - P2PQuicTransportStats client_stats_2 = - client_peer()->quic_transport()->GetStats(); - EXPECT_EQ(0u, client_stats_2.num_incoming_streams_created); - EXPECT_EQ(1u, client_stats_2.num_outgoing_streams_created); - EXPECT_GT(client_stats_2.timestamp, client_stats_1.timestamp); - P2PQuicTransportStats server_stats_2 = - server_peer()->quic_transport()->GetStats(); - EXPECT_EQ(1u, server_stats_2.num_incoming_streams_created); - EXPECT_EQ(0u, server_stats_2.num_outgoing_streams_created); - EXPECT_GT(server_stats_2.timestamp, server_stats_1.timestamp); -} - -// P2PQuicTransport tests that use a fake quic::QuicConnection. -class P2PQuicTransportMockConnectionTest : public testing::Test { - public: - P2PQuicTransportMockConnectionTest() { - connection_helper_ = new quic::test::MockQuicConnectionHelper(); - connection_ = new quic::test::MockQuicConnection( - connection_helper_, &alarm_factory_, quic::Perspective::IS_CLIENT); - - rtc::scoped_refptr<rtc::RTCCertificate> certificate = - CreateTestCertificate(); - P2PQuicTransportConfig config(quic::Perspective::IS_CLIENT, {certificate}, - kTransportDelegateReadBufferSize, - kTransportWriteBufferSize); - quic::QuicConfig quic_config; - transport_ = std::make_unique<P2PQuicTransportImpl>( - &delegate_, &packet_transport_, config, - std::unique_ptr<quic::test::MockQuicConnectionHelper>( - connection_helper_), - std::unique_ptr<quic::test::MockQuicConnection>(connection_), - quic_config, - std::make_unique<P2PQuicCryptoConfigFactoryImpl>(&quic_random_), - std::make_unique<ConnectedCryptoClientStreamFactory>(), &clock_); - // Called once in P2PQuicTransportImpl::Start and once in the destructor. - EXPECT_CALL(packet_transport_, SetReceiveDelegate(transport())).Times(1); - EXPECT_CALL(packet_transport_, SetReceiveDelegate(nullptr)).Times(1); - // DCHECKS get hit when the clock is at 0. - connection_helper_->AdvanceTime(quic::QuicTime::Delta::FromSeconds(1)); - transport_->Start(P2PQuicTransport::StartConfig("foobar")); - } - - ~P2PQuicTransportMockConnectionTest() override {} - - P2PQuicTransportImpl* transport() { return transport_.get(); } - - MockP2PQuicTransportDelegate* delegate() { return &delegate_; } - - quic::test::MockQuicConnection* connection() { return connection_; } - - private: - quic::MockClock clock_; - MockP2PQuicPacketTransport packet_transport_; - quic::test::MockRandom quic_random_; - quic::test::MockAlarmFactory alarm_factory_; - MockP2PQuicTransportDelegate delegate_; - std::unique_ptr<P2PQuicTransportImpl> transport_; - // Owned by the |transport_|. - quic::test::MockQuicConnection* connection_; - quic::test::MockQuicConnectionHelper* connection_helper_; -}; - -// Test that when a datagram is received it properly fires the -// OnDatagramReceived function on the delegate. -// Flaky on all platforms. See https://crbug.com/1071340 -TEST_F(P2PQuicTransportMockConnectionTest, DISABLED_OnDatagramReceived) { - EXPECT_TRUE(transport()->CanSendDatagram()); - EXPECT_CALL(*delegate(), OnDatagramReceived(ElementsAreArray(kMessage))); - transport()->OnMessageReceived(quiche::QuicheStringPiece( - reinterpret_cast<const char*>(kMessage), sizeof(kMessage))); -} - -// Test that when a datagram is sent that is properly fires the OnDatagramSent -// function on the delegate. -// Flaky on all platforms. See https://crbug.com/1071340 -TEST_F(P2PQuicTransportMockConnectionTest, DISABLED_OnDatagramSent) { - EXPECT_CALL(*connection(), SendMessage(_, _, _)) - .WillOnce(Invoke([](quic::QuicMessageId message_id, - quic::QuicMemSliceSpan message, bool flush) { - EXPECT_THAT(message.GetData(0), ElementsAreArray(kMessage)); - return quic::MESSAGE_STATUS_SUCCESS; - })); - EXPECT_CALL(*delegate(), OnDatagramSent()); - - transport()->SendDatagram(VectorFromArray(kMessage)); -} - -// Test that when the quic::QuicConnection is congestion control blocked that -// the datagram gets buffered and not sent. -// Flaky on all platforms. See https://crbug.com/1071340 -TEST_F(P2PQuicTransportMockConnectionTest, DISABLED_DatagramNotSent) { - EXPECT_CALL(*connection(), SendMessage(_, _, _)) - .WillOnce(Return(quic::MESSAGE_STATUS_BLOCKED)); - EXPECT_CALL(*delegate(), OnDatagramSent()).Times(0); - - transport()->SendDatagram(VectorFromArray(kMessage)); -} - -// Test that when datagrams are buffered they are later sent when the transport -// is no longer congestion control blocked. -// Flaky on all platforms. See https://crbug.com/1071340 -TEST_F(P2PQuicTransportMockConnectionTest, DISABLED_BufferedDatagramsSent) { - EXPECT_CALL(*connection(), SendMessage(_, _, _)) - .WillOnce(Return(quic::MESSAGE_STATUS_BLOCKED)); - transport()->SendDatagram(VectorFromArray(kMessage)); - transport()->SendDatagram(VectorFromArray(kMessage2)); - - EXPECT_CALL(*delegate(), OnDatagramSent()).Times(2); - // Need to check equality with the function call matcher, instead of - // passing a lamda that checks equality in an Invoke as done in other tests. - EXPECT_CALL(*connection(), - SendMessage(_, - ResultOf( - [](quic::QuicMemSliceSpan message) { - return message.GetData(0); - }, - ElementsAreArray(kMessage)), - _)) - .WillOnce(Return(quic::MESSAGE_STATUS_SUCCESS)); - EXPECT_CALL(*connection(), - SendMessage(_, - ResultOf( - [](quic::QuicMemSliceSpan message) { - return message.GetData(0); - }, - ElementsAreArray(kMessage2)), - _)) - .WillOnce(Return(quic::MESSAGE_STATUS_SUCCESS)); - - transport()->OnCanWrite(); -} - -// Tests the following scenario: -// -Write blocked - datagrams are buffered. -// -Write unblocked - send buffered datagrams. -// -Write blocked - keep datagrams buffered. -// Flaky on all platforms. See https://crbug.com/1071340 -TEST_F(P2PQuicTransportMockConnectionTest, - DISABLED_BufferedDatagramRemainBuffered) { - EXPECT_CALL(*connection(), SendMessage(_, _, _)) - .WillOnce(Return(quic::MESSAGE_STATUS_BLOCKED)); - transport()->SendDatagram(VectorFromArray(kMessage)); - transport()->SendDatagram(VectorFromArray(kMessage2)); - - // The first datagram gets sent off after becoming write unblocked, while the - // second datagram is buffered. - EXPECT_CALL(*connection(), - SendMessage(_, - ResultOf( - [](quic::QuicMemSliceSpan message) { - return message.GetData(0); - }, - ElementsAreArray(kMessage)), - _)) - .WillOnce(Return(quic::MESSAGE_STATUS_SUCCESS)); - EXPECT_CALL(*connection(), - SendMessage(_, - ResultOf( - [](quic::QuicMemSliceSpan message) { - return message.GetData(0); - }, - ElementsAreArray(kMessage2)), - _)) - .WillOnce(Return(quic::MESSAGE_STATUS_BLOCKED)); - // No callback for the second datagram, as it is still buffered. - EXPECT_CALL(*delegate(), OnDatagramSent()).Times(1); - - transport()->OnCanWrite(); - - // Sending another datagram at this point should just buffer it. - EXPECT_CALL(*connection(), SendMessage(_, _, _)).Times(0); - transport()->SendDatagram(VectorFromArray(kMessage)); -} - -// Flaky on all platforms. See https://crbug.com/1071340 -TEST_F(P2PQuicTransportMockConnectionTest, DISABLED_LostDatagramUpdatesStats) { - // The ID the quic::QuicSession will assign to the datagram that is used for - // callbacks, like OnDatagramLost. - uint32_t datagram_id; - EXPECT_CALL(*connection(), SendMessage(_, _, _)) - .WillOnce( - Invoke([&datagram_id](quic::QuicMessageId message_id, - quic::QuicMemSliceSpan message, bool flush) { - datagram_id = message_id; - return quic::MESSAGE_STATUS_SUCCESS; - })); - EXPECT_CALL(*delegate(), OnDatagramSent()).Times(1); - transport()->SendDatagram(VectorFromArray(kMessage)); - - EXPECT_EQ(0u, transport()->GetStats().num_datagrams_lost); - transport()->OnMessageLost(datagram_id); - - EXPECT_EQ(1u, transport()->GetStats().num_datagrams_lost); -} -} // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/quic_packet_transport_adapter.cc b/third_party/blink/renderer/modules/peerconnection/adapters/quic_packet_transport_adapter.cc deleted file mode 100644 index 60230d5..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/quic_packet_transport_adapter.cc +++ /dev/null
@@ -1,84 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "third_party/blink/renderer/modules/peerconnection/adapters/quic_packet_transport_adapter.h" -#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h" - -namespace blink { - -QuicPacketTransportAdapter::QuicPacketTransportAdapter( - cricket::IceTransportInternal* ice_transport) - : ice_transport_(ice_transport) { - DCHECK(ice_transport_); - ice_transport_->SignalReadPacket.connect( - this, &QuicPacketTransportAdapter::OnReadPacket); - ice_transport_->SignalReadyToSend.connect( - this, &QuicPacketTransportAdapter::OnReadyToSend); -} - -QuicPacketTransportAdapter::~QuicPacketTransportAdapter() { - // Caller is responsible for unsetting the write observer and receive - // delegate before destroying this. - DCHECK(!write_observer_); - DCHECK(!receive_delegate_); -} - -int QuicPacketTransportAdapter::WritePacket(const QuicPacket& packet) { - rtc::PacketOptions options; - options.packet_id = packet.packet_number; - int flags = 0; - return ice_transport_->SendPacket(packet.buffer, packet.buf_len, options, - flags); -} - -void QuicPacketTransportAdapter::SetReceiveDelegate( - ReceiveDelegate* receive_delegate) { - receive_delegate_ = receive_delegate; - if (!cached_client_hello_packet_.empty() && receive_delegate_) { - // If a CHLO was received early, give it to the delegate. - receive_delegate_->OnPacketDataReceived(cached_client_hello_packet_.c_str(), - cached_client_hello_packet_.size()); - cached_client_hello_packet_.clear(); - } -} - -void QuicPacketTransportAdapter::SetWriteObserver( - WriteObserver* write_observer) { - write_observer_ = write_observer; -} - -bool QuicPacketTransportAdapter::Writable() { - return ice_transport_->writable(); -} - -// IceTransportInternal callbacks. -void QuicPacketTransportAdapter::OnReadPacket( - rtc::PacketTransportInternal* packet_transport, - const char* buffer, - size_t buffer_length, - const int64_t& packet_time, - int flags) { - DCHECK_EQ(packet_transport, ice_transport_); - if (!receive_delegate_) { - // Cache the early CHLO from the QUIC handshake. - // The CHLO is stored in a single packet. All packets before the most recent - // can be discarded because they are no longer relevant, since at this point - // we have not responded. The packet could also be a connection close packet - // in the case that QUIC times out waiting for a response. - cached_client_hello_packet_ = std::string(buffer, buffer_length); - return; - } - receive_delegate_->OnPacketDataReceived(buffer, buffer_length); -} - -void QuicPacketTransportAdapter::OnReadyToSend( - rtc::PacketTransportInternal* packet_transport) { - DCHECK_EQ(packet_transport, ice_transport_); - if (!write_observer_) { - return; - } - write_observer_->OnCanWrite(); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/quic_packet_transport_adapter.h b/third_party/blink/renderer/modules/peerconnection/adapters/quic_packet_transport_adapter.h deleted file mode 100644 index 97689998..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/quic_packet_transport_adapter.h +++ /dev/null
@@ -1,56 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_QUIC_PACKET_TRANSPORT_ADAPTER_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_QUIC_PACKET_TRANSPORT_ADAPTER_H_ - -#include "third_party/blink/renderer/modules/modules_export.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_packet_transport.h" -#include "third_party/webrtc/p2p/base/p2p_transport_channel.h" - -namespace blink { - -// Implementation of P2PQuicPacketTransport backed by a IceTransportInternal. -// It adapts the underlying ICE transport to be used with the QUIC library. -// This does not filter packets. It requires that the IceTransportInternal is -// only being used for QUIC packets. -class MODULES_EXPORT QuicPacketTransportAdapter : public P2PQuicPacketTransport, - public sigslot::has_slots<> { - public: - QuicPacketTransportAdapter( - cricket::IceTransportInternal* p2p_transport_channel); - - ~QuicPacketTransportAdapter() override; - - // P2PQuicPacketTransport overrides. - int WritePacket(const QuicPacket& packet) override; - void SetReceiveDelegate(ReceiveDelegate* receive_delegate) override; - void SetWriteObserver(WriteObserver* write_observer) override; - bool Writable() override; - - private: - // IceTransportInternal callbacks. - void OnReadPacket(rtc::PacketTransportInternal* packet_transport, - const char* buffer, - size_t buffer_length, - const int64_t& packet_time, - int flags); - - void OnReadyToSend(rtc::PacketTransportInternal* packet_transport); - - // Owned by the IceTransportAdapter and will outlive this object. - cricket::IceTransportInternal* ice_transport_; - // The ReceiveDelegate and WriteObserver must be unset before - // this object is destroyed. - ReceiveDelegate* receive_delegate_ = nullptr; - WriteObserver* write_observer_ = nullptr; - // If the CHLO arrives early it is cached. This can occur if the QUIC - // handshake begins on the client side before the remote parameters are - // received on the server side. - std::string cached_client_hello_packet_; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_QUIC_PACKET_TRANSPORT_ADAPTER_H_
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/quic_packet_transport_adapter_test.cc b/third_party/blink/renderer/modules/peerconnection/adapters/quic_packet_transport_adapter_test.cc deleted file mode 100644 index 2c3785e..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/quic_packet_transport_adapter_test.cc +++ /dev/null
@@ -1,126 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "third_party/blink/renderer/modules/peerconnection/adapters/quic_packet_transport_adapter.h" - -#include "net/test/gtest_util.h" -#include "third_party/webrtc/p2p/base/mock_ice_transport.h" - -namespace blink { - -namespace { -using testing::StrEq; -} // namespace - -class MockWriteObserver : public P2PQuicPacketTransport::WriteObserver { - public: - MOCK_METHOD0(OnCanWrite, void()); -}; - -class MockReceiveDelegate : public P2PQuicPacketTransport::ReceiveDelegate { - public: - MOCK_METHOD2(OnPacketDataReceived, void(const char*, size_t)); -}; - -class QuicPacketTransportAdapterTest : public testing::Test { - public: - QuicPacketTransportAdapterTest() - : quic_packet_transport_adapter_(&mock_ice_transport_) {} - - ~QuicPacketTransportAdapterTest() override { - quic_packet_transport_adapter_.SetReceiveDelegate(nullptr); - quic_packet_transport_adapter_.SetWriteObserver(nullptr); - } - - cricket::MockIceTransport* mock_ice_transport() { - return &mock_ice_transport_; - } - - QuicPacketTransportAdapter* quic_packet_transport_adapter() { - return &quic_packet_transport_adapter_; - } - - private: - cricket::MockIceTransport mock_ice_transport_; - QuicPacketTransportAdapter quic_packet_transport_adapter_; -}; - -// Tests that when the underlying ICE transport is ready to send data that -// the QuicPacketTransportAdapter will tell the WriteObserver. -TEST_F(QuicPacketTransportAdapterTest, IceTransportReadyTriggersCanWrite) { - MockWriteObserver mock_write_observer; - quic_packet_transport_adapter()->SetWriteObserver(&mock_write_observer); - - EXPECT_CALL(mock_write_observer, OnCanWrite()); - - mock_ice_transport()->SignalReadyToSend(mock_ice_transport()); -} - -// Tests that writing a packet to the QuicPacketTransportAdapter will write -// the data to the underlying ICE transport. -TEST_F(QuicPacketTransportAdapterTest, WritePacketWritesToIceTransport) { - std::string packet("hola"); - - EXPECT_CALL(*mock_ice_transport(), - SendPacket(StrEq(packet), packet.size(), _, _)); - - P2PQuicPacketTransport::QuicPacket quic_packet; - quic_packet.buffer = packet.c_str(); - quic_packet.buf_len = packet.size(); - quic_packet_transport_adapter()->WritePacket(quic_packet); -} - -// Tests that when the underlying ICE transport receives data it it -// is passed appropriately to the ReceiveDelegate. -TEST_F(QuicPacketTransportAdapterTest, ReadPacketGivenToReceiveDelegate) { - MockReceiveDelegate mock_receive_delegate; - quic_packet_transport_adapter()->SetReceiveDelegate(&mock_receive_delegate); - - std::string packet("hola"); - EXPECT_CALL(mock_receive_delegate, - OnPacketDataReceived(StrEq(packet), packet.size())); - - mock_ice_transport()->SignalReadPacket(mock_ice_transport(), packet.c_str(), - packet.size(), 0, 0); -} - -// Tests that the most recent packet that was received before the -// ReceiveDelegate is hooked up will be given to the ReceiveDelegate once it is -// set. This is used as an optimization in the case that a QUIC CHLO is received -// early. -TEST_F(QuicPacketTransportAdapterTest, - MostRecentCachedPacketGivenToReceiveDelegate) { - std::string packet("hola"); - std::string latest_packet("bonjour"); - - mock_ice_transport()->SignalReadPacket(mock_ice_transport(), packet.c_str(), - packet.size(), 0, 0); - mock_ice_transport()->SignalReadPacket( - mock_ice_transport(), latest_packet.c_str(), latest_packet.size(), 0, 0); - - // The receive delegate is set after packets have been received. - MockReceiveDelegate mock_receive_delegate; - EXPECT_CALL(mock_receive_delegate, - OnPacketDataReceived(StrEq(latest_packet), latest_packet.size())); - - quic_packet_transport_adapter()->SetReceiveDelegate(&mock_receive_delegate); -} - -// Tests that the cached packet is not reused once it has been handed off to -// a set ReceiveDelegate. -TEST_F(QuicPacketTransportAdapterTest, CachedPacketIsNotReused) { - std::string packet("hola"); - mock_ice_transport()->SignalReadPacket(mock_ice_transport(), packet.c_str(), - packet.size(), 0, 0); - - MockReceiveDelegate mock_receive_delegate; - EXPECT_CALL(mock_receive_delegate, OnPacketDataReceived(_, _)); - quic_packet_transport_adapter()->SetReceiveDelegate(&mock_receive_delegate); - - MockReceiveDelegate latest_receive_delegate; - EXPECT_CALL(latest_receive_delegate, OnPacketDataReceived(_, _)).Times(0); - quic_packet_transport_adapter()->SetReceiveDelegate(&latest_receive_delegate); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_host.cc b/third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_host.cc deleted file mode 100644 index d701abd..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_host.cc +++ /dev/null
@@ -1,107 +0,0 @@ -// Copyright 2018 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/peerconnection/adapters/quic_stream_host.h" - -#include "third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_proxy.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_host.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/web_rtc_cross_thread_copier.h" -#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" -#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" - -namespace blink { - -QuicStreamHost::QuicStreamHost() { - DETACH_FROM_THREAD(thread_checker_); -} - -QuicStreamHost::~QuicStreamHost() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); -} - -void QuicStreamHost::set_proxy(base::WeakPtr<QuicStreamProxy> stream_proxy) { - DETACH_FROM_THREAD(thread_checker_); - stream_proxy_ = stream_proxy; -} - -void QuicStreamHost::Initialize(QuicTransportHost* transport_host, - P2PQuicStream* p2p_stream) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(transport_host); - DCHECK(p2p_stream); - transport_host_ = transport_host; - p2p_stream_ = p2p_stream; - p2p_stream_->SetDelegate(this); -} - -scoped_refptr<base::SingleThreadTaskRunner> QuicStreamHost::proxy_thread() - const { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(transport_host_); - return transport_host_->proxy_thread(); -} - -void QuicStreamHost::Reset() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(p2p_stream_); - p2p_stream_->Reset(); - Delete(); -} - -void QuicStreamHost::MarkReceivedDataConsumed(uint32_t amount) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(p2p_stream_); - p2p_stream_->MarkReceivedDataConsumed(amount); -} - -void QuicStreamHost::WriteData(Vector<uint8_t> data, bool fin) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(p2p_stream_); - p2p_stream_->WriteData(std::move(data), fin); - if (fin) { - DCHECK(writable_); - writable_ = false; - if (!readable_ && !writable_) { - Delete(); - } - } -} - -void QuicStreamHost::OnRemoteReset() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - PostCrossThreadTask( - *proxy_thread(), FROM_HERE, - CrossThreadBindOnce(&QuicStreamProxy::OnRemoteReset, stream_proxy_)); - Delete(); -} - -void QuicStreamHost::OnDataReceived(Vector<uint8_t> data, bool fin) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - PostCrossThreadTask(*proxy_thread(), FROM_HERE, - CrossThreadBindOnce(&QuicStreamProxy::OnDataReceived, - stream_proxy_, std::move(data), fin)); - if (fin) { - readable_ = false; - if (!readable_ && !writable_) { - Delete(); - } - } -} - -void QuicStreamHost::OnWriteDataConsumed(uint32_t amount) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - PostCrossThreadTask(*proxy_thread(), FROM_HERE, - CrossThreadBindOnce(&QuicStreamProxy::OnWriteDataConsumed, - stream_proxy_, amount)); -} - -void QuicStreamHost::Delete() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(transport_host_); - p2p_stream_->SetDelegate(nullptr); - // OnRemoveStream will delete |this|. - transport_host_->OnRemoveStream(this); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_host.h b/third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_host.h deleted file mode 100644 index 4607b6c..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_host.h +++ /dev/null
@@ -1,88 +0,0 @@ -// Copyright 2018 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_PEERCONNECTION_ADAPTERS_QUIC_STREAM_HOST_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_QUIC_STREAM_HOST_H_ - -#include "base/memory/scoped_refptr.h" -#include "base/memory/weak_ptr.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_checker.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream.h" - -namespace blink { - -class QuicStreamProxy; -class QuicTransportHost; - -// This class is the host side correspondent to the QuicStreamProxy. See the -// QuicStreamProxy documentation for background. This class lives on the host -// thread and proxies calls between the QuicStreamProxy and the P2PQuicStream -// (which is single-threaded). -// -// The QuicStreamHost is owned by the QuicTransportHost and constructed when -// either a new local QUIC stream is created or when a remote QUIC stream has -// been created. The stream host will be deleted in the following circumstances: -// 1) Reset() is called. -// 2) OnRemoteReset() is indicated. -// 3) Finish() and OnRemoteFinish() have been called. -// The QuicStreamHost will instruct the QuicTransportHost to delete it when any -// condition has been met. -// -// Since the QuicStreamHost can be constructed from either the proxy or host -// thread, initialization happens in three steps: -// 1) QuicStreamHost is constructed. -// 2) set_proxy is called when a WeakPtr to the corresponding proxy-thread -// object. -// 3) Initialize is called on the host thread. -class QuicStreamHost final : public base::SupportsWeakPtr<QuicStreamHost>, - public P2PQuicStream::Delegate { - public: - QuicStreamHost(); - ~QuicStreamHost() override; - - // Sets a WeakPtr to the corresponding QuicStreamProxy. This is valid on - // either the proxy or host thread. Should happen right after construction. - void set_proxy(base::WeakPtr<QuicStreamProxy> stream_proxy); - - // Initializes the QuicStreamHost. Must be called on the host thread. - // |transport_host| must outlive this object. - void Initialize(QuicTransportHost* transport_host, P2PQuicStream* p2p_stream); - - // The remaining methods can only be called from the host thread and must be - // preceded by Initialize(). - - scoped_refptr<base::SingleThreadTaskRunner> proxy_thread() const; - - void Reset(); - void MarkReceivedDataConsumed(uint32_t amount); - void WriteData(Vector<uint8_t> data, bool fin); - - private: - // Instruct the QuicTransportHost to remove and delete this stream host. - void Delete(); - - // P2PQuicStream::Delegate overrides. - void OnRemoteReset() override; - void OnDataReceived(Vector<uint8_t> data, bool fin) override; - void OnWriteDataConsumed(uint32_t amount) override; - - // Up reference. Owned by QuicTransportProxy. - QuicTransportHost* transport_host_ = nullptr; - // Forward reference. Owned by P2PQuicTransport. - P2PQuicStream* p2p_stream_ = nullptr; - // Back reference. Owned by QuicTransportProxy. - base::WeakPtr<QuicStreamProxy> stream_proxy_; - - // |readable_| transitions to false when OnDataReceived(_, true) is called. - bool readable_ = true; - // |writable_| transitions to false when WriteData(_, true) is called. - bool writable_ = true; - - THREAD_CHECKER(thread_checker_); -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_QUIC_STREAM_HOST_H_
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_proxy.cc b/third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_proxy.cc deleted file mode 100644 index fa1f566..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_proxy.cc +++ /dev/null
@@ -1,111 +0,0 @@ -// Copyright 2018 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/peerconnection/adapters/quic_stream_proxy.h" - -#include "third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_host.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_proxy.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/web_rtc_cross_thread_copier.h" -#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" -#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" - -namespace blink { - -QuicStreamProxy::QuicStreamProxy() { - DETACH_FROM_THREAD(thread_checker_); -} - -QuicStreamProxy::~QuicStreamProxy() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); -} - -void QuicStreamProxy::set_host(base::WeakPtr<QuicStreamHost> stream_host) { - DETACH_FROM_THREAD(thread_checker_); - stream_host_ = stream_host; -} - -void QuicStreamProxy::Initialize(QuicTransportProxy* transport_proxy) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(transport_proxy); - transport_proxy_ = transport_proxy; -} - -void QuicStreamProxy::set_delegate(Delegate* delegate) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(delegate); - delegate_ = delegate; -} - -scoped_refptr<base::SingleThreadTaskRunner> QuicStreamProxy::host_thread() - const { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(transport_proxy_); - return transport_proxy_->host_thread(); -} - -void QuicStreamProxy::Reset() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - PostCrossThreadTask( - *host_thread(), FROM_HERE, - CrossThreadBindOnce(&QuicStreamHost::Reset, stream_host_)); - Delete(); -} - -void QuicStreamProxy::MarkReceivedDataConsumed(uint32_t amount) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - PostCrossThreadTask( - *host_thread(), FROM_HERE, - CrossThreadBindOnce(&QuicStreamHost::MarkReceivedDataConsumed, - stream_host_, amount)); -} - -void QuicStreamProxy::WriteData(Vector<uint8_t> data, bool fin) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - PostCrossThreadTask(*host_thread(), FROM_HERE, - CrossThreadBindOnce(&QuicStreamHost::WriteData, - stream_host_, std::move(data), fin)); - if (fin) { - writable_ = false; - if (!readable_ && !writable_) { - Delete(); - } - } -} - -void QuicStreamProxy::OnRemoteReset() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(delegate_); - // Need to copy the |delegate_| member since Delete() will destroy |this|. - Delegate* delegate_copy = delegate_; - Delete(); - delegate_copy->OnRemoteReset(); -} - -void QuicStreamProxy::OnDataReceived(Vector<uint8_t> data, bool fin) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(delegate_); - // Need to copy the |delegate_| member since Delete() will destroy |this|. - Delegate* delegate_copy = delegate_; - if (fin) { - readable_ = false; - if (!readable_ && !writable_) { - Delete(); - } - } - delegate_copy->OnDataReceived(std::move(data), fin); -} - -void QuicStreamProxy::OnWriteDataConsumed(uint32_t amount) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(delegate_); - delegate_->OnWriteDataConsumed(amount); -} - -void QuicStreamProxy::Delete() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - // OnRemoveStream will delete |this|. - transport_proxy_->OnRemoveStream(this); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_proxy.h b/third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_proxy.h deleted file mode 100644 index 5881aef8..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_proxy.h +++ /dev/null
@@ -1,103 +0,0 @@ -// Copyright 2018 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_PEERCONNECTION_ADAPTERS_QUIC_STREAM_PROXY_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_QUIC_STREAM_PROXY_H_ - -#include "base/memory/scoped_refptr.h" -#include "base/memory/weak_ptr.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_checker.h" -#include "third_party/blink/renderer/platform/wtf/vector.h" - -namespace blink { - -class QuicStreamHost; -class QuicTransportProxy; - -// This class allows interactions with a QUIC stream that runs on a thread -// different from which it is controlled. All interactions with the QUIC -// implementation happen asynchronously. -// -// The QuicStreamProxy is owned by the QuicTransportProxy and constructed when -// either a new local QUIC stream is created or when a remote QUIC stream has -// been created. The stream proxy will be deleted in the following -// circumstances: -// 1) Reset() is called. -// 2) OnRemoteReset() is indicated. -// 3) Finish() and OnRemoteFinish() have been called. -// The client is responsible for knowing when any of these conditions have been -// met and clearing its reference accordingly. -// -// Since the QuicStreamProxy can be constructed from either the proxy or host -// thread, initialization happens in four steps: -// 1) QuicStreamProxy is constructed. -// 2) set_host is called with a WeakPtr to the corresponding host-thread object. -// 3) Initialize is called on the proxy thread. -// 4) set_delegate is called on the proxy thread. -class QuicStreamProxy final : public base::SupportsWeakPtr<QuicStreamProxy> { - public: - class Delegate { - public: - virtual ~Delegate() = default; - - // Called when the remote side resets the stream. - virtual void OnRemoteReset() {} - // Called when the remote side receives data and/or the finish bit. - virtual void OnDataReceived(Vector<uint8_t> data, bool fin) {} - // Called when data written with WriteData() has been consumed by QUIC. - virtual void OnWriteDataConsumed(uint32_t amount) {} - }; - - QuicStreamProxy(); - ~QuicStreamProxy(); - - // Sets a WeakPtr to the corresponding QuicStreamHost. This is valid on either - // the proxy or host thread. Should happen right after construction. - void set_host(base::WeakPtr<QuicStreamHost> stream_host); - - // Initializes the QuicStreamProxy. Must be called on the proxy thread. - // |transport_proxy| must outlive this object. - void Initialize(QuicTransportProxy* transport_proxy); - - // Sets the delegate for receiving remote callbacks. - void set_delegate(Delegate* delegate); - - // The remaining methods can only be called from the proxy thread and must - // be preceded by Initialize(). - - scoped_refptr<base::SingleThreadTaskRunner> host_thread() const; - - void Reset(); - void MarkReceivedDataConsumed(uint32_t amount); - void WriteData(Vector<uint8_t> data, bool fin); - - private: - // Instruct the QuicTransportProxy to remove and delete this stream proxy. - void Delete(); - - // Callbacks from QuicStreamHost. - friend class QuicStreamHost; - void OnRemoteReset(); - void OnDataReceived(Vector<uint8_t> data, bool fin); - void OnWriteDataConsumed(uint32_t amount); - - // Up reference. Owned by the QuicTransportProxy client. - QuicTransportProxy* transport_proxy_ = nullptr; - // Forward reference. Owned by the QuicTransportHost. - base::WeakPtr<QuicStreamHost> stream_host_; - // Back reference. Owned by the RTCQuicTransport. - Delegate* delegate_ = nullptr; - - // |readable_| transitions to false when OnDataReceived(_, true) is called. - bool readable_ = true; - // |writable_| transitions to false when WriteData(_, true) is called. - bool writable_ = true; - - THREAD_CHECKER(thread_checker_); -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_QUIC_STREAM_PROXY_H_
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_host.cc b/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_host.cc deleted file mode 100644 index 69d8565..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_host.cc +++ /dev/null
@@ -1,167 +0,0 @@ -// Copyright 2018 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/peerconnection/adapters/quic_transport_host.h" - -#include <utility> - -#include "third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_host.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_factory.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_host.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_proxy.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_proxy.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/web_rtc_cross_thread_copier.h" -#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" -#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" - -namespace blink { - -QuicTransportHost::QuicTransportHost( - base::WeakPtr<QuicTransportProxy> proxy, - std::unique_ptr<P2PQuicTransportFactory> quic_transport_factory) - : quic_transport_factory_(std::move(quic_transport_factory)), - proxy_(std::move(proxy)) { - DETACH_FROM_THREAD(thread_checker_); - DCHECK(quic_transport_factory_); - DCHECK(proxy_); -} - -QuicTransportHost::~QuicTransportHost() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - // If the TaskRunner this is getting initialized on is destroyed before - // Initialize is called then |ice_transport_host_| may still be null. - if (ice_transport_host_) { - ice_transport_host_->DisconnectConsumer(this); - } -} - -void QuicTransportHost::Initialize(IceTransportHost* ice_transport_host, - const P2PQuicTransportConfig& config) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(ice_transport_host); - DCHECK(!ice_transport_host_); - ice_transport_host_ = ice_transport_host; - IceTransportAdapter* ice_transport_adapter = - ice_transport_host_->ConnectConsumer(this); - quic_transport_ = quic_transport_factory_->CreateQuicTransport( - /*delegate=*/this, ice_transport_adapter->packet_transport(), config); -} - -scoped_refptr<base::SingleThreadTaskRunner> QuicTransportHost::proxy_thread() - const { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - return ice_transport_host_->proxy_thread(); -} - -scoped_refptr<base::SingleThreadTaskRunner> QuicTransportHost::host_thread() - const { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - return ice_transport_host_->host_thread(); -} - -void QuicTransportHost::Start(P2PQuicTransport::StartConfig config) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - quic_transport_->Start(std::move(config)); -} - -void QuicTransportHost::Stop() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - quic_transport_->Stop(); -} - -void QuicTransportHost::CreateStream( - std::unique_ptr<QuicStreamHost> stream_host) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - P2PQuicStream* p2p_stream = quic_transport_->CreateStream(); - stream_host->Initialize(this, p2p_stream); - stream_hosts_.insert(stream_host.get(), std::move(stream_host)); -} - -void QuicTransportHost::SendDatagram(Vector<uint8_t> datagram) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - quic_transport_->SendDatagram(std::move(datagram)); -} - -void QuicTransportHost::GetStats(uint32_t request_id) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - P2PQuicTransportStats stats = quic_transport_->GetStats(); - PostCrossThreadTask(*proxy_thread(), FROM_HERE, - CrossThreadBindOnce(&QuicTransportProxy::OnStats, proxy_, - request_id, stats)); -} - -void QuicTransportHost::OnRemoveStream(QuicStreamHost* stream_host_to_remove) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - auto it = stream_hosts_.find(stream_host_to_remove); - DCHECK(it != stream_hosts_.end()); - stream_hosts_.erase(it); -} - -void QuicTransportHost::OnRemoteStopped() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - stream_hosts_.clear(); - PostCrossThreadTask( - *proxy_thread(), FROM_HERE, - CrossThreadBindOnce(&QuicTransportProxy::OnRemoteStopped, proxy_)); -} - -void QuicTransportHost::OnConnectionFailed(const std::string& error_details, - bool from_remote) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - stream_hosts_.clear(); - PostCrossThreadTask( - *proxy_thread(), FROM_HERE, - CrossThreadBindOnce(&QuicTransportProxy::OnConnectionFailed, proxy_, - error_details, from_remote)); -} - -void QuicTransportHost::OnConnected(P2PQuicNegotiatedParams negotiated_params) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - PostCrossThreadTask(*proxy_thread(), FROM_HERE, - CrossThreadBindOnce(&QuicTransportProxy::OnConnected, - proxy_, negotiated_params)); -} - -void QuicTransportHost::OnStream(P2PQuicStream* p2p_stream) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(p2p_stream); - - auto stream_proxy = std::make_unique<QuicStreamProxy>(); - auto stream_host = std::make_unique<QuicStreamHost>(); - stream_proxy->set_host(stream_host->AsWeakPtr()); - stream_host->set_proxy(stream_proxy->AsWeakPtr()); - - stream_host->Initialize(this, p2p_stream); - - stream_hosts_.insert(stream_host.get(), std::move(stream_host)); - - PostCrossThreadTask( - *proxy_thread(), FROM_HERE, - CrossThreadBindOnce(&QuicTransportProxy::OnStream, proxy_, - WTF::Passed(std::move(stream_proxy)))); -} - -void QuicTransportHost::OnDatagramSent() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - PostCrossThreadTask( - *proxy_thread(), FROM_HERE, - CrossThreadBindOnce(&QuicTransportProxy::OnDatagramSent, proxy_)); -} - -void QuicTransportHost::OnDatagramReceived(Vector<uint8_t> datagram) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - PostCrossThreadTask( - *proxy_thread(), FROM_HERE, - CrossThreadBindOnce(&QuicTransportProxy::OnDatagramReceived, proxy_, - std::move(datagram))); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_host.h b/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_host.h deleted file mode 100644 index bf6fd6c0..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_host.h +++ /dev/null
@@ -1,91 +0,0 @@ -// Copyright 2018 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_PEERCONNECTION_ADAPTERS_QUIC_TRANSPORT_HOST_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_QUIC_TRANSPORT_HOST_H_ - -#include "base/memory/scoped_refptr.h" -#include "base/memory/weak_ptr.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_checker.h" -#include "net/third_party/quiche/src/quic/core/quic_types.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_factory.h" -#include "third_party/blink/renderer/platform/wtf/hash_map.h" - -namespace blink { - -class IceTransportHost; -class QuicStreamHost; -class QuicTransportProxy; - -// The host class is the host side correspondent to the QuicTransportProxy. See -// the QuicTransportProxy documentation for background. This class lives on the -// host thread and proxies calls between the QuicTransportProxy and the -// P2PQuicTransport (which is single-threaded). -// -// proxy thread host thread -// +-----------------------+ +-----------------------------------+ -// | | | | -// | <-> ICE Proxy | =========> | ICE Host <-> P2PTransportChannel | -// | ^ | <--------- | ^ ^ | -// | client | | | | | | -// | v | | v v | -// | <-> QUIC Proxy | =========> | QUIC Host <-> P2PQuicTransport | -// | | <--------- | | -// +-----------------------+ +-----------------------------------+ -// -// The QuicTransportHost connects to the underlying IceTransportHost in -// Initialize and disconnects in the destructor. The IceTransportHost must -// outlive the QuicTransportHost. -// -// The Host can be constructed on any thread but after that point all methods -// must be called on the host thread. -class QuicTransportHost final : public P2PQuicTransport::Delegate { - public: - QuicTransportHost( - base::WeakPtr<QuicTransportProxy> transport_proxy, - std::unique_ptr<P2PQuicTransportFactory> quic_transport_factory); - ~QuicTransportHost() override; - - void Initialize(IceTransportHost* ice_transport_host, - const P2PQuicTransportConfig& config); - - scoped_refptr<base::SingleThreadTaskRunner> proxy_thread() const; - scoped_refptr<base::SingleThreadTaskRunner> host_thread() const; - - void Start(P2PQuicTransport::StartConfig config); - void Stop(); - - void CreateStream(std::unique_ptr<QuicStreamHost> stream_host); - - void SendDatagram(Vector<uint8_t> datagram); - - void GetStats(uint32_t request_id); - - // QuicStreamHost callbacks. - void OnRemoveStream(QuicStreamHost* stream_host_to_remove); - - private: - // P2PQuicTransport::Delegate overrides. - void OnRemoteStopped() override; - void OnConnectionFailed(const std::string& error_details, - bool from_remote) override; - void OnConnected(P2PQuicNegotiatedParams negotiated_params) override; - void OnStream(P2PQuicStream* stream) override; - void OnDatagramSent() override; - void OnDatagramReceived(Vector<uint8_t> datagram) override; - - std::unique_ptr<P2PQuicTransportFactory> quic_transport_factory_; - std::unique_ptr<P2PQuicTransport> quic_transport_; - base::WeakPtr<QuicTransportProxy> proxy_; - IceTransportHost* ice_transport_host_ = nullptr; - HashMap<QuicStreamHost*, std::unique_ptr<QuicStreamHost>> stream_hosts_; - - THREAD_CHECKER(thread_checker_); -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_QUIC_TRANSPORT_HOST_H_
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_proxy.cc b/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_proxy.cc deleted file mode 100644 index 3af56de..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_proxy.cc +++ /dev/null
@@ -1,184 +0,0 @@ -// Copyright 2018 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/peerconnection/adapters/quic_transport_proxy.h" - -#include "third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_host.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_proxy.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_factory.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_host.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_proxy.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_host.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/web_rtc_cross_thread_copier.h" -#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" -#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" - -namespace blink { - -QuicTransportProxy::QuicTransportProxy( - Delegate* delegate, - IceTransportProxy* ice_transport_proxy, - std::unique_ptr<P2PQuicTransportFactory> quic_transport_factory, - const P2PQuicTransportConfig& config) - : host_(nullptr, - base::OnTaskRunnerDeleter(ice_transport_proxy->host_thread())), - delegate_(delegate), - ice_transport_proxy_(ice_transport_proxy) { - DCHECK(delegate_); - DCHECK(ice_transport_proxy_); - scoped_refptr<base::SingleThreadTaskRunner> proxy_thread = - ice_transport_proxy->proxy_thread(); - DCHECK(proxy_thread->BelongsToCurrentThread()); - // Wait to initialize the host until the weak_ptr_factory_ is initialized. - // The QuicTransportHost is constructed on the proxy thread but should only be - // interacted with via PostTask to the host thread. The OnTaskRunnerDeleter - // (configured above) will ensure it gets deleted on the host thread. - host_.reset(new QuicTransportHost(weak_ptr_factory_.GetWeakPtr(), - std::move(quic_transport_factory))); - // Connect to the IceTransportProxy. This gives us a reference to the - // underlying IceTransportHost that should be connected by the - // QuicTransportHost on the host thread. It is safe to post it unretained - // since the IceTransportHost's ownership is determined by the - // IceTransportProxy, and the IceTransportProxy is required to outlive this - // object. - IceTransportHost* ice_transport_host = - ice_transport_proxy->ConnectConsumer(this); - PostCrossThreadTask( - *host_thread(), FROM_HERE, - CrossThreadBindOnce(&QuicTransportHost::Initialize, - CrossThreadUnretained(host_.get()), - CrossThreadUnretained(ice_transport_host), config)); -} - -QuicTransportProxy::~QuicTransportProxy() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - ice_transport_proxy_->DisconnectConsumer(this); - // Note: The QuicTransportHost will be deleted on the host thread. -} - -scoped_refptr<base::SingleThreadTaskRunner> QuicTransportProxy::proxy_thread() - const { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - return ice_transport_proxy_->proxy_thread(); -} - -scoped_refptr<base::SingleThreadTaskRunner> QuicTransportProxy::host_thread() - const { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - return ice_transport_proxy_->host_thread(); -} - -void QuicTransportProxy::Start(P2PQuicTransport::StartConfig config) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - PostCrossThreadTask(*host_thread(), FROM_HERE, - CrossThreadBindOnce(&QuicTransportHost::Start, - CrossThreadUnretained(host_.get()), - WTF::Passed(std::move(config)))); -} - -void QuicTransportProxy::Stop() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - PostCrossThreadTask(*host_thread(), FROM_HERE, - CrossThreadBindOnce(&QuicTransportHost::Stop, - CrossThreadUnretained(host_.get()))); -} - -QuicStreamProxy* QuicTransportProxy::CreateStream() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - auto stream_proxy = std::make_unique<QuicStreamProxy>(); - auto stream_host = std::make_unique<QuicStreamHost>(); - stream_proxy->set_host(stream_host->AsWeakPtr()); - stream_host->set_proxy(stream_proxy->AsWeakPtr()); - - stream_proxy->Initialize(this); - - PostCrossThreadTask(*host_thread(), FROM_HERE, - CrossThreadBindOnce(&QuicTransportHost::CreateStream, - CrossThreadUnretained(host_.get()), - WTF::Passed(std::move(stream_host)))); - - QuicStreamProxy* stream_proxy_ptr = stream_proxy.get(); - stream_proxies_.insert(stream_proxy_ptr, std::move(stream_proxy)); - return stream_proxy_ptr; -} - -void QuicTransportProxy::SendDatagram(Vector<uint8_t> datagram) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - PostCrossThreadTask(*host_thread(), FROM_HERE, - CrossThreadBindOnce(&QuicTransportHost::SendDatagram, - CrossThreadUnretained(host_.get()), - std::move(datagram))); -} - -void QuicTransportProxy::GetStats(uint32_t request_id) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - PostCrossThreadTask( - *host_thread(), FROM_HERE, - CrossThreadBindOnce(&QuicTransportHost::GetStats, - CrossThreadUnretained(host_.get()), request_id)); -} - -void QuicTransportProxy::OnRemoveStream( - QuicStreamProxy* stream_proxy_to_remove) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - auto it = stream_proxies_.find(stream_proxy_to_remove); - DCHECK(it != stream_proxies_.end()); - stream_proxies_.erase(it); -} - -void QuicTransportProxy::OnConnected( - P2PQuicNegotiatedParams negotiated_params) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - delegate_->OnConnected(negotiated_params); -} - -void QuicTransportProxy::OnRemoteStopped() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - stream_proxies_.clear(); - delegate_->OnRemoteStopped(); -} - -void QuicTransportProxy::OnConnectionFailed(const std::string& error_details, - bool from_remote) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - stream_proxies_.clear(); - delegate_->OnConnectionFailed(error_details, from_remote); -} - -void QuicTransportProxy::OnStream( - std::unique_ptr<QuicStreamProxy> stream_proxy) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - stream_proxy->Initialize(this); - - QuicStreamProxy* stream_proxy_ptr = stream_proxy.get(); - stream_proxies_.insert(stream_proxy_ptr, std::move(stream_proxy)); - delegate_->OnStream(stream_proxy_ptr); -} - -void QuicTransportProxy::OnStats(uint32_t request_id, - const P2PQuicTransportStats& stats) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - delegate_->OnStats(request_id, stats); -} - -void QuicTransportProxy::OnDatagramSent() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - delegate_->OnDatagramSent(); -} - -void QuicTransportProxy::OnDatagramReceived(Vector<uint8_t> datagram) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - delegate_->OnDatagramReceived(std::move(datagram)); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_proxy.h b/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_proxy.h deleted file mode 100644 index 387b2db..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_proxy.h +++ /dev/null
@@ -1,125 +0,0 @@ -// Copyright 2018 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_PEERCONNECTION_ADAPTERS_QUIC_TRANSPORT_PROXY_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_QUIC_TRANSPORT_PROXY_H_ - -#include "base/memory/scoped_refptr.h" -#include "base/memory/weak_ptr.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_checker.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_factory.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_stats.h" -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" -#include "third_party/blink/renderer/platform/wtf/hash_map.h" -#include "third_party/blink/renderer/platform/wtf/vector.h" -#include "third_party/webrtc/api/scoped_refptr.h" - -namespace blink { - -class IceTransportProxy; -class QuicStreamProxy; -class QuicTransportHost; - -// This class allows the QUIC implementation (P2PQuicTransport) to run on a -// thread different from the thread from which it is controlled. All -// interactions with the QUIC implementation happen asynchronously. -// -// The QuicTransportProxy is intended to be used with an IceTransportProxy -- -// see the IceTransportProxy class documentation for background and terms. The -// proxy and host threads used with the QuicTransportProxy should be the same as -// the ones used with the connected IceTransportProxy. -class QuicTransportProxy final { - USING_FAST_MALLOC(QuicTransportProxy); - - public: - // Delegate for receiving callbacks from the QUIC implementation. These all - // run on the proxy thread. - class Delegate { - public: - virtual ~Delegate() = default; - - // Called when the QUIC handshake finishes and fingerprints have been - // verified. - virtual void OnConnected(P2PQuicNegotiatedParams negotiated_params) {} - // Called when the remote side has indicated it is closed. - virtual void OnRemoteStopped() {} - // Called when the connection is closed due to a QUIC error. This can happen - // locally by the framer or remotely by the peer. - virtual void OnConnectionFailed(const std::string& error_details, - bool from_remote) {} - // Called when the remote side has created a new stream. - virtual void OnStream(QuicStreamProxy* stream_proxy) {} - - // Called after the stats have been gathered on the host thread. The - // |request_id| maps to |request_id| used in GetStats(). - virtual void OnStats(uint32_t request_id, - const P2PQuicTransportStats& stats) {} - // Called when the datagram (sent with SendDatagram) has been - // consumed by the QUIC library and sent on the network. - virtual void OnDatagramSent() {} - // Called when we receive a datagram from the remote side. - virtual void OnDatagramReceived(Vector<uint8_t> datagram) {} - }; - - // Construct a Proxy with the underlying QUIC implementation running on the - // same thread as the IceTransportProxy. Callbacks will be serviced by the - // given delegate. - // The delegate and IceTransportProxy must outlive the QuicTransportProxy. - // The QuicTransportProxy will immediately connect to the given - // IceTransportProxy; it can be disconnected by destroying the - // QuicTransportProxy object. - QuicTransportProxy( - Delegate* delegate, - IceTransportProxy* ice_transport_proxy, - std::unique_ptr<P2PQuicTransportFactory> quic_transport_factory, - const P2PQuicTransportConfig& config); - ~QuicTransportProxy(); - - scoped_refptr<base::SingleThreadTaskRunner> proxy_thread() const; - scoped_refptr<base::SingleThreadTaskRunner> host_thread() const; - - void Start(P2PQuicTransport::StartConfig config); - void Stop(); - - QuicStreamProxy* CreateStream(); - - void SendDatagram(Vector<uint8_t> datagram); - - // Gathers stats on the host thread, then returns them asynchronously with - // Delegate::OnStats. The |request_id| is used to map the GetStats call to the - // returned stats. - void GetStats(uint32_t request_id); - - // QuicStreamProxy callbacks. - void OnRemoveStream(QuicStreamProxy* stream_proxy); - - private: - // Callbacks from QuicTransportHost. - friend class QuicTransportHost; - void OnConnected(P2PQuicNegotiatedParams negotiated_params); - void OnRemoteStopped(); - void OnConnectionFailed(const std::string& error_details, bool from_remote); - void OnStream(std::unique_ptr<QuicStreamProxy> stream_proxy); - void OnStats(uint32_t request_id, const P2PQuicTransportStats& stats); - void OnDatagramSent(); - void OnDatagramReceived(Vector<uint8_t> datagram); - - // Since the Host is deleted on the host thread (Via OnTaskRunnerDeleter), as - // long as this is alive it is safe to post tasks to it (using unretained). - std::unique_ptr<QuicTransportHost, base::OnTaskRunnerDeleter> host_; - Delegate* const delegate_; - IceTransportProxy* ice_transport_proxy_; - HashMap<QuicStreamProxy*, std::unique_ptr<QuicStreamProxy>> stream_proxies_; - - THREAD_CHECKER(thread_checker_); - - // Must be the last member. - base::WeakPtrFactory<QuicTransportProxy> weak_ptr_factory_{this}; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_QUIC_TRANSPORT_PROXY_H_
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/test/mock_ice_transport_adapter.h b/third_party/blink/renderer/modules/peerconnection/adapters/test/mock_ice_transport_adapter.h index 3c6c2a0..d5f867b 100644 --- a/third_party/blink/renderer/modules/peerconnection/adapters/test/mock_ice_transport_adapter.h +++ b/third_party/blink/renderer/modules/peerconnection/adapters/test/mock_ice_transport_adapter.h
@@ -7,20 +7,12 @@ #include "testing/gmock/include/gmock/gmock.h" #include "third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_adapter.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_packet_transport.h" namespace blink { class MockIceTransportAdapter : public testing::NiceMock<IceTransportAdapter> { public: - MockIceTransportAdapter() : MockIceTransportAdapter(nullptr) {} - MockIceTransportAdapter( - std::unique_ptr<P2PQuicPacketTransport> packet_transport) - : packet_transport_(std::move(packet_transport)) { - ON_CALL(*this, packet_transport()).WillByDefault(testing::Invoke([this] { - return packet_transport_.get(); - })); - } + MockIceTransportAdapter() = default; ~MockIceTransportAdapter() override { Die(); } MOCK_METHOD0(Die, void()); @@ -36,10 +28,6 @@ const Vector<cricket::Candidate>&)); MOCK_METHOD1(HandleRemoteRestart, void(const cricket::IceParameters&)); MOCK_METHOD1(AddRemoteCandidate, void(const cricket::Candidate&)); - MOCK_CONST_METHOD0(packet_transport, P2PQuicPacketTransport*()); - - private: - std::unique_ptr<P2PQuicPacketTransport> packet_transport_; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/test/mock_p2p_quic_packet_transport.h b/third_party/blink/renderer/modules/peerconnection/adapters/test/mock_p2p_quic_packet_transport.h deleted file mode 100644 index 9e28706e..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/test/mock_p2p_quic_packet_transport.h +++ /dev/null
@@ -1,24 +0,0 @@ -// Copyright 2018 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_PEERCONNECTION_ADAPTERS_TEST_MOCK_P2P_QUIC_PACKET_TRANSPORT_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_TEST_MOCK_P2P_QUIC_PACKET_TRANSPORT_H_ - -#include "testing/gmock/include/gmock/gmock.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_packet_transport.h" - -namespace blink { - -class MockP2PQuicPacketTransport : public P2PQuicPacketTransport { - public: - // P2PQuicPacketTransport overrides. - MOCK_METHOD1(WritePacket, int(const QuicPacket&)); - MOCK_METHOD1(SetReceiveDelegate, void(ReceiveDelegate*)); - MOCK_METHOD1(SetWriteObserver, void(WriteObserver*)); - MOCK_METHOD0(Writable, bool()); -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_TEST_MOCK_P2P_QUIC_PACKET_TRANSPORT_H_
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/test/mock_p2p_quic_stream.h b/third_party/blink/renderer/modules/peerconnection/adapters/test/mock_p2p_quic_stream.h deleted file mode 100644 index 3db62fd..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/test/mock_p2p_quic_stream.h +++ /dev/null
@@ -1,36 +0,0 @@ -// Copyright 2018 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_PEERCONNECTION_ADAPTERS_TEST_MOCK_P2P_QUIC_STREAM_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_TEST_MOCK_P2P_QUIC_STREAM_H_ - -#include "testing/gmock/include/gmock/gmock.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream.h" - -namespace blink { - -class MockP2PQuicStream : public testing::NiceMock<P2PQuicStream> { - public: - explicit MockP2PQuicStream(P2PQuicStream::Delegate** delegate_out = nullptr) { - if (delegate_out) { - // Ensure the caller has not left the delegate_out value floating. - DCHECK_EQ(nullptr, *delegate_out); - EXPECT_CALL(*this, SetDelegate(testing::_)) - .WillOnce(testing::Invoke( - [delegate_out](P2PQuicStream::Delegate* delegate) { - *delegate_out = delegate; - })); - } - } - - // P2PQuicStream overrides. - MOCK_METHOD0(Reset, void()); - MOCK_METHOD1(MarkReceivedDataConsumed, void(uint32_t)); - MOCK_METHOD2(WriteData, void(Vector<uint8_t>, bool)); - MOCK_METHOD1(SetDelegate, void(Delegate*)); -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_TEST_MOCK_P2P_QUIC_STREAM_H_
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/test/mock_p2p_quic_stream_delegate.h b/third_party/blink/renderer/modules/peerconnection/adapters/test/mock_p2p_quic_stream_delegate.h deleted file mode 100644 index a33d4ddf..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/test/mock_p2p_quic_stream_delegate.h +++ /dev/null
@@ -1,24 +0,0 @@ -// Copyright 2018 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_PEERCONNECTION_ADAPTERS_TEST_MOCK_P2P_QUIC_STREAM_DELEGATE_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_TEST_MOCK_P2P_QUIC_STREAM_DELEGATE_H_ - -#include "testing/gmock/include/gmock/gmock.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream.h" - -namespace blink { - -class MockP2PQuicStreamDelegate - : public testing::NiceMock<P2PQuicStream::Delegate> { - public: - // P2PQuicStream::Delegate overrides. - MOCK_METHOD1(OnWriteDataConsumed, void(uint32_t)); - MOCK_METHOD0(OnRemoteReset, void()); - MOCK_METHOD2(OnDataReceived, void(Vector<uint8_t>, bool)); -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_TEST_MOCK_P2P_QUIC_STREAM_DELEGATE_H_
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/test/mock_p2p_quic_transport.h b/third_party/blink/renderer/modules/peerconnection/adapters/test/mock_p2p_quic_transport.h deleted file mode 100644 index e9cfc96..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/test/mock_p2p_quic_transport.h +++ /dev/null
@@ -1,30 +0,0 @@ -// Copyright 2018 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_PEERCONNECTION_ADAPTERS_TEST_MOCK_P2P_QUIC_TRANSPORT_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_TEST_MOCK_P2P_QUIC_TRANSPORT_H_ - -#include "testing/gmock/include/gmock/gmock.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_stats.h" - -namespace blink { - -class MockP2PQuicTransport : public testing::NiceMock<P2PQuicTransport> { - public: - ~MockP2PQuicTransport() override { Die(); } - MOCK_METHOD0(Die, void()); - - // P2PQuicTransport overrides. - MOCK_METHOD0(Stop, void()); - void Start(StartConfig config) override { MockStart(config); } - MOCK_METHOD1(MockStart, void(const StartConfig&)); - MOCK_METHOD0(CreateStream, P2PQuicStream*()); - MOCK_CONST_METHOD0(GetStats, P2PQuicTransportStats()); - MOCK_METHOD1(SendDatagram, void(Vector<uint8_t>)); -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_TEST_MOCK_P2P_QUIC_TRANSPORT_H_
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/test/mock_p2p_quic_transport_delegate.h b/third_party/blink/renderer/modules/peerconnection/adapters/test/mock_p2p_quic_transport_delegate.h deleted file mode 100644 index b702cc8f..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/test/mock_p2p_quic_transport_delegate.h +++ /dev/null
@@ -1,27 +0,0 @@ -// Copyright 2018 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_PEERCONNECTION_ADAPTERS_TEST_MOCK_P2P_QUIC_TRANSPORT_DELEGATE_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_TEST_MOCK_P2P_QUIC_TRANSPORT_DELEGATE_H_ - -#include "testing/gmock/include/gmock/gmock.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport.h" - -namespace blink { - -class MockP2PQuicTransportDelegate - : public testing::NiceMock<P2PQuicTransport::Delegate> { - public: - // P2PQuicTransport::Delegate overrides. - MOCK_METHOD0(OnRemoteStopped, void()); - MOCK_METHOD2(OnConnectionFailed, void(const std::string&, bool)); - MOCK_METHOD1(OnConnected, void(P2PQuicNegotiatedParams)); - MOCK_METHOD1(OnStream, void(P2PQuicStream*)); - MOCK_METHOD1(OnDatagramReceived, void(Vector<uint8_t> datagram)); - MOCK_METHOD0(OnDatagramSent, void()); -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_TEST_MOCK_P2P_QUIC_TRANSPORT_DELEGATE_H_
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/test/mock_p2p_quic_transport_factory.h b/third_party/blink/renderer/modules/peerconnection/adapters/test/mock_p2p_quic_transport_factory.h deleted file mode 100644 index a6bc14f..0000000 --- a/third_party/blink/renderer/modules/peerconnection/adapters/test/mock_p2p_quic_transport_factory.h +++ /dev/null
@@ -1,54 +0,0 @@ -// Copyright 2018 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_PEERCONNECTION_ADAPTERS_TEST_MOCK_P2P_QUIC_TRANSPORT_FACTORY_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_TEST_MOCK_P2P_QUIC_TRANSPORT_FACTORY_H_ - -#include "testing/gmock/include/gmock/gmock.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_factory.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/test/mock_p2p_quic_transport.h" - -namespace blink { - -class MockP2PQuicTransportFactory - : public testing::NiceMock<P2PQuicTransportFactory> { - public: - MockP2PQuicTransportFactory() = default; - MockP2PQuicTransportFactory( - std::unique_ptr<MockP2PQuicTransport> mock_transport, - P2PQuicTransport::Delegate** delegate_out = nullptr) - : mock_transport_(std::move(mock_transport)), - delegate_out_(delegate_out) { - if (delegate_out) { - // Ensure the caller has not left the delegate_out value floating. - DCHECK_EQ(nullptr, *delegate_out); - } - ON_CALL(*this, CreateQuicTransport(testing::_, testing::_, testing::_)) - .WillByDefault( - testing::Invoke([this](P2PQuicTransport::Delegate* delegate, - P2PQuicPacketTransport* packet_transport, - const P2PQuicTransportConfig& config) { - DCHECK(mock_transport_); - if (delegate_out_) { - *delegate_out_ = delegate; - } - return std::move(mock_transport_); - })); - } - - // P2PQuicTransportFactory overrides. - MOCK_METHOD3(CreateQuicTransport, - std::unique_ptr<P2PQuicTransport>( - P2PQuicTransport::Delegate* delegate, - P2PQuicPacketTransport* packet_transport, - const P2PQuicTransportConfig& config)); - - private: - std::unique_ptr<MockP2PQuicTransport> mock_transport_; - P2PQuicTransport::Delegate** delegate_out_ = nullptr; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_TEST_MOCK_P2P_QUIC_TRANSPORT_FACTORY_H_
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/web_rtc_cross_thread_copier.h b/third_party/blink/renderer/modules/peerconnection/adapters/web_rtc_cross_thread_copier.h index ad74f6a..6167403 100644 --- a/third_party/blink/renderer/modules/peerconnection/adapters/web_rtc_cross_thread_copier.h +++ b/third_party/blink/renderer/modules/peerconnection/adapters/web_rtc_cross_thread_copier.h
@@ -12,7 +12,6 @@ #include <vector> #include "third_party/blink/public/platform/web_vector.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport.h" #include "third_party/blink/renderer/platform/wtf/cross_thread_copier.h" #include "third_party/blink/renderer/platform/wtf/vector.h" #include "third_party/webrtc/api/rtc_error.h" @@ -41,7 +40,6 @@ class MockWebRtcVideoTrack; class MediaStreamVideoTrack; -struct P2PQuicTransportConfig; } @@ -86,12 +84,6 @@ }; template <> -struct CrossThreadCopier<blink::P2PQuicTransportConfig> - : public CrossThreadCopierPassThrough<blink::P2PQuicTransportConfig> { - STATIC_ONLY(CrossThreadCopier); -}; - -template <> struct CrossThreadCopier<webrtc::DtlsTransportInformation> : public CrossThreadCopierPassThrough<webrtc::DtlsTransportInformation> { STATIC_ONLY(CrossThreadCopier); @@ -104,31 +96,6 @@ }; template <> -struct CrossThreadCopier<blink::P2PQuicTransport::StartConfig> - : public CrossThreadCopierPassThrough< - blink::P2PQuicTransport::StartConfig> { - STATIC_ONLY(CrossThreadCopier); - using Type = blink::P2PQuicTransport::StartConfig; - static blink::P2PQuicTransport::StartConfig Copy( - blink::P2PQuicTransport::StartConfig config) { - // This is in fact a move. - return config; - } -}; - -template <> -struct CrossThreadCopier<blink::P2PQuicTransportStats> - : public CrossThreadCopierPassThrough<blink::P2PQuicTransportStats> { - STATIC_ONLY(CrossThreadCopier); -}; - -template <> -struct CrossThreadCopier<blink::P2PQuicNegotiatedParams> - : public CrossThreadCopierPassThrough<blink::P2PQuicNegotiatedParams> { - STATIC_ONLY(CrossThreadCopier); -}; - -template <> struct CrossThreadCopier<webrtc::RTCError> : public CrossThreadCopierPassThrough<webrtc::RTCError> { STATIC_ONLY(CrossThreadCopier);
diff --git a/third_party/blink/renderer/modules/peerconnection/idls.gni b/third_party/blink/renderer/modules/peerconnection/idls.gni index 2ddbb81..d6b0fb6 100644 --- a/third_party/blink/renderer/modules/peerconnection/idls.gni +++ b/third_party/blink/renderer/modules/peerconnection/idls.gni
@@ -19,9 +19,6 @@ "rtc_peer_connection.idl", "rtc_peer_connection_ice_error_event.idl", "rtc_peer_connection_ice_event.idl", - "rtc_quic_stream.idl", - "rtc_quic_stream_event.idl", - "rtc_quic_transport.idl", "rtc_rtp_receiver.idl", "rtc_rtp_sender.idl", "rtc_rtp_transceiver.idl", @@ -53,11 +50,6 @@ "rtc_offer_options.idl", "rtc_peer_connection_ice_error_event_init.idl", "rtc_peer_connection_ice_event_init.idl", - "rtc_quic_parameters.idl", - "rtc_quic_stream_event_init.idl", - "rtc_quic_stream_read_result.idl", - "rtc_quic_stream_write_parameters.idl", - "rtc_quic_transport_stats.idl", "rtc_rtcp_parameters.idl", "rtc_rtp_capabilities.idl", "rtc_rtp_codec_capability.idl",
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.cc b/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.cc index 984e4d1..497509c 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.cc
@@ -22,7 +22,6 @@ #include "third_party/blink/renderer/modules/peerconnection/rtc_ice_candidate.h" #include "third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h" #include "third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_ice_event.h" -#include "third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.h" #include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/scheduler/public/thread.h" @@ -188,34 +187,10 @@ DCHECK(!proxy_); } -bool RTCIceTransport::HasConsumer() const { - return consumer_; -} - bool RTCIceTransport::IsFromPeerConnection() const { return peer_connection_; } -IceTransportProxy* RTCIceTransport::ConnectConsumer( - RTCQuicTransport* consumer) { - DCHECK(consumer); - DCHECK(proxy_); - DCHECK(!peer_connection_); - if (!consumer_) { - consumer_ = consumer; - } else { - DCHECK_EQ(consumer_, consumer); - } - return proxy_.get(); -} - -void RTCIceTransport::DisconnectConsumer(RTCQuicTransport* consumer) { - DCHECK(consumer); - DCHECK(proxy_); - DCHECK_EQ(consumer, consumer_); - consumer_ = nullptr; -} - String RTCIceTransport::role() const { switch (role_) { case cricket::ICEROLE_CONTROLLING: @@ -435,9 +410,6 @@ *ConvertToCricketIceCandidate(*remote_candidate)); } proxy_->Start(remote_parameters, role, initial_remote_candidates); - if (consumer_) { - consumer_->OnIceTransportStarted(); - } } else { remote_candidates_.clear(); state_ = webrtc::IceTransportState::kNew; @@ -545,11 +517,6 @@ if (IsClosed()) { return; } - if (HasConsumer()) { - consumer_->OnIceTransportClosed(reason); - } - // Notifying the consumer that we're closing should cause it to disconnect. - DCHECK(!HasConsumer()); state_ = webrtc::IceTransportState::kClosed; selected_candidate_pair_ = nullptr; proxy_.reset(); @@ -590,7 +557,6 @@ visitor->Trace(local_parameters_); visitor->Trace(remote_parameters_); visitor->Trace(selected_candidate_pair_); - visitor->Trace(consumer_); visitor->Trace(peer_connection_); EventTargetWithInlineData::Trace(visitor); ExecutionContextLifecycleObserver::Trace(visitor);
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.h b/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.h index a8aa600..884b804 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.h +++ b/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.h
@@ -27,7 +27,6 @@ class RTCIceCandidate; class RTCIceGatherOptions; class IceTransportAdapterCrossThreadFactory; -class RTCQuicTransport; class RTCPeerConnection; // Blink bindings for the RTCIceTransport JavaScript object. @@ -92,14 +91,6 @@ // Returns true if the RTCIceTransport is in a terminal state. bool IsClosed() const { return state_ == webrtc::IceTransportState::kClosed; } - // An RTCQuicTransport can be connected to this RTCIceTransport. Only one can - // be connected at a time. The consumer will be automatically disconnected - // if stop() is called on this object. Otherwise, the RTCQuicTransport is - // responsible for disconnecting itself when it is done. - // ConnectConsumer returns an IceTransportProxy that can be used to connect - // a QuicTransportProxy. It may be called repeatedly with the same - // RTCQuicTransport. - bool HasConsumer() const; // If |this| was created from an RTCPeerConnection. // // Background: This is because we don't reuse an RTCIceTransport that has been @@ -115,8 +106,6 @@ // -Asynchronously connect to the P2PTransport - if the count of connected // transports to the P2PTransportChannel is > 1, then throw an exception. bool IsFromPeerConnection() const; - IceTransportProxy* ConnectConsumer(RTCQuicTransport* consumer); - void DisconnectConsumer(RTCQuicTransport* consumer); // rtc_ice_transport.idl String role() const; @@ -185,7 +174,6 @@ Member<RTCIceParameters> remote_parameters_; Member<RTCIceCandidatePair> selected_candidate_pair_; - Member<RTCQuicTransport> consumer_; const WeakMember<RTCPeerConnection> peer_connection_; // Handle to the WebRTC ICE transport. Created when this binding is
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport_test.cc b/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport_test.cc index f6f802c..8eb1ba9 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport_test.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport_test.cc
@@ -13,7 +13,6 @@ #include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_ice_candidate_init.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_ice_gather_options.h" #include "third_party/blink/renderer/modules/peerconnection/adapters/test/mock_ice_transport_adapter_cross_thread_factory.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/test/mock_p2p_quic_packet_transport.h" #include "third_party/blink/renderer/modules/peerconnection/rtc_ice_candidate.h" #include "third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_ice_event.h" #include "third_party/webrtc/pc/webrtc_sdp.h" @@ -108,9 +107,7 @@ RTCIceTransport* RTCIceTransportTest::CreateIceTransport( V8TestingScope& scope) { - return CreateIceTransport( - scope, std::make_unique<MockIceTransportAdapter>( - std::make_unique<MockP2PQuicPacketTransport>())); + return CreateIceTransport(scope, std::make_unique<MockIceTransportAdapter>()); } RTCIceTransport* RTCIceTransportTest::CreateIceTransport(
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_quic_parameters.idl b/third_party/blink/renderer/modules/peerconnection/rtc_quic_parameters.idl deleted file mode 100644 index 4fd90d7..0000000 --- a/third_party/blink/renderer/modules/peerconnection/rtc_quic_parameters.idl +++ /dev/null
@@ -1,16 +0,0 @@ -// Copyright 2018 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://w3c.github.io/webrtc-quic/#dom-rtcquicrole -enum RTCQuicRole { - "auto", - "client", - "server", -}; - -// https://w3c.github.io/webrtc-quic/#rtcquicparameters* -dictionary RTCQuicParameters { - RTCQuicRole role = "auto"; - sequence<RTCDtlsFingerprint> fingerprints; -};
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream.cc b/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream.cc deleted file mode 100644 index fda672d9..0000000 --- a/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream.cc +++ /dev/null
@@ -1,413 +0,0 @@ -// Copyright 2018 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/peerconnection/rtc_quic_stream.h" - -#include "base/containers/span.h" -#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" -#include "third_party/blink/renderer/core/dom/events/event.h" -#include "third_party/blink/renderer/platform/bindings/exception_state.h" - -namespace blink { - -// 6 MB allows a reasonable amount to buffer on the read and write side. -// TODO(https://crbug.com/874296): Consider exposing these configurations. -const uint32_t RTCQuicStream::kWriteBufferSize = 6 * 1024 * 1024; -const uint32_t RTCQuicStream::kReadBufferSize = 6 * 1024 * 1024; - -class RTCQuicStream::PendingReadBufferedAmountPromise - : public GarbageCollected<PendingReadBufferedAmountPromise> { - public: - PendingReadBufferedAmountPromise(ScriptPromiseResolver* promise_resolver, - uint32_t readable_amount) - : promise_resolver_(promise_resolver), - readable_amount_(readable_amount) {} - - ScriptPromiseResolver* promise_resolver() const { return promise_resolver_; } - uint32_t readable_amount() const { return readable_amount_; } - - void Trace(Visitor* visitor) const { visitor->Trace(promise_resolver_); } - - private: - Member<ScriptPromiseResolver> promise_resolver_; - uint32_t readable_amount_; -}; - -class RTCQuicStream::PendingWriteBufferedAmountPromise - : public GarbageCollected<PendingWriteBufferedAmountPromise> { - public: - PendingWriteBufferedAmountPromise(ScriptPromiseResolver* promise_resolver, - uint32_t threshold) - : promise_resolver_(promise_resolver), threshold_(threshold) {} - - ScriptPromiseResolver* promise_resolver() const { return promise_resolver_; } - uint32_t threshold() const { return threshold_; } - - void Trace(Visitor* visitor) const { visitor->Trace(promise_resolver_); } - - private: - Member<ScriptPromiseResolver> promise_resolver_; - uint32_t threshold_; -}; - -RTCQuicStream::RTCQuicStream(ExecutionContext* context, - RTCQuicTransport* transport, - QuicStreamProxy* stream_proxy) - : ExecutionContextClient(context), - transport_(transport), - proxy_(stream_proxy) { - DCHECK(transport_); - DCHECK(proxy_); -} - -RTCQuicStream::~RTCQuicStream() = default; - -RTCQuicTransport* RTCQuicStream::transport() const { - return transport_; -} - -String RTCQuicStream::state() const { - switch (state_) { - case RTCQuicStreamState::kNew: - return "new"; - case RTCQuicStreamState::kOpening: - return "opening"; - case RTCQuicStreamState::kOpen: - return "open"; - case RTCQuicStreamState::kClosing: - return "closing"; - case RTCQuicStreamState::kClosed: - return "closed"; - } - return String(); -} - -uint32_t RTCQuicStream::readBufferedAmount() const { - return receive_buffer_.size(); -} - -uint32_t RTCQuicStream::maxReadBufferedAmount() const { - return kReadBufferSize; -} - -uint32_t RTCQuicStream::writeBufferedAmount() const { - return write_buffered_amount_; -} - -uint32_t RTCQuicStream::maxWriteBufferedAmount() const { - return kWriteBufferSize; -} - -RTCQuicStreamReadResult* RTCQuicStream::readInto( - NotShared<DOMUint8Array> data, - ExceptionState& exception_state) { - if (RaiseIfNotReadable(exception_state)) { - return 0; - } - uint32_t read_amount = static_cast<uint32_t>(receive_buffer_.ReadInto( - base::make_span(data.View()->Data(), data.View()->lengthAsSizeT()))); - if (!received_fin_ && read_amount > 0) { - proxy_->MarkReceivedDataConsumed(read_amount); - } - if (receive_buffer_.empty() && received_fin_) { - read_fin_ = true; - if (wrote_fin_) { - DCHECK_EQ(state_, RTCQuicStreamState::kClosing); - Close(CloseReason::kReadWriteFinished); - } else { - DCHECK_EQ(state_, RTCQuicStreamState::kOpen); - state_ = RTCQuicStreamState::kClosing; - } - } - auto* result = RTCQuicStreamReadResult::Create(); - result->setAmount(read_amount); - result->setFinished(read_fin_); - return result; -} - -void RTCQuicStream::write(const RTCQuicStreamWriteParameters* data, - ExceptionState& exception_state) { - bool finish = data->finish(); - bool has_write_data = - data->hasData() && data->data().View()->lengthAsSizeT() > 0; - if (!has_write_data && !finish) { - exception_state.ThrowDOMException( - DOMExceptionCode::kNotSupportedError, - "Cannot write empty data, unless data.finish is set to true."); - return; - } - if (RaiseIfNotWritable(exception_state)) { - return; - } - Vector<uint8_t> data_vector; - if (has_write_data) { - DOMUint8Array* write_data = data->data().View(); - size_t remaining_write_buffer_size = - kWriteBufferSize - writeBufferedAmount(); - if (write_data->lengthAsSizeT() > remaining_write_buffer_size) { - exception_state.ThrowDOMException( - DOMExceptionCode::kOperationError, - "The write data size of " + - String::Number(write_data->lengthAsSizeT()) + - " bytes would exceed the remaining write buffer size of " + - String::Number(remaining_write_buffer_size) + " bytes."); - return; - } - data_vector.resize(static_cast<wtf_size_t>(write_data->lengthAsSizeT())); - memcpy(data_vector.data(), write_data->Data(), write_data->lengthAsSizeT()); - write_buffered_amount_ += - static_cast<uint32_t>(write_data->lengthAsSizeT()); - } - proxy_->WriteData(std::move(data_vector), finish); - if (finish) { - wrote_fin_ = true; - if (!read_fin_) { - DCHECK_EQ(state_, RTCQuicStreamState::kOpen); - state_ = RTCQuicStreamState::kClosing; - RejectPendingWaitForWriteBufferedAmountBelowPromises(); - } else { - DCHECK_EQ(state_, RTCQuicStreamState::kClosing); - Close(CloseReason::kReadWriteFinished); - } - } -} - -void RTCQuicStream::reset() { - if (IsClosed()) { - return; - } - Close(CloseReason::kLocalReset); -} - -ScriptPromise RTCQuicStream::waitForReadable(ScriptState* script_state, - uint32_t amount, - ExceptionState& exception_state) { - if (RaiseIfNotReadable(exception_state)) { - return ScriptPromise(); - } - if (amount > kReadBufferSize) { - exception_state.ThrowTypeError( - "The amount " + String::Number(amount) + - " is greater than the maximum read buffer size of " + - String::Number(kReadBufferSize) + "."); - return ScriptPromise(); - } - auto* promise_resolver = - MakeGarbageCollected<ScriptPromiseResolver>(script_state); - ScriptPromise promise = promise_resolver->Promise(); - if (received_fin_ || receive_buffer_.size() >= amount) { - promise_resolver->Resolve(); - } else { - pending_read_buffered_amount_promises_.push_back( - MakeGarbageCollected<PendingReadBufferedAmountPromise>(promise_resolver, - amount)); - } - return promise; -} - -ScriptPromise RTCQuicStream::waitForWriteBufferedAmountBelow( - ScriptState* script_state, - uint32_t threshold, - ExceptionState& exception_state) { - if (RaiseIfNotWritable(exception_state)) { - return ScriptPromise(); - } - auto* promise_resolver = - MakeGarbageCollected<ScriptPromiseResolver>(script_state); - ScriptPromise promise = promise_resolver->Promise(); - if (write_buffered_amount_ <= threshold) { - promise_resolver->Resolve(); - } else { - pending_write_buffered_amount_promises_.push_back( - MakeGarbageCollected<PendingWriteBufferedAmountPromise>( - promise_resolver, threshold)); - } - return promise; -} - -bool RTCQuicStream::RaiseIfNotReadable(ExceptionState& exception_state) { - if (read_fin_) { - exception_state.ThrowDOMException( - DOMExceptionCode::kInvalidStateError, - "The stream is not readable: The end of the stream has been read."); - return true; - } - if (IsClosed()) { - exception_state.ThrowDOMException( - DOMExceptionCode::kInvalidStateError, - "The stream is not readable: The stream is closed."); - return true; - } - return false; -} - -bool RTCQuicStream::RaiseIfNotWritable(ExceptionState& exception_state) { - if (wrote_fin_) { - exception_state.ThrowDOMException( - DOMExceptionCode::kInvalidStateError, - "The stream is not writable: finish() has been called."); - return true; - } - if (IsClosed()) { - exception_state.ThrowDOMException( - DOMExceptionCode::kInvalidStateError, - "The stream is not writable: The stream is closed."); - return true; - } - return false; -} - -void RTCQuicStream::RejectPendingWaitForReadablePromises() { - // TODO(https://github.com/w3c/webrtc-quic/issues/81): The promise resolve - // order is under specified. - for (PendingReadBufferedAmountPromise* pending_promise : - pending_read_buffered_amount_promises_) { - ScriptState::Scope scope( - pending_promise->promise_resolver()->GetScriptState()); - ExceptionState exception_state( - pending_promise->promise_resolver()->GetScriptState()->GetIsolate(), - ExceptionState::kExecutionContext, "RTCQuicStream", "waitForReadable"); - exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, - "The RTCQuicStream is not readable."); - pending_promise->promise_resolver()->Reject(exception_state); - } - pending_read_buffered_amount_promises_.clear(); -} - -void RTCQuicStream::RejectPendingWaitForWriteBufferedAmountBelowPromises() { - // TODO(https://github.com/w3c/webrtc-quic/issues/81): The promise resolve - // order is under specified. - for (PendingWriteBufferedAmountPromise* pending_promise : - pending_write_buffered_amount_promises_) { - ScriptState::Scope scope( - pending_promise->promise_resolver()->GetScriptState()); - ExceptionState exception_state( - pending_promise->promise_resolver()->GetScriptState()->GetIsolate(), - ExceptionState::kExecutionContext, "RTCQuicStream", - "waitForWriteBufferedAmountBelow"); - exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, - "The stream is no longer writable."); - pending_promise->promise_resolver()->Reject(exception_state); - } - pending_write_buffered_amount_promises_.clear(); -} - -void RTCQuicStream::OnRemoteReset() { - Close(CloseReason::kRemoteReset); -} - -void RTCQuicStream::OnDataReceived(Vector<uint8_t> data, bool fin) { - DCHECK(!received_fin_); - DCHECK_LE(data.size(), kReadBufferSize - receive_buffer_.size()); - received_fin_ = fin; - receive_buffer_.Append(std::move(data)); - // TODO(https://github.com/w3c/webrtc-quic/issues/81): The promise resolve - // order is under specified. - for (auto* it = pending_read_buffered_amount_promises_.begin(); - it != pending_read_buffered_amount_promises_.end(); - /* incremented manually */) { - PendingReadBufferedAmountPromise* pending_promise = *it; - if (received_fin_ || - receive_buffer_.size() >= pending_promise->readable_amount()) { - pending_promise->promise_resolver()->Resolve(); - it = pending_read_buffered_amount_promises_.erase(it); - } else { - ++it; - } - } -} - -void RTCQuicStream::OnWriteDataConsumed(uint32_t amount) { - DCHECK_GE(write_buffered_amount_, amount); - write_buffered_amount_ -= amount; - // TODO(https://github.com/w3c/webrtc-quic/issues/81): The promise resolve - // order is under specified. - for (auto* it = pending_write_buffered_amount_promises_.begin(); - it != pending_write_buffered_amount_promises_.end(); - /* incremented manually */) { - PendingWriteBufferedAmountPromise* pending_promise = *it; - if (write_buffered_amount_ <= pending_promise->threshold()) { - pending_promise->promise_resolver()->Resolve(); - it = pending_write_buffered_amount_promises_.erase(it); - } else { - ++it; - } - } -} - -void RTCQuicStream::OnQuicTransportClosed( - RTCQuicTransport::CloseReason reason) { - switch (reason) { - case RTCQuicTransport::CloseReason::kContextDestroyed: - Close(CloseReason::kContextDestroyed); - break; - default: - Close(CloseReason::kQuicTransportClosed); - break; - } -} - -void RTCQuicStream::Close(CloseReason reason) { - DCHECK_NE(state_, RTCQuicStreamState::kClosed); - - // Tear down the QuicStreamProxy. - // If the Close is caused by a remote event or regular use of WriteData, the - // QuicStreamProxy will have already been deleted. - // If the Close is caused by the transport then the transport is responsible - // for deleting the QuicStreamProxy. - if (reason == CloseReason::kLocalReset) { - // This deletes the QuicStreamProxy. - proxy_->Reset(); - } - proxy_ = nullptr; - - // Remove this stream from the RTCQuicTransport unless closing from a - // transport-level event. - switch (reason) { - case CloseReason::kReadWriteFinished: - case CloseReason::kLocalReset: - case CloseReason::kRemoteReset: - transport_->RemoveStream(this); - break; - case CloseReason::kQuicTransportClosed: - case CloseReason::kContextDestroyed: - // The RTCQuicTransport will handle clearing its list of streams. - break; - } - - // Clear observable state. - receive_buffer_.Clear(); - write_buffered_amount_ = 0; - - // It's illegal to resolve or reject promises when the ExecutionContext is - // being destroyed. - if (reason != CloseReason::kContextDestroyed) { - RejectPendingWaitForReadablePromises(); - RejectPendingWaitForWriteBufferedAmountBelowPromises(); - } - - // Change the state. Fire the statechange event only if the close is caused by - // a remote stream event. - state_ = RTCQuicStreamState::kClosed; - if (reason == CloseReason::kRemoteReset) { - DispatchEvent(*Event::Create(event_type_names::kStatechange)); - } -} - -const AtomicString& RTCQuicStream::InterfaceName() const { - return event_target_names::kRTCQuicStream; -} - -ExecutionContext* RTCQuicStream::GetExecutionContext() const { - return ExecutionContextClient::GetExecutionContext(); -} - -void RTCQuicStream::Trace(Visitor* visitor) const { - visitor->Trace(transport_); - visitor->Trace(pending_read_buffered_amount_promises_); - visitor->Trace(pending_write_buffered_amount_promises_); - EventTargetWithInlineData::Trace(visitor); - ExecutionContextClient::Trace(visitor); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream.h b/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream.h deleted file mode 100644 index eace0450..0000000 --- a/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream.h +++ /dev/null
@@ -1,141 +0,0 @@ -// Copyright 2018 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_PEERCONNECTION_RTC_QUIC_STREAM_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_RTC_QUIC_STREAM_H_ - -#include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_quic_stream_read_result.h" -#include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_quic_stream_write_parameters.h" -#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h" -#include "third_party/blink/renderer/core/typed_arrays/array_buffer_view_helpers.h" -#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h" -#include "third_party/blink/renderer/modules/event_target_modules.h" -#include "third_party/blink/renderer/modules/modules_export.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_proxy.h" -#include "third_party/blink/renderer/modules/peerconnection/byte_buffer_queue.h" -#include "third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.h" - -namespace blink { - -class ScriptPromise; - -enum class RTCQuicStreamState { kNew, kOpening, kOpen, kClosing, kClosed }; - -// The RTCQuicStream does not need to be ActiveScriptWrappable since the -// RTCQuicTransport that it is associated with holds a strong reference to it -// as long as it is not closed. -class MODULES_EXPORT RTCQuicStream final : public EventTargetWithInlineData, - public ExecutionContextClient, - public QuicStreamProxy::Delegate { - DEFINE_WRAPPERTYPEINFO(); - - public: - // TODO(steveanton): These maybe should be adjustable. - static const uint32_t kWriteBufferSize; - static const uint32_t kReadBufferSize; - - enum class CloseReason { - // Both read and write sides have been finished. - kReadWriteFinished, - // reset() was called. - kLocalReset, - // The remote stream sent a reset(). - kRemoteReset, - // The RTCQuicTransport has closed. - kQuicTransportClosed, - // The ExecutionContext is being destroyed. - kContextDestroyed, - }; - - RTCQuicStream(ExecutionContext* context, - RTCQuicTransport* transport, - QuicStreamProxy* stream_proxy); - ~RTCQuicStream() override; - - // Called by the RTCQuicTransport when it is being closed. - void OnQuicTransportClosed(RTCQuicTransport::CloseReason reason); - - // rtc_quic_stream.idl - RTCQuicTransport* transport() const; - String state() const; - uint32_t readBufferedAmount() const; - uint32_t maxReadBufferedAmount() const; - uint32_t writeBufferedAmount() const; - uint32_t maxWriteBufferedAmount() const; - RTCQuicStreamReadResult* readInto(NotShared<DOMUint8Array> data, - ExceptionState& exception_state); - void write(const RTCQuicStreamWriteParameters* data, - ExceptionState& exception_state); - void reset(); - ScriptPromise waitForWriteBufferedAmountBelow( - ScriptState* script_state, - uint32_t threshold, - ExceptionState& exception_state); - ScriptPromise waitForReadable(ScriptState* script_state, - uint32_t amount, - ExceptionState& exception_state); - DEFINE_ATTRIBUTE_EVENT_LISTENER(statechange, kStatechange) - - // EventTarget overrides. - const AtomicString& InterfaceName() const override; - ExecutionContext* GetExecutionContext() const override; - - // For garbage collection. - void Trace(Visitor* visitor) const override; - - private: - class PendingReadBufferedAmountPromise; - class PendingWriteBufferedAmountPromise; - - // QuicStreamProxy::Delegate overrides. - void OnRemoteReset() override; - void OnDataReceived(Vector<uint8_t> data, bool fin) override; - void OnWriteDataConsumed(uint32_t amount) override; - - bool RaiseIfNotReadable(ExceptionState&); - bool RaiseIfNotWritable(ExceptionState&); - - // Permenantly closes the RTCQuicStream with the given reason. - // The RTCQuicStream must not already be closed. - // This will transition the state to closed. - void Close(CloseReason reason); - - bool IsClosed() const { return state_ == RTCQuicStreamState::kClosed; } - - void RejectPendingWaitForReadablePromises(); - void RejectPendingWaitForWriteBufferedAmountBelowPromises(); - - Member<RTCQuicTransport> transport_; - RTCQuicStreamState state_ = RTCQuicStreamState::kOpen; - - // Data that has been received but not read. - // OnDataReceived() appends to the read buffer. - // readInto() will read out from the front of the buffer. - ByteBufferQueue receive_buffer_; - // True if the fin has been received from the network. - bool received_fin_ = false; - // True if the fin has been read out via readInto(). This signifies that the - // RTCQuicStream is closed for reading. - bool read_fin_ = false; - // Pending waitForReadable promises. - HeapVector<Member<PendingReadBufferedAmountPromise>> - pending_read_buffered_amount_promises_; - - // Amount of bytes written but may not yet have been sent by the underlying - // P2PQuicStream. - // write() increases this number. - // OnDataSent() decreases this number. - uint32_t write_buffered_amount_ = 0; - // True if finish() has been called. - bool wrote_fin_ = false; - // Pending waitForWriteBufferedAmountBelow Promises. - HeapVector<Member<PendingWriteBufferedAmountPromise>> - pending_write_buffered_amount_promises_; - - QuicStreamProxy* proxy_; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_RTC_QUIC_STREAM_H_
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream.idl b/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream.idl deleted file mode 100644 index 8e793d4..0000000 --- a/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream.idl +++ /dev/null
@@ -1,36 +0,0 @@ -// Copyright 2018 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://w3c.github.io/webrtc-quic/#rtcquicstreamstate* -enum RTCQuicStreamState { - "new", - "opening", - "open", - "closing", - "closed", -}; - -// https://w3c.github.io/webrtc-quic/#quicstream* -[ - Exposed=Window, - RuntimeEnabled=RTCQuicTransport, - SecureContext -] interface RTCQuicStream : EventTarget { - [Measure] readonly attribute RTCQuicTransport transport; - [Measure] readonly attribute RTCQuicStreamState state; - [Measure] readonly attribute unsigned long readBufferedAmount; - [Measure] readonly attribute unsigned long maxReadBufferedAmount; - [Measure] readonly attribute unsigned long writeBufferedAmount; - [Measure] readonly attribute unsigned long maxWriteBufferedAmount; - [Measure, RaisesException] RTCQuicStreamReadResult readInto(Uint8Array data); - [Measure, RaisesException] void write(RTCQuicStreamWriteParameters data); - [Measure] void reset(); - [CallWith=ScriptState, Measure, RaisesException] - Promise<void> waitForWriteBufferedAmountBelow(unsigned long amount); - [CallWith=ScriptState, Measure, RaisesException] - Promise<void> waitForReadable(unsigned long amount); - attribute EventHandler onstatechange; - // TODO(crbug.com/868068): Implement remaining methods, attributes, and events. -}; -
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_event.cc b/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_event.cc deleted file mode 100644 index 7f61f19..0000000 --- a/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_event.cc +++ /dev/null
@@ -1,45 +0,0 @@ -// Copyright 2018 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/peerconnection/rtc_quic_stream_event.h" -#include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_quic_stream_event_init.h" -#include "third_party/blink/renderer/modules/peerconnection/rtc_quic_stream.h" - -namespace blink { - -RTCQuicStreamEvent* RTCQuicStreamEvent::Create(RTCQuicStream* stream) { - return MakeGarbageCollected<RTCQuicStreamEvent>(stream); -} - -RTCQuicStreamEvent* RTCQuicStreamEvent::Create( - const AtomicString& type, - const RTCQuicStreamEventInit* initializer) { - return MakeGarbageCollected<RTCQuicStreamEvent>(type, initializer); -} - -RTCQuicStreamEvent::RTCQuicStreamEvent(RTCQuicStream* stream) - : Event(event_type_names::kQuicstream, Bubbles::kNo, Cancelable::kNo), - stream_(stream) {} - -RTCQuicStreamEvent::RTCQuicStreamEvent( - const AtomicString& type, - const RTCQuicStreamEventInit* initializer) - : Event(type, initializer), stream_(initializer->stream()) {} - -RTCQuicStreamEvent::~RTCQuicStreamEvent() = default; - -RTCQuicStream* RTCQuicStreamEvent::stream() const { - return stream_.Get(); -} - -const AtomicString& RTCQuicStreamEvent::InterfaceName() const { - return event_interface_names::kRTCQuicStreamEvent; -} - -void RTCQuicStreamEvent::Trace(Visitor* visitor) const { - visitor->Trace(stream_); - Event::Trace(visitor); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_event.h b/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_event.h deleted file mode 100644 index faeb397b..0000000 --- a/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_event.h +++ /dev/null
@@ -1,43 +0,0 @@ -// Copyright 2018 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_PEERCONNECTION_RTC_QUIC_STREAM_EVENT_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_RTC_QUIC_STREAM_EVENT_H_ - -#include "third_party/blink/renderer/modules/event_modules.h" - -namespace blink { - -class RTCQuicStream; -class RTCQuicStreamEventInit; - -class MODULES_EXPORT RTCQuicStreamEvent final : public Event { - DEFINE_WRAPPERTYPEINFO(); - - public: - static RTCQuicStreamEvent* Create(RTCQuicStream* stream); - static RTCQuicStreamEvent* Create(const AtomicString& type, - const RTCQuicStreamEventInit* init); - - RTCQuicStreamEvent(RTCQuicStream* stream); - RTCQuicStreamEvent(const AtomicString& type, - const RTCQuicStreamEventInit* init); - ~RTCQuicStreamEvent() override; - - // rtc_quic_stream_event.idl - RTCQuicStream* stream() const; - - // Event overrides. - const AtomicString& InterfaceName() const override; - - // For garbage collection. - void Trace(Visitor*) const override; - - private: - Member<RTCQuicStream> stream_; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_RTC_QUIC_STREAM_EVENT_H_
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_event.idl b/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_event.idl deleted file mode 100644 index 3facdd0..0000000 --- a/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_event.idl +++ /dev/null
@@ -1,12 +0,0 @@ -// Copyright 2018 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://w3c.github.io/webrtc-quic/#rtcquicstreamevent -[ - RuntimeEnabled=RTCQuicTransport, - Exposed=Window -] interface RTCQuicStreamEvent : Event { - constructor(DOMString type, optional RTCQuicStreamEventInit eventInitDict = {}); - readonly attribute RTCQuicStream stream; -};
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_event_init.idl b/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_event_init.idl deleted file mode 100644 index 53e3bcd..0000000 --- a/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_event_init.idl +++ /dev/null
@@ -1,8 +0,0 @@ -// Copyright 2018 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://w3c.github.io/webrtc-quic/#dom-rtcquicstreameventinit -dictionary RTCQuicStreamEventInit : EventInit { - RTCQuicStream stream; -};
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_read_result.idl b/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_read_result.idl deleted file mode 100644 index b2d58c2..0000000 --- a/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_read_result.idl +++ /dev/null
@@ -1,9 +0,0 @@ -// Copyright 2018 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://w3c.github.io/webrtc-quic/#dom-rtcquicstreamreadresult -dictionary RTCQuicStreamReadResult { - unsigned long amount; - boolean finished; -};
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_test.cc b/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_test.cc deleted file mode 100644 index 3d717b7..0000000 --- a/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_test.cc +++ /dev/null
@@ -1,1228 +0,0 @@ -// Copyright 2018 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. - -// This file tests the RTCQuicStream Blink bindings, QuicStreamProxy and -// QuicStreamHost by mocking out the underlying P2PQuicTransport. -// Everything is run on a single thread but with separate TestSimpleTaskRunners -// for the main thread / worker thread. - -#include "third_party/blink/renderer/modules/peerconnection/rtc_quic_stream.h" -#include "third_party/blink/renderer/bindings/core/v8/script_promise.h" -#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/test/mock_p2p_quic_stream.h" -#include "third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_event.h" -#include "third_party/blink/renderer/modules/peerconnection/rtc_quic_transport_test.h" - -namespace blink { -namespace { - -using testing::_; -using testing::ElementsAre; -using testing::InvokeWithoutArgs; -using testing::Return; -using testing::SaveArg; - -RTCQuicStreamWriteParameters* CreateWriteParametersWithData( - const Vector<uint8_t>& data) { - RTCQuicStreamWriteParameters* write_parameters = - RTCQuicStreamWriteParameters::Create(); - write_parameters->setData(NotShared<DOMUint8Array>( - DOMUint8Array::Create(data.data(), data.size()))); - write_parameters->setFinish(false); - return write_parameters; -} - -RTCQuicStreamWriteParameters* CreateWriteParametersWithDataOfLength( - uint32_t length, - bool finish = false) { - RTCQuicStreamWriteParameters* write_parameters = - RTCQuicStreamWriteParameters::Create(); - write_parameters->setData( - NotShared<DOMUint8Array>(DOMUint8Array::Create(length))); - write_parameters->setFinish(finish); - return write_parameters; -} - -RTCQuicStreamWriteParameters* CreateWriteParametersWithoutData(bool finish) { - RTCQuicStreamWriteParameters* write_parameters = - RTCQuicStreamWriteParameters::Create(); - write_parameters->setFinish(finish); - return write_parameters; -} - -} // namespace - -class RTCQuicStreamTest : public RTCQuicTransportTest { - public: - RTCQuicStream* CreateQuicStream(V8TestingScope& scope, - MockP2PQuicStream* mock_stream) { - auto p2p_quic_transport = std::make_unique<MockP2PQuicTransport>(); - EXPECT_CALL(*p2p_quic_transport, CreateStream()) - .WillOnce(Return(mock_stream)); - Persistent<RTCQuicTransport> quic_transport = - CreateConnectedQuicTransport(scope, std::move(p2p_quic_transport)); - return quic_transport->createStream(ASSERT_NO_EXCEPTION); - } -}; - -// Test that RTCQuicTransport.createStream causes CreateStream to be called on -// the underlying transport and a P2PQuicStream::Delegate to be set on the -// underlying P2PQuicStream. -TEST_F(RTCQuicStreamTest, RTCQuicTransportCreateStreamCallsUnderlying) { - V8TestingScope scope; - - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(); - EXPECT_CALL(*p2p_quic_stream, SetDelegate(_)) - .WillOnce(testing::Invoke( - [](P2PQuicStream::Delegate* delegate) { EXPECT_TRUE(delegate); })); - - auto p2p_quic_transport = std::make_unique<MockP2PQuicTransport>(); - EXPECT_CALL(*p2p_quic_transport, CreateStream()) - .WillOnce(Return(p2p_quic_stream.get())); - - Persistent<RTCQuicTransport> quic_transport = - CreateConnectedQuicTransport(scope, std::move(p2p_quic_transport)); - Persistent<RTCQuicStream> quic_stream = - quic_transport->createStream(ASSERT_NO_EXCEPTION); - - RunUntilIdle(); -} - -// Test that calling OnStream on the P2PQuicTransport delegate causes a -// quicstream event to fire with a new RTCQuicStream. -TEST_F(RTCQuicStreamTest, NewRemoteStreamFiresEvent) { - V8TestingScope scope; - - P2PQuicTransport::Delegate* transport_delegate = nullptr; - Persistent<RTCQuicTransport> quic_transport = - CreateConnectedQuicTransport(scope, &transport_delegate); - - Persistent<MockEventListener> quic_stream_listener = - CreateMockEventListener(); - EXPECT_CALL(*quic_stream_listener, Invoke(_, _)) - .WillOnce(testing::Invoke([](ExecutionContext*, Event* event) { - auto* stream_event = static_cast<RTCQuicStreamEvent*>(event); - EXPECT_NE(nullptr, stream_event->stream()); - })); - quic_transport->addEventListener(event_type_names::kQuicstream, - quic_stream_listener); - - ASSERT_TRUE(transport_delegate); - - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(); - EXPECT_CALL(*p2p_quic_stream, SetDelegate(_)) - .WillOnce(testing::Invoke( - [](P2PQuicStream::Delegate* delegate) { EXPECT_TRUE(delegate); })); - transport_delegate->OnStream(p2p_quic_stream.get()); - - RunUntilIdle(); -} - -// Test that calling reset() calls Reset() on the underlying P2PQuicStream. -TEST_F(RTCQuicStreamTest, ResetCallsUnderlying) { - V8TestingScope scope; - - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(); - EXPECT_CALL(*p2p_quic_stream, Reset()).Times(1); - - auto p2p_quic_transport = std::make_unique<MockP2PQuicTransport>(); - EXPECT_CALL(*p2p_quic_transport, CreateStream()) - .WillOnce(Return(p2p_quic_stream.get())); - - Persistent<RTCQuicTransport> quic_transport = - CreateConnectedQuicTransport(scope, std::move(p2p_quic_transport)); - Persistent<RTCQuicStream> stream = - quic_transport->createStream(ASSERT_NO_EXCEPTION); - - stream->reset(); - - RunUntilIdle(); -} - -// Test that calling OnRemoteReset() on the P2PQuicStream delegate fires a -// statechange event to 'closed'. -TEST_F(RTCQuicStreamTest, OnRemoteResetFiresStateChangeToClosed) { - V8TestingScope scope; - - P2PQuicStream::Delegate* stream_delegate = nullptr; - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(); - EXPECT_CALL(*p2p_quic_stream, SetDelegate(_)) - .WillOnce(SaveArg<0>(&stream_delegate)); - - auto p2p_quic_transport = std::make_unique<MockP2PQuicTransport>(); - EXPECT_CALL(*p2p_quic_transport, CreateStream()) - .WillOnce(Return(p2p_quic_stream.get())); - - Persistent<RTCQuicTransport> quic_transport = - CreateConnectedQuicTransport(scope, std::move(p2p_quic_transport)); - Persistent<RTCQuicStream> quic_stream = - quic_transport->createStream(ASSERT_NO_EXCEPTION); - - Persistent<MockEventListener> state_change_listener = - CreateMockEventListener(); - EXPECT_CALL(*state_change_listener, Invoke(_, _)) - .WillOnce(InvokeWithoutArgs( - [quic_stream]() { EXPECT_EQ("closed", quic_stream->state()); })); - quic_stream->addEventListener(event_type_names::kStatechange, - state_change_listener); - - RunUntilIdle(); - - ASSERT_TRUE(stream_delegate); - EXPECT_CALL(*p2p_quic_stream.get(), SetDelegate(nullptr)); - - stream_delegate->OnRemoteReset(); - - RunUntilIdle(); -} - -// Test that a pending OnRemoteReset() is ignored if reset() is called first. -TEST_F(RTCQuicStreamTest, PendingOnRemoteResetIgnoredAfterReset) { - V8TestingScope scope; - - P2PQuicStream::Delegate* stream_delegate = nullptr; - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(); - EXPECT_CALL(*p2p_quic_stream, SetDelegate(_)) - .WillOnce(SaveArg<0>(&stream_delegate)); - - auto p2p_quic_transport = std::make_unique<MockP2PQuicTransport>(); - EXPECT_CALL(*p2p_quic_transport, CreateStream()) - .WillOnce(Return(p2p_quic_stream.get())); - - Persistent<RTCQuicTransport> quic_transport = - CreateConnectedQuicTransport(scope, std::move(p2p_quic_transport)); - Persistent<RTCQuicStream> quic_stream = - quic_transport->createStream(ASSERT_NO_EXCEPTION); - - // Expect no statechange event since reset() will already transition the state - // to 'closed'. - Persistent<MockEventListener> state_change_listener = - CreateMockEventListener(); - EXPECT_CALL(*state_change_listener, Invoke(_, _)).Times(0); - quic_stream->addEventListener(event_type_names::kStatechange, - state_change_listener); - - RunUntilIdle(); - - ASSERT_TRUE(stream_delegate); - EXPECT_CALL(*p2p_quic_stream.get(), SetDelegate(nullptr)); - - stream_delegate->OnRemoteReset(); - quic_stream->reset(); - EXPECT_EQ("closed", quic_stream->state()); - - RunUntilIdle(); - - EXPECT_EQ("closed", quic_stream->state()); -} - -// The following group tests write(), writeBufferedAmount(), and -// maxWriteBufferdAmount(). - -// Test that write() adds to writeBufferedAmount(). -TEST_F(RTCQuicStreamTest, WriteAddsToWriteBufferedAmount) { - V8TestingScope scope; - - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(); - Persistent<RTCQuicStream> stream = - CreateQuicStream(scope, p2p_quic_stream.get()); - - stream->write(CreateWriteParametersWithData({1, 2}), ASSERT_NO_EXCEPTION); - EXPECT_EQ(2u, stream->writeBufferedAmount()); - - stream->write(CreateWriteParametersWithData({3, 4, 5}), ASSERT_NO_EXCEPTION); - EXPECT_EQ(5u, stream->writeBufferedAmount()); - - RunUntilIdle(); -} - -// Test that write() calls WriteData() on the underlying P2PQuicStream. -TEST_F(RTCQuicStreamTest, WriteCallsWriteData) { - V8TestingScope scope; - - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(); - EXPECT_CALL(*p2p_quic_stream, WriteData(_, _)) - .WillOnce(testing::Invoke([](Vector<uint8_t> data, bool fin) { - EXPECT_THAT(data, ElementsAre(1, 2, 3, 4)); - EXPECT_FALSE(fin); - })); - - Persistent<RTCQuicStream> stream = - CreateQuicStream(scope, p2p_quic_stream.get()); - stream->write(CreateWriteParametersWithData({1, 2, 3, 4}), - ASSERT_NO_EXCEPTION); - - RunUntilIdle(); -} - -// Test that write() with no data throws a NotSupportedError and does not post a -// WriteData() to the underlying P2PQuicStream. -TEST_F(RTCQuicStreamTest, WriteWithoutDataThrowsNotSupportedError) { - V8TestingScope scope; - - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(); - EXPECT_CALL(*p2p_quic_stream, WriteData(_, _)).Times(0); - - Persistent<RTCQuicStream> stream = - CreateQuicStream(scope, p2p_quic_stream.get()); - stream->write(CreateWriteParametersWithoutData(/*finish=*/false), - scope.GetExceptionState()); - EXPECT_EQ(DOMExceptionCode::kNotSupportedError, - scope.GetExceptionState().CodeAs<DOMExceptionCode>()); - - RunUntilIdle(); -} - -// Test that writing a finish without data calls WriteData() on the underlying -// P2PQuicStream. -TEST_F(RTCQuicStreamTest, WriteFinishWithoutDataCallsWriteData) { - V8TestingScope scope; - - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(); - EXPECT_CALL(*p2p_quic_stream, WriteData(_, _)) - .WillOnce(testing::Invoke([](Vector<uint8_t> data, bool fin) { - EXPECT_THAT(data, ElementsAre()); - EXPECT_TRUE(fin); - })); - - Persistent<RTCQuicStream> stream = - CreateQuicStream(scope, p2p_quic_stream.get()); - stream->write(CreateWriteParametersWithoutData(/*finish=*/true), - ASSERT_NO_EXCEPTION); - - RunUntilIdle(); -} - -// Test that writeBufferedAmount is decreased when receiving OnWriteDataConsumed -// from the underlying P2PQuicStream. -TEST_F(RTCQuicStreamTest, OnWriteDataConsumedSubtractsFromWriteBufferedAmount) { - V8TestingScope scope; - - P2PQuicStream::Delegate* stream_delegate = nullptr; - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(&stream_delegate); - - Persistent<RTCQuicStream> stream = - CreateQuicStream(scope, p2p_quic_stream.get()); - stream->write(CreateWriteParametersWithDataOfLength(4), ASSERT_NO_EXCEPTION); - - RunUntilIdle(); - - ASSERT_TRUE(stream_delegate); - stream_delegate->OnWriteDataConsumed(4); - - RunUntilIdle(); - - EXPECT_EQ(0u, stream->writeBufferedAmount()); -} - -// Test that writeBufferedAmount is set to 0 if the stream was reset by the -// remote peer. -TEST_F(RTCQuicStreamTest, OnRemoteResetSetsWriteBufferedAmountToZero) { - V8TestingScope scope; - - P2PQuicStream::Delegate* stream_delegate = nullptr; - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(&stream_delegate); - - Persistent<RTCQuicStream> stream = - CreateQuicStream(scope, p2p_quic_stream.get()); - stream->write(CreateWriteParametersWithDataOfLength(4), ASSERT_NO_EXCEPTION); - - RunUntilIdle(); - - ASSERT_TRUE(stream_delegate); - EXPECT_CALL(*p2p_quic_stream.get(), SetDelegate(nullptr)); - - stream_delegate->OnRemoteReset(); - - RunUntilIdle(); - - EXPECT_EQ(0u, stream->writeBufferedAmount()); - - RunUntilIdle(); -} - -// Test that writeBufferedAmount is set to 0 if the stream calls write() with -// a finish, followed by receiving a finish from the remote side, and reading -// it out. -// -// TODO(https://crbug.com/874296): It doesn't really make sense the write buffer -// gets cleared in this case. Consider changing this. -TEST_F(RTCQuicStreamTest, - FinishThenReceiveFinishSetsWriteBufferedAmountToZero) { - V8TestingScope scope; - - P2PQuicStream::Delegate* stream_delegate = nullptr; - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(&stream_delegate); - - Persistent<RTCQuicStream> stream = - CreateQuicStream(scope, p2p_quic_stream.get()); - stream->write(CreateWriteParametersWithDataOfLength(4, /*finish=*/true), - ASSERT_NO_EXCEPTION); - - RunUntilIdle(); - - ASSERT_TRUE(stream_delegate); - EXPECT_CALL(*p2p_quic_stream.get(), SetDelegate(nullptr)); - - stream_delegate->OnDataReceived({}, /*fin=*/true); - - RunUntilIdle(); - - EXPECT_EQ(4u, stream->writeBufferedAmount()); - NotShared<DOMUint8Array> read_buffer(DOMUint8Array::Create(10)); - EXPECT_TRUE(stream->readInto(read_buffer, ASSERT_NO_EXCEPTION)->finished()); - EXPECT_EQ(0u, stream->writeBufferedAmount()); - - RunUntilIdle(); -} - -// Test that write throws an InvalidStateError if the stream was reset by the -// remote peer. -TEST_F(RTCQuicStreamTest, WriteThrowsIfRemoteReset) { - V8TestingScope scope; - - P2PQuicStream::Delegate* stream_delegate = nullptr; - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(&stream_delegate); - - Persistent<RTCQuicStream> stream = - CreateQuicStream(scope, p2p_quic_stream.get()); - - RunUntilIdle(); - - ASSERT_TRUE(stream_delegate); - EXPECT_CALL(*p2p_quic_stream.get(), SetDelegate(nullptr)); - - stream_delegate->OnRemoteReset(); - - RunUntilIdle(); - - stream->write(CreateWriteParametersWithDataOfLength(1), - scope.GetExceptionState()); - EXPECT_EQ(DOMExceptionCode::kInvalidStateError, - scope.GetExceptionState().CodeAs<DOMExceptionCode>()); - - RunUntilIdle(); -} - -// The following group tests waitForWriteBufferedAmountBelow(). - -// Test that a waitForWriteBufferedAmountBelow() promise resolves once -// OnWriteDataConsumed() frees up enough write buffer space. -TEST_F(RTCQuicStreamTest, WaitForWriteBufferedAmountBelowResolves) { - V8TestingScope scope; - - P2PQuicStream::Delegate* stream_delegate = nullptr; - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(&stream_delegate); - - Persistent<RTCQuicStream> stream = - CreateQuicStream(scope, p2p_quic_stream.get()); - - stream->write( - CreateWriteParametersWithDataOfLength(stream->maxWriteBufferedAmount()), - ASSERT_NO_EXCEPTION); - - ScriptPromise promise = stream->waitForWriteBufferedAmountBelow( - scope.GetScriptState(), stream->maxWriteBufferedAmount() - 1, - ASSERT_NO_EXCEPTION); - EXPECT_EQ(v8::Promise::kPending, - promise.V8Value().As<v8::Promise>()->State()); - - RunUntilIdle(); - - ASSERT_TRUE(stream_delegate); - stream_delegate->OnWriteDataConsumed(1); - - RunUntilIdle(); - - EXPECT_EQ(v8::Promise::kFulfilled, - promise.V8Value().As<v8::Promise>()->State()); -} - -// Test that a waitForWriteBufferedAmount() promise does not resolve until -// OnWriteDataConsumed() frees up exactly the threshold amount. -TEST_F(RTCQuicStreamTest, - WaitForWriteBufferedAmountBelowDoesNotResolveUntilExceedsThreshold) { - V8TestingScope scope; - - P2PQuicStream::Delegate* stream_delegate = nullptr; - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(&stream_delegate); - - Persistent<RTCQuicStream> stream = - CreateQuicStream(scope, p2p_quic_stream.get()); - stream->write( - CreateWriteParametersWithDataOfLength(stream->maxWriteBufferedAmount()), - ASSERT_NO_EXCEPTION); - - ScriptPromise promise = stream->waitForWriteBufferedAmountBelow( - scope.GetScriptState(), stream->maxWriteBufferedAmount() - 10, - ASSERT_NO_EXCEPTION); - EXPECT_EQ(v8::Promise::kPending, - promise.V8Value().As<v8::Promise>()->State()); - - RunUntilIdle(); - - // Post OnWriteDataConsumed(9) -- this should not resolve the promise since - // we're waiting for 10 bytes to be available. - ASSERT_TRUE(stream_delegate); - stream_delegate->OnWriteDataConsumed(9); - - RunUntilIdle(); - - EXPECT_EQ(v8::Promise::kPending, - promise.V8Value().As<v8::Promise>()->State()); - - // Post OnWriteDataConsumed(1) -- this should resolve the promise since now we - // have 9 + 1 = 10 bytes available. - stream_delegate->OnWriteDataConsumed(1); - - RunUntilIdle(); - - EXPECT_EQ(v8::Promise::kFulfilled, - promise.V8Value().As<v8::Promise>()->State()); -} - -// Test that if two waitForWriteBufferedAmount() promises are waiting on -// different thresholds, OnWriteDataConsumed() which satisfies the first -// threshold but not the second will only resolve the first promise. Once -// OnWriteDataConsumed() is received again past the second threshold then the -// second promise will be resolved. -TEST_F(RTCQuicStreamTest, - TwoWaitForWriteBufferedAmountBelowPromisesResolveInSequence) { - V8TestingScope scope; - - P2PQuicStream::Delegate* stream_delegate = nullptr; - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(&stream_delegate); - - Persistent<RTCQuicStream> stream = - CreateQuicStream(scope, p2p_quic_stream.get()); - stream->write( - CreateWriteParametersWithDataOfLength(stream->maxWriteBufferedAmount()), - ASSERT_NO_EXCEPTION); - - ScriptPromise promise_10 = stream->waitForWriteBufferedAmountBelow( - scope.GetScriptState(), stream->maxWriteBufferedAmount() - 10, - ASSERT_NO_EXCEPTION); - ScriptPromise promise_90 = stream->waitForWriteBufferedAmountBelow( - scope.GetScriptState(), stream->maxWriteBufferedAmount() - 90, - ASSERT_NO_EXCEPTION); - - RunUntilIdle(); - - ASSERT_TRUE(stream_delegate); - stream_delegate->OnWriteDataConsumed(10); - - RunUntilIdle(); - - EXPECT_EQ(v8::Promise::kFulfilled, - promise_10.V8Value().As<v8::Promise>()->State()); - EXPECT_EQ(v8::Promise::kPending, - promise_90.V8Value().As<v8::Promise>()->State()); - - stream_delegate->OnWriteDataConsumed(80); - - RunUntilIdle(); - - EXPECT_EQ(v8::Promise::kFulfilled, - promise_90.V8Value().As<v8::Promise>()->State()); -} - -// Test that if two waitForWriteBufferedAmount() promises are waiting on -// different thresholds and a single OnWriteDataConsumed() is received such that -// the buffered amount is below both thresholds then both promises are resolved. -TEST_F(RTCQuicStreamTest, - TwoWaitForWriteBufferedAmountBelowPromisesResolveTogether) { - V8TestingScope scope; - - P2PQuicStream::Delegate* stream_delegate = nullptr; - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(&stream_delegate); - - Persistent<RTCQuicStream> stream = - CreateQuicStream(scope, p2p_quic_stream.get()); - stream->write( - CreateWriteParametersWithDataOfLength(stream->maxWriteBufferedAmount()), - ASSERT_NO_EXCEPTION); - - ScriptPromise promise_10 = stream->waitForWriteBufferedAmountBelow( - scope.GetScriptState(), stream->maxWriteBufferedAmount() - 10, - ASSERT_NO_EXCEPTION); - ScriptPromise promise_90 = stream->waitForWriteBufferedAmountBelow( - scope.GetScriptState(), stream->maxWriteBufferedAmount() - 90, - ASSERT_NO_EXCEPTION); - - RunUntilIdle(); - - ASSERT_TRUE(stream_delegate); - stream_delegate->OnWriteDataConsumed(90); - - RunUntilIdle(); - - EXPECT_EQ(v8::Promise::kFulfilled, - promise_10.V8Value().As<v8::Promise>()->State()); - EXPECT_EQ(v8::Promise::kFulfilled, - promise_90.V8Value().As<v8::Promise>()->State()); -} - -// Test that when receiving OnRemoteReset() the waitForWriteBufferedAmountBelow -// Promise will be rejected. -TEST_F(RTCQuicStreamTest, - WaitForWriteBufferedAmountBelowPromisesRejectedOnRemoteReset) { - V8TestingScope scope; - - P2PQuicStream::Delegate* stream_delegate = nullptr; - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(&stream_delegate); - - Persistent<RTCQuicStream> stream = - CreateQuicStream(scope, p2p_quic_stream.get()); - stream->write( - CreateWriteParametersWithDataOfLength(stream->maxWriteBufferedAmount()), - ASSERT_NO_EXCEPTION); - - ScriptPromise promise = stream->waitForWriteBufferedAmountBelow( - scope.GetScriptState(), 0, ASSERT_NO_EXCEPTION); - - RunUntilIdle(); - - ASSERT_TRUE(stream_delegate); - EXPECT_CALL(*p2p_quic_stream.get(), SetDelegate(nullptr)); - - stream_delegate->OnRemoteReset(); - - RunUntilIdle(); - - EXPECT_EQ(v8::Promise::kRejected, - promise.V8Value().As<v8::Promise>()->State()); -} - -// Test that there is no crash when the ExecutionContext is being destroyed and -// there are pending waitForWriteBufferedAmountBelow() promises. If the -// RTCQuicStream attempts to resolve the promise in ContextDestroyed, it will -// likely crash since the v8::Isolate is being torn down. -TEST_F( - RTCQuicStreamTest, - NoCrashIfPendingWaitForWriteBufferedAmountBelowPromisesOnContextDestroyed) { - V8TestingScope scope; - - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(); - - Persistent<RTCQuicStream> stream = - CreateQuicStream(scope, p2p_quic_stream.get()); - stream->write( - CreateWriteParametersWithDataOfLength(stream->maxWriteBufferedAmount()), - ASSERT_NO_EXCEPTION); - - stream->waitForWriteBufferedAmountBelow(scope.GetScriptState(), 0, - ASSERT_NO_EXCEPTION); - - RunUntilIdle(); -} - -// The following group tests readInto(), readBufferedAmount(), and -// maxReadBufferedAmount(). - -static base::span<const uint8_t> GetSpan(NotShared<DOMUint8Array> data) { - return base::make_span(data.View()->Data(), data.View()->lengthAsSizeT()); -} - -// Test that readInto() with an empty data buffer succeeds but does not post -// MarkReceivedDataConsumed() to the underlying P2PQuicStream. -TEST_F(RTCQuicStreamTest, ReadIntoEmptyDoesNotPostMarkReceivedDataConsumed) { - V8TestingScope scope; - - P2PQuicStream::Delegate* stream_delegate = nullptr; - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(&stream_delegate); - EXPECT_CALL(*p2p_quic_stream, MarkReceivedDataConsumed(_)).Times(0); - - Persistent<RTCQuicStream> stream = - CreateQuicStream(scope, p2p_quic_stream.get()); - - EXPECT_EQ(0u, stream->readBufferedAmount()); - - NotShared<DOMUint8Array> read_buffer(DOMUint8Array::Create(0)); - RTCQuicStreamReadResult* result = - stream->readInto(read_buffer, ASSERT_NO_EXCEPTION); - EXPECT_EQ(0u, result->amount()); - EXPECT_FALSE(result->finished()); - EXPECT_EQ(0u, stream->readBufferedAmount()); - - RunUntilIdle(); -} - -// Test that data delived via OnDataReceived() increases readBufferedAmount. -TEST_F(RTCQuicStreamTest, OnDataReceivedIncreasesReadBufferedAmount) { - V8TestingScope scope; - - P2PQuicStream::Delegate* stream_delegate = nullptr; - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(&stream_delegate); - - Persistent<RTCQuicStream> stream = - CreateQuicStream(scope, p2p_quic_stream.get()); - - RunUntilIdle(); - - ASSERT_TRUE(stream_delegate); - stream_delegate->OnDataReceived({1, 2, 3}, /*fin=*/false); - - RunUntilIdle(); - - EXPECT_EQ(3u, stream->readBufferedAmount()); -} - -// Test that readInto() reads out data received from OnDataReceived() and -// decreases readBufferedAmount. -TEST_F(RTCQuicStreamTest, ReadIntoReadsDataFromOnDataReceived) { - V8TestingScope scope; - - P2PQuicStream::Delegate* stream_delegate = nullptr; - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(&stream_delegate); - - Persistent<RTCQuicStream> stream = - CreateQuicStream(scope, p2p_quic_stream.get()); - - RunUntilIdle(); - - ASSERT_TRUE(stream_delegate); - stream_delegate->OnDataReceived({1, 2, 3}, /*fin=*/false); - - RunUntilIdle(); - - NotShared<DOMUint8Array> read_buffer(DOMUint8Array::Create(5)); - RTCQuicStreamReadResult* result = - stream->readInto(read_buffer, ASSERT_NO_EXCEPTION); - EXPECT_EQ(3u, result->amount()); - EXPECT_FALSE(result->finished()); - EXPECT_THAT(GetSpan(read_buffer), ElementsAre(1, 2, 3, 0, 0)); - EXPECT_EQ(0u, stream->readBufferedAmount()); - - RunUntilIdle(); -} - -// Test that readInto() posts MarkReceivedDataConsumed() with the amount of -// bytes read to the underlying P2PQuicStream. -TEST_F(RTCQuicStreamTest, ReadIntoPostsMarkReceivedDataConsumed) { - V8TestingScope scope; - - P2PQuicStream::Delegate* stream_delegate = nullptr; - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(&stream_delegate); - EXPECT_CALL(*p2p_quic_stream, MarkReceivedDataConsumed(3)).Times(1); - - Persistent<RTCQuicStream> stream = - CreateQuicStream(scope, p2p_quic_stream.get()); - - RunUntilIdle(); - - ASSERT_TRUE(stream_delegate); - stream_delegate->OnDataReceived({1, 2, 3}, /*fin=*/false); - - RunUntilIdle(); - - NotShared<DOMUint8Array> read_buffer(DOMUint8Array::Create(5)); - RTCQuicStreamReadResult* result = - stream->readInto(read_buffer, ASSERT_NO_EXCEPTION); - EXPECT_EQ(3u, result->amount()); - EXPECT_FALSE(result->finished()); - - RunUntilIdle(); -} - -// Test that readInto() returns {finished: true} if OnDataReceived() has -// indicated the stream is finished without receiving any data. -TEST_F(RTCQuicStreamTest, ReadIntoReadsBareFin) { - V8TestingScope scope; - - P2PQuicStream::Delegate* stream_delegate = nullptr; - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(&stream_delegate); - - Persistent<RTCQuicStream> stream = - CreateQuicStream(scope, p2p_quic_stream.get()); - - RunUntilIdle(); - - ASSERT_TRUE(stream_delegate); - stream_delegate->OnDataReceived({}, /*fin=*/true); - - RunUntilIdle(); - - NotShared<DOMUint8Array> empty_read_buffer(DOMUint8Array::Create(0)); - RTCQuicStreamReadResult* result = - stream->readInto(empty_read_buffer, ASSERT_NO_EXCEPTION); - EXPECT_EQ(0u, result->amount()); - EXPECT_TRUE(result->finished()); - - RunUntilIdle(); -} - -// Test that readInto() indicates finished once all buffered received data has -// been read. -TEST_F(RTCQuicStreamTest, ReadIntoReadsBufferedDataAndFinish) { - V8TestingScope scope; - - P2PQuicStream::Delegate* stream_delegate = nullptr; - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(&stream_delegate); - - Persistent<RTCQuicStream> stream = - CreateQuicStream(scope, p2p_quic_stream.get()); - - RunUntilIdle(); - - ASSERT_TRUE(stream_delegate); - stream_delegate->OnDataReceived({1, 2, 3}, /*fin=*/true); - - RunUntilIdle(); - - NotShared<DOMUint8Array> read_buffer(DOMUint8Array::Create(3)); - RTCQuicStreamReadResult* result = - stream->readInto(read_buffer, ASSERT_NO_EXCEPTION); - EXPECT_EQ(3u, result->amount()); - EXPECT_TRUE(result->finished()); - EXPECT_THAT(GetSpan(read_buffer), ElementsAre(1, 2, 3)); - - RunUntilIdle(); -} - -// Test that readInto() does not indicate finished until all buffered data has -// been read out, even if the finish has already been received. -TEST_F(RTCQuicStreamTest, ReadIntoReadsPartialDataBeforeFin) { - V8TestingScope scope; - - P2PQuicStream::Delegate* stream_delegate = nullptr; - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(&stream_delegate); - - Persistent<RTCQuicStream> stream = - CreateQuicStream(scope, p2p_quic_stream.get()); - - RunUntilIdle(); - - ASSERT_TRUE(stream_delegate); - stream_delegate->OnDataReceived({1, 2, 3}, /*fin=*/true); - - RunUntilIdle(); - - { - NotShared<DOMUint8Array> read_buffer(DOMUint8Array::Create(2)); - RTCQuicStreamReadResult* result = - stream->readInto(read_buffer, ASSERT_NO_EXCEPTION); - EXPECT_EQ(2u, result->amount()); - EXPECT_FALSE(result->finished()); - EXPECT_THAT(GetSpan(read_buffer), ElementsAre(1, 2)); - } - - { - NotShared<DOMUint8Array> read_buffer(DOMUint8Array::Create(2)); - RTCQuicStreamReadResult* result = - stream->readInto(read_buffer, ASSERT_NO_EXCEPTION); - EXPECT_EQ(1u, result->amount()); - EXPECT_TRUE(result->finished()); - EXPECT_THAT(GetSpan(read_buffer), ElementsAre(3, 0)); - } - - RunUntilIdle(); -} - -// Test that readInto() does not post MarkReceivedDataConsumed() to the -// underlying P2PQuicStream once the finish flag has been delivered in -// OnDataReceived(). -TEST_F(RTCQuicStreamTest, - ReadIntoDoesNotPostMarkReceivedDataConsumedOnceFinReceived) { - V8TestingScope scope; - - P2PQuicStream::Delegate* stream_delegate = nullptr; - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(&stream_delegate); - EXPECT_CALL(*p2p_quic_stream, MarkReceivedDataConsumed(_)).Times(0); - - Persistent<RTCQuicStream> stream = - CreateQuicStream(scope, p2p_quic_stream.get()); - - RunUntilIdle(); - - ASSERT_TRUE(stream_delegate); - stream_delegate->OnDataReceived({1, 2, 3}, /*fin=*/true); - - RunUntilIdle(); - - NotShared<DOMUint8Array> read_buffer(DOMUint8Array::Create(2)); - - RTCQuicStreamReadResult* result = - stream->readInto(read_buffer, ASSERT_NO_EXCEPTION); - EXPECT_EQ(2u, result->amount()); - EXPECT_FALSE(result->finished()); - - result = stream->readInto(read_buffer, ASSERT_NO_EXCEPTION); - EXPECT_EQ(1u, result->amount()); - EXPECT_TRUE(result->finished()); - - RunUntilIdle(); -} - -// Test that readInto() throws an InvalidStateError if the finish flag has -// already been read out. -TEST_F(RTCQuicStreamTest, ReadIntoThrowsIfFinishAlreadyRead) { - V8TestingScope scope; - - P2PQuicStream::Delegate* stream_delegate = nullptr; - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(&stream_delegate); - - Persistent<RTCQuicStream> stream = - CreateQuicStream(scope, p2p_quic_stream.get()); - - RunUntilIdle(); - - ASSERT_TRUE(stream_delegate); - stream_delegate->OnDataReceived({}, /*fin=*/true); - - RunUntilIdle(); - - NotShared<DOMUint8Array> read_buffer(DOMUint8Array::Create(2)); - EXPECT_TRUE(stream->readInto(read_buffer, ASSERT_NO_EXCEPTION)->finished()); - - stream->readInto(read_buffer, scope.GetExceptionState()); - EXPECT_EQ(DOMExceptionCode::kInvalidStateError, - scope.GetExceptionState().CodeAs<DOMExceptionCode>()); -} - -// Test that readInto() throws an InvalidStateError if the stream is closed. -TEST_F(RTCQuicStreamTest, ReadIntoThrowsIfClosed) { - V8TestingScope scope; - - P2PQuicStream::Delegate* stream_delegate = nullptr; - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(&stream_delegate); - - Persistent<RTCQuicStream> stream = - CreateQuicStream(scope, p2p_quic_stream.get()); - EXPECT_CALL(*p2p_quic_stream.get(), SetDelegate(nullptr)); - - stream->reset(); - - NotShared<DOMUint8Array> read_buffer(DOMUint8Array::Create(2)); - stream->readInto(read_buffer, scope.GetExceptionState()); - EXPECT_EQ(DOMExceptionCode::kInvalidStateError, - scope.GetExceptionState().CodeAs<DOMExceptionCode>()); - - RunUntilIdle(); -} - -// The following group tests waitForReadable(). - -// Test that a waitForReadable() promise resolves once OnDataReceived() delivers -// enough data. -TEST_F(RTCQuicStreamTest, WaitForReadableResolves) { - V8TestingScope scope; - - P2PQuicStream::Delegate* stream_delegate = nullptr; - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(&stream_delegate); - Persistent<RTCQuicStream> stream = - CreateQuicStream(scope, p2p_quic_stream.get()); - - ScriptPromise promise = - stream->waitForReadable(scope.GetScriptState(), 3, ASSERT_NO_EXCEPTION); - EXPECT_EQ(v8::Promise::kPending, - promise.V8Value().As<v8::Promise>()->State()); - - RunUntilIdle(); - - ASSERT_TRUE(stream_delegate); - stream_delegate->OnDataReceived({1, 2, 3}, /*fin=*/false); - - RunUntilIdle(); - - EXPECT_EQ(v8::Promise::kFulfilled, - promise.V8Value().As<v8::Promise>()->State()); -} - -// Test that a waitForReadable() promise resolves immediately if sufficient data -// is already in the receive buffer. -TEST_F(RTCQuicStreamTest, WaitForReadableResolveImmediately) { - V8TestingScope scope; - - P2PQuicStream::Delegate* stream_delegate = nullptr; - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(&stream_delegate); - Persistent<RTCQuicStream> stream = - CreateQuicStream(scope, p2p_quic_stream.get()); - - RunUntilIdle(); - - ASSERT_TRUE(stream_delegate); - stream_delegate->OnDataReceived({1, 2, 3}, /*fin=*/false); - - RunUntilIdle(); - - ScriptPromise promise = - stream->waitForReadable(scope.GetScriptState(), 3, ASSERT_NO_EXCEPTION); - EXPECT_EQ(v8::Promise::kFulfilled, - promise.V8Value().As<v8::Promise>()->State()); - - RunUntilIdle(); -} - -// Test that a waitForReadable() promise resolves immediately if finish has -// been received, but not yet read out. -TEST_F(RTCQuicStreamTest, - WaitForReadableResolveImmediatelyAfterFinishReceived) { - V8TestingScope scope; - - P2PQuicStream::Delegate* stream_delegate = nullptr; - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(&stream_delegate); - Persistent<RTCQuicStream> stream = - CreateQuicStream(scope, p2p_quic_stream.get()); - - RunUntilIdle(); - - ASSERT_TRUE(stream_delegate); - stream_delegate->OnDataReceived({}, /*fin=*/true); - - RunUntilIdle(); - - ScriptPromise promise = - stream->waitForReadable(scope.GetScriptState(), 10, ASSERT_NO_EXCEPTION); - EXPECT_EQ(v8::Promise::kFulfilled, - promise.V8Value().As<v8::Promise>()->State()); - - RunUntilIdle(); -} - -// Test that a waitForReadable() promise does not resolve until OnDataReceived() -// delivers at least the readable amount. -TEST_F(RTCQuicStreamTest, WaitForReadableDoesNotResolveUntilExceedsThreshold) { - V8TestingScope scope; - - P2PQuicStream::Delegate* stream_delegate = nullptr; - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(&stream_delegate); - Persistent<RTCQuicStream> stream = - CreateQuicStream(scope, p2p_quic_stream.get()); - - ScriptPromise promise = - stream->waitForReadable(scope.GetScriptState(), 5, ASSERT_NO_EXCEPTION); - EXPECT_EQ(v8::Promise::kPending, - promise.V8Value().As<v8::Promise>()->State()); - - RunUntilIdle(); - - ASSERT_TRUE(stream_delegate); - stream_delegate->OnDataReceived({1, 2, 3}, /*fin=*/false); - - RunUntilIdle(); - - EXPECT_EQ(v8::Promise::kPending, - promise.V8Value().As<v8::Promise>()->State()); - - stream_delegate->OnDataReceived({4, 5}, /*fin=*/false); - - RunUntilIdle(); - - EXPECT_EQ(v8::Promise::kFulfilled, - promise.V8Value().As<v8::Promise>()->State()); -} - -// Test that if two waitForReadable() promises are waiting on different readable -// amounts, OnDataReceived() which satisfies the first readable amount but not -// the second will only resolve the first promise. Once OnDataReceived() is -// received again with readable amount satisfying the second promise then it -// will be resolved. -TEST_F(RTCQuicStreamTest, TwoWaitForReadablePromisesResolveInSequence) { - V8TestingScope scope; - - P2PQuicStream::Delegate* stream_delegate = nullptr; - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(&stream_delegate); - Persistent<RTCQuicStream> stream = - CreateQuicStream(scope, p2p_quic_stream.get()); - - ScriptPromise promise_3 = - stream->waitForReadable(scope.GetScriptState(), 3, ASSERT_NO_EXCEPTION); - ScriptPromise promise_5 = - stream->waitForReadable(scope.GetScriptState(), 5, ASSERT_NO_EXCEPTION); - - RunUntilIdle(); - - ASSERT_TRUE(stream_delegate); - stream_delegate->OnDataReceived({1, 2, 3}, /*fin=*/false); - - RunUntilIdle(); - - EXPECT_EQ(v8::Promise::kFulfilled, - promise_3.V8Value().As<v8::Promise>()->State()); - EXPECT_EQ(v8::Promise::kPending, - promise_5.V8Value().As<v8::Promise>()->State()); - - stream_delegate->OnDataReceived({4, 5}, /*fin=*/false); - - RunUntilIdle(); - - EXPECT_EQ(v8::Promise::kFulfilled, - promise_5.V8Value().As<v8::Promise>()->State()); -} - -// Test that if two waitForReadable() promises are waiting on different -// thresholds and a single OnDataReceived() is received such that the readable -// amount satisfies both promises then they are both resolved. -TEST_F(RTCQuicStreamTest, TwoWaitForReadablePromisesResolveTogether) { - V8TestingScope scope; - - P2PQuicStream::Delegate* stream_delegate = nullptr; - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(&stream_delegate); - Persistent<RTCQuicStream> stream = - CreateQuicStream(scope, p2p_quic_stream.get()); - - ScriptPromise promise_3 = - stream->waitForReadable(scope.GetScriptState(), 3, ASSERT_NO_EXCEPTION); - ScriptPromise promise_5 = - stream->waitForReadable(scope.GetScriptState(), 5, ASSERT_NO_EXCEPTION); - - RunUntilIdle(); - - ASSERT_TRUE(stream_delegate); - stream_delegate->OnDataReceived({1, 2, 3, 4, 5}, /*fin=*/false); - - RunUntilIdle(); - - EXPECT_EQ(v8::Promise::kFulfilled, - promise_3.V8Value().As<v8::Promise>()->State()); - EXPECT_EQ(v8::Promise::kFulfilled, - promise_5.V8Value().As<v8::Promise>()->State()); -} - -// Test that a remote finish immediately resolves all pending waitForReadable() -// promises. -TEST_F(RTCQuicStreamTest, RemoteFinishResolvesPendingWaitForReadablePromises) { - V8TestingScope scope; - - P2PQuicStream::Delegate* stream_delegate = nullptr; - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(&stream_delegate); - Persistent<RTCQuicStream> stream = - CreateQuicStream(scope, p2p_quic_stream.get()); - - ScriptPromise promise_3 = - stream->waitForReadable(scope.GetScriptState(), 3, ASSERT_NO_EXCEPTION); - ScriptPromise promise_5 = - stream->waitForReadable(scope.GetScriptState(), 5, ASSERT_NO_EXCEPTION); - - RunUntilIdle(); - - ASSERT_TRUE(stream_delegate); - stream_delegate->OnDataReceived({}, /*fin=*/true); - - RunUntilIdle(); - - EXPECT_EQ(v8::Promise::kFulfilled, - promise_3.V8Value().As<v8::Promise>()->State()); - EXPECT_EQ(v8::Promise::kFulfilled, - promise_5.V8Value().As<v8::Promise>()->State()); -} - -// Test that calling waitForReadable() resolves immediately if the finish has -// been received via OnDataReceived() but not yet read out via readInto(). -// Note: If the finish has been read out via readInto(), waitForReadable() will -// throw an exception since the stream is no longer readable. -TEST_F(RTCQuicStreamTest, WaitForReadableResolvesImmediatelyIfRemoteFinished) { - V8TestingScope scope; - - P2PQuicStream::Delegate* stream_delegate = nullptr; - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(&stream_delegate); - Persistent<RTCQuicStream> stream = - CreateQuicStream(scope, p2p_quic_stream.get()); - - RunUntilIdle(); - - ASSERT_TRUE(stream_delegate); - stream_delegate->OnDataReceived({}, /*fin=*/true); - - RunUntilIdle(); - - ScriptPromise promise = - stream->waitForReadable(scope.GetScriptState(), 5, ASSERT_NO_EXCEPTION); - EXPECT_EQ(v8::Promise::kFulfilled, - promise.V8Value().As<v8::Promise>()->State()); -} - -// The following group tests state transitions with reset(), write() with a -// finish, remote reset() and remote write() with a finish. - -// Test that a OnRemoteReset() immediately transitions the state to 'closed'. -TEST_F(RTCQuicStreamTest, OnRemoteResetTransitionsToClosed) { - V8TestingScope scope; - - P2PQuicStream::Delegate* stream_delegate = nullptr; - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(&stream_delegate); - Persistent<RTCQuicStream> stream = - CreateQuicStream(scope, p2p_quic_stream.get()); - - RunUntilIdle(); - - ASSERT_TRUE(stream_delegate); - EXPECT_EQ("open", stream->state()); - EXPECT_CALL(*p2p_quic_stream.get(), SetDelegate(nullptr)); - - stream_delegate->OnRemoteReset(); - - RunUntilIdle(); - - EXPECT_EQ("closed", stream->state()); - - RunUntilIdle(); -} - -// Test that writing a finish after reading out a remote finish transitions -// state to 'closed'. -TEST_F(RTCQuicStreamTest, FinishAfterReadingRemoteFinishTransitionsToClosed) { - V8TestingScope scope; - - P2PQuicStream::Delegate* stream_delegate = nullptr; - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(&stream_delegate); - EXPECT_CALL(*p2p_quic_stream, WriteData(_, true)).Times(1); - Persistent<RTCQuicStream> stream = - CreateQuicStream(scope, p2p_quic_stream.get()); - - RunUntilIdle(); - - ASSERT_TRUE(stream_delegate); - stream_delegate->OnDataReceived({}, /*fin=*/true); - - RunUntilIdle(); - - NotShared<DOMUint8Array> read_buffer(DOMUint8Array::Create(10)); - EXPECT_TRUE(stream->readInto(read_buffer, ASSERT_NO_EXCEPTION)->finished()); - - EXPECT_EQ("closing", stream->state()); - EXPECT_CALL(*p2p_quic_stream.get(), SetDelegate(nullptr)); - - stream->write(CreateWriteParametersWithoutData(/*finish=*/true), - ASSERT_NO_EXCEPTION); - - EXPECT_EQ("closed", stream->state()); - - RunUntilIdle(); -} - -// Test that reading out a remote finish after writing a finish transitions -// state to 'closed'. -TEST_F(RTCQuicStreamTest, ReadingRemoteFinishAfterFinishTransitionsToClosed) { - V8TestingScope scope; - - P2PQuicStream::Delegate* stream_delegate = nullptr; - auto p2p_quic_stream = std::make_unique<MockP2PQuicStream>(&stream_delegate); - EXPECT_CALL(*p2p_quic_stream, WriteData(_, true)).Times(1); - Persistent<RTCQuicStream> stream = - CreateQuicStream(scope, p2p_quic_stream.get()); - - stream->write(CreateWriteParametersWithoutData(/*finish=*/true), - ASSERT_NO_EXCEPTION); - - EXPECT_EQ("closing", stream->state()); - - RunUntilIdle(); - - ASSERT_TRUE(stream_delegate); - EXPECT_CALL(*p2p_quic_stream.get(), SetDelegate(nullptr)); - - stream_delegate->OnDataReceived({}, /*fin=*/true); - - RunUntilIdle(); - - EXPECT_EQ("closing", stream->state()); - - NotShared<DOMUint8Array> read_buffer(DOMUint8Array::Create(10)); - EXPECT_TRUE(stream->readInto(read_buffer, ASSERT_NO_EXCEPTION)->finished()); - - EXPECT_EQ("closed", stream->state()); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_write_parameters.idl b/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_write_parameters.idl deleted file mode 100644 index 2d8d47c2..0000000 --- a/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_write_parameters.idl +++ /dev/null
@@ -1,9 +0,0 @@ -// Copyright 2018 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://w3c.github.io/webrtc-quic/#dom-rtcquicstreamwriteparameters -dictionary RTCQuicStreamWriteParameters { - Uint8Array data; - boolean finish = false; -};
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.cc b/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.cc deleted file mode 100644 index 1d0953d..0000000 --- a/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.cc +++ /dev/null
@@ -1,715 +0,0 @@ -// Copyright 2018 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/peerconnection/rtc_quic_transport.h" - -#include "net/quic/platform/impl/quic_chromium_clock.h" -#include "net/quic/quic_chromium_alarm_factory.h" -#include "third_party/blink/public/platform/platform.h" -#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" -#include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_quic_transport_stats.h" -#include "third_party/blink/renderer/core/dom/document.h" -#include "third_party/blink/renderer/core/dom/dom_high_res_time_stamp.h" -#include "third_party/blink/renderer/core/dom/events/event.h" -#include "third_party/blink/renderer/core/frame/local_frame.h" -#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_factory_impl.h" -#include "third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.h" -#include "third_party/blink/renderer/modules/peerconnection/rtc_certificate.h" -#include "third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.h" -#include "third_party/blink/renderer/modules/peerconnection/rtc_quic_stream.h" -#include "third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_event.h" - -namespace blink { -namespace { -// QUIC requires 128 bits of entropy for the pre shared key. -const size_t kPreSharedKeyLength = 128 / 8; - -// This class wraps a P2PQuicTransportFactoryImpl but does not construct it -// until CreateQuicTransport is called for the first time. This ensures that it -// is executed on the WebRTC worker thread. -class DefaultP2PQuicTransportFactory : public P2PQuicTransportFactory { - public: - explicit DefaultP2PQuicTransportFactory( - scoped_refptr<base::SingleThreadTaskRunner> host_thread) - : host_thread_(std::move(host_thread)) { - DCHECK(host_thread_); - } - - // P2PQuicTransportFactory overrides. - std::unique_ptr<P2PQuicTransport> CreateQuicTransport( - P2PQuicTransport::Delegate* delegate, - P2PQuicPacketTransport* packet_transport, - const P2PQuicTransportConfig& config) override { - DCHECK(host_thread_->RunsTasksInCurrentSequence()); - return GetFactory()->CreateQuicTransport(delegate, packet_transport, - config); - } - - private: - P2PQuicTransportFactory* GetFactory() { - DCHECK(host_thread_->RunsTasksInCurrentSequence()); - if (!factory_impl_) { - quic::QuicClock* clock = quic::QuicChromiumClock::GetInstance(); - auto alarm_factory = std::make_unique<net::QuicChromiumAlarmFactory>( - host_thread_.get(), clock); - factory_impl_ = std::make_unique<P2PQuicTransportFactoryImpl>( - clock, std::move(alarm_factory)); - } - return factory_impl_.get(); - } - - scoped_refptr<base::SingleThreadTaskRunner> host_thread_; - std::unique_ptr<P2PQuicTransportFactory> factory_impl_; -}; - -void RejectPromise(ScriptPromiseResolver* promise_resolver, - const char* method_name) { - ScriptState::Scope scope(promise_resolver->GetScriptState()); - ExceptionState exception_state( - promise_resolver->GetScriptState()->GetIsolate(), - ExceptionState::kExecutionContext, "RTCQuicTransport", method_name); - exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, - "The RTCQuicTransport is closed."); - promise_resolver->Reject(exception_state); -} - -} // namespace - -RTCQuicTransport* RTCQuicTransport::Create(ExecutionContext* context, - RTCIceTransport* transport, - ExceptionState& exception_state) { - return Create(context, transport, {}, exception_state); -} - -RTCQuicTransport* RTCQuicTransport::Create( - ExecutionContext* context, - RTCIceTransport* transport, - const HeapVector<Member<RTCCertificate>>& certificates, - ExceptionState& exception_state) { - return Create(context, transport, certificates, exception_state, - std::make_unique<DefaultP2PQuicTransportFactory>( - PeerConnectionDependencyFactory::GetInstance() - ->GetWebRtcNetworkTaskRunner())); -} - -RTCQuicTransport* RTCQuicTransport::Create( - ExecutionContext* context, - RTCIceTransport* transport, - const HeapVector<Member<RTCCertificate>>& certificates, - ExceptionState& exception_state, - std::unique_ptr<P2PQuicTransportFactory> p2p_quic_transport_factory) { - DCHECK(context); - DCHECK(transport); - DCHECK(p2p_quic_transport_factory); - if (transport->IsClosed()) { - exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, - "Cannot construct an RTCQuicTransport " - "with a closed RTCIceTransport."); - return nullptr; - } - if (transport->HasConsumer()) { - exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, - "Cannot construct an RTCQuicTransport " - "with an RTCIceTransport that already " - "has a connected RTCQuicTransport."); - return nullptr; - } - if (transport->IsFromPeerConnection()) { - exception_state.ThrowDOMException( - DOMExceptionCode::kInvalidStateError, - "Cannot construct an RTCQuicTransport " - "with an RTCIceTransport that came from an " - "RTCPeerConnection."); - return nullptr; - } - for (const auto& certificate : certificates) { - if (certificate->expires() < - ConvertSecondsToDOMTimeStamp(base::Time::Now().ToDoubleT())) { - exception_state.ThrowTypeError( - "Cannot construct an RTCQuicTransport with an expired " - "certificate."); - return nullptr; - } - } - uint8_t generated_key[kPreSharedKeyLength]; - quic::QuicRandom::GetInstance()->RandBytes(generated_key, - base::size(generated_key)); - return MakeGarbageCollected<RTCQuicTransport>( - context, transport, - DOMArrayBuffer::Create(generated_key, base::size(generated_key)), - certificates, exception_state, std::move(p2p_quic_transport_factory)); -} - -RTCQuicTransport::RTCQuicTransport( - ExecutionContext* context, - RTCIceTransport* transport, - DOMArrayBuffer* key, - const HeapVector<Member<RTCCertificate>>& certificates, - ExceptionState& exception_state, - std::unique_ptr<P2PQuicTransportFactory> p2p_quic_transport_factory) - : ExecutionContextClient(context), - transport_(transport), - key_(key), - certificates_(certificates), - p2p_quic_transport_factory_(std::move(p2p_quic_transport_factory)) { - DCHECK_GT(key_->ByteLengthAsSizeT(), 0u); - transport->ConnectConsumer(this); -} - -RTCQuicTransport::~RTCQuicTransport() { - DCHECK(!proxy_); -} - -RTCIceTransport* RTCQuicTransport::transport() const { - return transport_; -} - -String RTCQuicTransport::state() const { - switch (state_) { - case RTCQuicTransportState::kNew: - return "new"; - case RTCQuicTransportState::kConnecting: - return "connecting"; - case RTCQuicTransportState::kConnected: - return "connected"; - case RTCQuicTransportState::kClosed: - return "closed"; - case RTCQuicTransportState::kFailed: - return "failed"; - } - return String(); -} - -DOMArrayBuffer* RTCQuicTransport::getKey() const { - return DOMArrayBuffer::Create(key_->Data(), key_->ByteLengthAsSizeT()); -} - -void RTCQuicTransport::connect(ExceptionState& exception_state) { - if (RaiseExceptionIfClosed(exception_state)) { - return; - } - if (RaiseExceptionIfStarted(exception_state)) { - return; - } - start_reason_ = StartReason::kClientConnecting; - std::string pre_shared_key(static_cast<const char*>(key_->Data()), - key_->ByteLengthAsSizeT()); - StartConnection(quic::Perspective::IS_CLIENT, - P2PQuicTransport::StartConfig(pre_shared_key)); -} - -void RTCQuicTransport::listen(const DOMArrayPiece& remote_key, - ExceptionState& exception_state) { - if (remote_key.ByteLengthAsSizeT() == 0u) { - exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError, - "Cannot listen with an empty key."); - return; - } - if (RaiseExceptionIfClosed(exception_state)) { - return; - } - if (RaiseExceptionIfStarted(exception_state)) { - return; - } - start_reason_ = StartReason::kServerListening; - std::string pre_shared_key(static_cast<const char*>(remote_key.Data()), - remote_key.ByteLengthAsSizeT()); - StartConnection(quic::Perspective::IS_SERVER, - P2PQuicTransport::StartConfig(pre_shared_key)); -} - -RTCQuicParameters* RTCQuicTransport::getLocalParameters() const { - RTCQuicParameters* result = RTCQuicParameters::Create(); - - HeapVector<Member<RTCDtlsFingerprint>> fingerprints; - for (const auto& certificate : certificates_) { - // TODO(github.com/w3c/webrtc-quic/issues/33): The specification says that - // getLocalParameters should return one fingerprint per certificate but is - // not clear which one to pick if an RTCCertificate has multiple - // fingerprints. - for (const auto& certificate_fingerprint : certificate->getFingerprints()) { - fingerprints.push_back(certificate_fingerprint); - } - } - result->setFingerprints(fingerprints); - return result; -} - -RTCQuicParameters* RTCQuicTransport::getRemoteParameters() const { - return remote_parameters_; -} - -const HeapVector<Member<RTCCertificate>>& RTCQuicTransport::getCertificates() - const { - return certificates_; -} - -const HeapVector<Member<DOMArrayBuffer>>& -RTCQuicTransport::getRemoteCertificates() const { - return remote_certificates_; -} - -static quic::Perspective QuicPerspectiveFromIceRole(cricket::IceRole ice_role) { - switch (ice_role) { - case cricket::ICEROLE_CONTROLLED: - return quic::Perspective::IS_CLIENT; - case cricket::ICEROLE_CONTROLLING: - return quic::Perspective::IS_SERVER; - default: - NOTREACHED(); - } - return quic::Perspective::IS_CLIENT; -} - -static std::unique_ptr<rtc::SSLFingerprint> RTCDtlsFingerprintToSSLFingerprint( - const RTCDtlsFingerprint* dtls_fingerprint) { - std::string algorithm = dtls_fingerprint->algorithm().Utf8(); - std::string value = dtls_fingerprint->value().Utf8(); - std::unique_ptr<rtc::SSLFingerprint> rtc_fingerprint = - rtc::SSLFingerprint::CreateUniqueFromRfc4572(algorithm, value); - DCHECK(rtc_fingerprint); - return rtc_fingerprint; -} - -void RTCQuicTransport::start(RTCQuicParameters* remote_parameters, - ExceptionState& exception_state) { - if (RaiseExceptionIfClosed(exception_state)) { - return; - } - if (RaiseExceptionIfStarted(exception_state)) { - return; - } - remote_parameters_ = remote_parameters; - start_reason_ = StartReason::kP2PWithRemoteFingerprints; - if (transport_->IsStarted()) { - Vector<std::unique_ptr<rtc::SSLFingerprint>> rtc_fingerprints; - for (const RTCDtlsFingerprint* fingerprint : - remote_parameters_->fingerprints()) { - rtc_fingerprints.push_back( - RTCDtlsFingerprintToSSLFingerprint(fingerprint)); - }; - StartConnection(QuicPerspectiveFromIceRole(transport_->GetRole()), - P2PQuicTransport::StartConfig(std::move(rtc_fingerprints))); - } -} - -void RTCQuicTransport::StartConnection( - quic::Perspective perspective, - P2PQuicTransport::StartConfig start_config) { - DCHECK_EQ(state_, RTCQuicTransportState::kNew); - DCHECK_NE(start_reason_, StartReason::kNotStarted); - - state_ = RTCQuicTransportState::kConnecting; - // We don't create the underlying transports until we are starting - // to connect. - Vector<rtc::scoped_refptr<rtc::RTCCertificate>> rtc_certificates; - for (const auto& certificate : certificates_) { - rtc_certificates.push_back(certificate->Certificate()); - } - IceTransportProxy* transport_proxy = transport_->ConnectConsumer(this); - P2PQuicTransportConfig quic_transport_config( - perspective, rtc_certificates, - /*stream_delegate_read_buffer_size_in=*/RTCQuicStream::kReadBufferSize, - /*stream_write_buffer_size_in=*/RTCQuicStream::kWriteBufferSize); - proxy_.reset(new QuicTransportProxy(this, transport_proxy, - std::move(p2p_quic_transport_factory_), - quic_transport_config)); - proxy_->Start(std::move(start_config)); -} - -void RTCQuicTransport::OnIceTransportStarted() { - // If start() has already been called, we now start up the connection, - // since start() determines its quic::Perspective based upon ICE. - if (start_reason_ == StartReason::kP2PWithRemoteFingerprints) { - DCHECK(remote_parameters_); - Vector<std::unique_ptr<rtc::SSLFingerprint>> rtc_fingerprints; - for (const RTCDtlsFingerprint* fingerprint : - remote_parameters_->fingerprints()) { - rtc_fingerprints.push_back( - RTCDtlsFingerprintToSSLFingerprint(fingerprint)); - }; - StartConnection(QuicPerspectiveFromIceRole(transport_->GetRole()), - P2PQuicTransport::StartConfig(std::move(rtc_fingerprints))); - } -} - -void RTCQuicTransport::stop() { - if (IsClosed()) { - // The transport could have already been closed due to the context being - // destroyed, the RTCIceTransport closing or a remote/local stop(). - return; - } - if (IsDisposed()) { - // This occurs in the "failed" state. - state_ = RTCQuicTransportState::kClosed; - return; - } - Close(CloseReason::kLocalStopped); -} - -RTCQuicStream* RTCQuicTransport::createStream(ExceptionState& exception_state) { - // TODO(github.com/w3c/webrtc-quic/issues/50): Maybe support createStream in - // the 'new' or 'connecting' states. - if (state_ != RTCQuicTransportState::kConnected) { - exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, - "RTCQuicTransport.createStream() is only " - "valid in the 'connected' state."); - return nullptr; - } - return AddStream(proxy_->CreateStream()); -} - -ScriptPromise RTCQuicTransport::readyToSendDatagram( - ScriptState* script_state, - ExceptionState& exception_state) { - if (ready_to_send_datagram_promise_) { - exception_state.ThrowDOMException( - DOMExceptionCode::kInvalidStateError, - "Pending readyToSendDatagram promise exists"); - return ScriptPromise(); - } - if (RaiseExceptionIfNotConnected(exception_state)) { - return ScriptPromise(); - } - - auto* promise_resolver = - MakeGarbageCollected<ScriptPromiseResolver>(script_state); - ScriptPromise promise = promise_resolver->Promise(); - if (CanWriteDatagram()) { - promise_resolver->Resolve(); - return promise; - } - ready_to_send_datagram_promise_ = promise_resolver; - return promise; -} - -void RTCQuicTransport::sendDatagram(const DOMArrayPiece& data, - ExceptionState& exception_state) { - if (RaiseExceptionIfNotConnected(exception_state)) { - return; - } - if (!CanWriteDatagram()) { - exception_state.ThrowDOMException( - DOMExceptionCode::kInvalidStateError, - "Cannot send datagram because not readyToSend()"); - return; - } - if (data.ByteLengthAsSizeT() > max_datagram_length_) { - exception_state.ThrowDOMException( - DOMExceptionCode::kInvalidStateError, - "data of size " + String::Number(data.ByteLengthAsSizeT()) + - " is too large to fit into a datagram of max size: " + - String::Number(max_datagram_length_.value_or(0))); - return; - } - - Vector<uint8_t> datagram(static_cast<wtf_size_t>(data.ByteLengthAsSizeT())); - memcpy(datagram.data(), data.Data(), data.ByteLengthAsSizeT()); - proxy_->SendDatagram(std::move(datagram)); - num_buffered_sent_datagrams_++; -} - -ScriptPromise RTCQuicTransport::receiveDatagrams( - ScriptState* script_state, - ExceptionState& exception_state) { - if (receive_datagrams_promise_) { - exception_state.ThrowDOMException( - DOMExceptionCode::kInvalidStateError, - "Pending receiveDatagrams promise exists"); - return ScriptPromise(); - } - - if (RaiseExceptionIfNotConnected(exception_state)) { - return ScriptPromise(); - } - - auto* promise_resolver = - MakeGarbageCollected<ScriptPromiseResolver>(script_state); - ScriptPromise promise = promise_resolver->Promise(); - if (received_datagrams_.IsEmpty()) { - receive_datagrams_promise_ = promise_resolver; - return promise; - } - HeapVector<Member<DOMArrayBuffer>> resolved_datagrams; - resolved_datagrams.swap(received_datagrams_); - promise_resolver->Resolve(resolved_datagrams); - return promise; -} - -ScriptPromise RTCQuicTransport::getStats(ScriptState* script_state, - ExceptionState& exception_state) { - // TODO(https://crbug.com/874296): If a shutdown procedure is implemented, we - // can cache the stats before the underlying transport is torn down. This - // would allow getting stats after your transport has closed. - if (state_ != RTCQuicTransportState::kConnected && - state_ != RTCQuicTransportState::kConnecting) { - exception_state.ThrowDOMException( - DOMExceptionCode::kInvalidStateError, - "The RTCQuicTransport's state is not 'connecting' or 'connected'."); - return ScriptPromise(); - } - auto* promise_resolver = - MakeGarbageCollected<ScriptPromiseResolver>(script_state); - uint32_t request_id = ++get_stats_id_counter_; - stats_promise_map_.Set(request_id, promise_resolver); - proxy_->GetStats(request_id); - return promise_resolver->Promise(); -} - -RTCQuicStream* RTCQuicTransport::AddStream(QuicStreamProxy* stream_proxy) { - auto* stream = MakeGarbageCollected<RTCQuicStream>(GetExecutionContext(), - this, stream_proxy); - stream_proxy->set_delegate(stream); - streams_.insert(stream); - return stream; -} - -void RTCQuicTransport::RemoveStream(RTCQuicStream* stream) { - DCHECK(stream); - auto it = streams_.find(stream); - DCHECK(it != streams_.end()); - streams_.erase(it); -} - -void RTCQuicTransport::OnConnected(P2PQuicNegotiatedParams negotiated_params) { - // Datagrams should always be supported between RTCQuicTransport endpoints. - DCHECK(negotiated_params.datagrams_supported()); - max_datagram_length_ = negotiated_params.max_datagram_length(); - state_ = RTCQuicTransportState::kConnected; - DispatchEvent(*Event::Create(event_type_names::kStatechange)); -} - -void RTCQuicTransport::OnConnectionFailed(const std::string& error_details, - bool from_remote) { - Close(CloseReason::kFailed); -} - -void RTCQuicTransport::OnRemoteStopped() { - Close(CloseReason::kRemoteStopped); -} - -void RTCQuicTransport::OnStream(QuicStreamProxy* stream_proxy) { - RTCQuicStream* stream = AddStream(stream_proxy); - DispatchEvent(*MakeGarbageCollected<RTCQuicStreamEvent>(stream)); -} - -static RTCQuicTransportStats* CreateRTCQuicTransportStats( - const P2PQuicTransportStats& p2p_stats) { - RTCQuicTransportStats* rtc_stats = RTCQuicTransportStats::Create(); - rtc_stats->setTimestamp( - ConvertTimeTicksToDOMHighResTimeStamp(p2p_stats.timestamp)); - rtc_stats->setBytesSent(p2p_stats.bytes_sent); - rtc_stats->setPacketsSent(p2p_stats.packets_sent); - rtc_stats->setStreamBytesSent(p2p_stats.stream_bytes_sent); - rtc_stats->setStreamBytesReceived(p2p_stats.stream_bytes_received); - rtc_stats->setNumOutgoingStreamsCreated( - p2p_stats.num_outgoing_streams_created); - rtc_stats->setNumIncomingStreamsCreated( - p2p_stats.num_incoming_streams_created); - rtc_stats->setBytesReceived(p2p_stats.bytes_received); - rtc_stats->setPacketsReceived(p2p_stats.packets_received); - rtc_stats->setPacketsProcessed(p2p_stats.packets_processed); - rtc_stats->setBytesRetransmitted(p2p_stats.bytes_retransmitted); - rtc_stats->setPacketsRetransmitted(p2p_stats.packets_retransmitted); - rtc_stats->setPacketsLost(p2p_stats.packets_lost); - rtc_stats->setPacketsDropped(p2p_stats.packets_dropped); - rtc_stats->setCryptoRetransmitCount(p2p_stats.crypto_retransmit_count); - rtc_stats->setMinRttUs(p2p_stats.min_rtt_us); - rtc_stats->setSmoothedRttUs(p2p_stats.srtt_us); - rtc_stats->setMaxPacketSize(p2p_stats.max_packet_size); - rtc_stats->setMaxReceivedPacketSize(p2p_stats.max_received_packet_size); - rtc_stats->setEstimatedBandwidthBps(p2p_stats.estimated_bandwidth_bps); - rtc_stats->setPacketsReordered(p2p_stats.packets_reordered); - rtc_stats->setBlockedFramesReceived(p2p_stats.blocked_frames_received); - rtc_stats->setBlockedFramesSent(p2p_stats.blocked_frames_sent); - rtc_stats->setConnectivityProbingPacketsReceived( - p2p_stats.connectivity_probing_packets_received); - rtc_stats->setNumDatagramsLost(p2p_stats.num_datagrams_lost); - return rtc_stats; -} - -void RTCQuicTransport::OnStats(uint32_t request_id, - const P2PQuicTransportStats& stats) { - auto it = stats_promise_map_.find(request_id); - DCHECK(it != stats_promise_map_.end()); - ScriptPromiseResolver* resolver = it->value; - stats_promise_map_.erase(it); - - RTCQuicTransportStats* rtc_stats = CreateRTCQuicTransportStats(stats); - rtc_stats->setNumReceivedDatagramsDropped(num_dropped_received_datagrams_); - - // Resolving a promise can cause user code to run, so do this last. - // See crbug.com/1108472 - resolver->Resolve(rtc_stats); -} - -void RTCQuicTransport::OnDatagramSent() { - num_buffered_sent_datagrams_--; - DCHECK_GE(num_buffered_sent_datagrams_, 0); - - // There may be a pending readyToSend promise that can now be resolved. - if (ready_to_send_datagram_promise_) { - ready_to_send_datagram_promise_.Release()->Resolve(); - } -} - -void RTCQuicTransport::OnDatagramReceived(Vector<uint8_t> datagram) { - DOMArrayBuffer* copied_datagram = DOMArrayBuffer::Create( - static_cast<void*>(datagram.data()), datagram.size()); - if (receive_datagrams_promise_) { - // We have an pending promise to resolve with received datagrams. - HeapVector<Member<DOMArrayBuffer>> received_datagrams; - received_datagrams.push_back(copied_datagram); - receive_datagrams_promise_.Release()->Resolve(received_datagrams); - return; - } - if (received_datagrams_.size() == kMaxBufferedRecvDatagrams) { - num_dropped_received_datagrams_++; - return; - } - received_datagrams_.push_back(copied_datagram); -} - -void RTCQuicTransport::OnIceTransportClosed( - RTCIceTransport::CloseReason reason) { - if (reason == RTCIceTransport::CloseReason::kContextDestroyed) { - Close(CloseReason::kContextDestroyed); - } else { - Close(CloseReason::kIceTransportClosed); - } -} - -void RTCQuicTransport::Close(CloseReason reason) { - DCHECK(!IsDisposed()); - - // Disconnect from the RTCIceTransport, allowing a new RTCQuicTransport to - // connect to it. - transport_->DisconnectConsumer(this); - - // Notify the active streams that the transport is closing. - for (RTCQuicStream* stream : streams_) { - stream->OnQuicTransportClosed(reason); - } - streams_.clear(); - - // Tear down the QuicTransportProxy and change the state. - switch (reason) { - case CloseReason::kLocalStopped: - case CloseReason::kIceTransportClosed: - case CloseReason::kContextDestroyed: - // The QuicTransportProxy may be active so gracefully Stop() before - // destroying it. - if (proxy_) { - proxy_->Stop(); - proxy_.reset(); - } - state_ = RTCQuicTransportState::kClosed; - break; - case CloseReason::kRemoteStopped: - case CloseReason::kFailed: - // The QuicTransportProxy has already been closed by the event, so just - // go ahead and delete it. - proxy_.reset(); - state_ = - (reason == CloseReason::kFailed ? RTCQuicTransportState::kFailed - : RTCQuicTransportState::kClosed); - DispatchEvent(*Event::Create(event_type_names::kStatechange)); - break; - } - received_datagrams_.clear(); - - if (reason != CloseReason::kContextDestroyed) { - // Cannot reject/resolve promises when ExecutionContext is being destroyed. - RejectPendingPromises(); - } - - DCHECK(!proxy_); - DCHECK(IsDisposed()); -} - -bool RTCQuicTransport::RaiseExceptionIfClosed( - ExceptionState& exception_state) const { - if (IsClosed()) { - exception_state.ThrowDOMException( - DOMExceptionCode::kInvalidStateError, - "The RTCQuicTransport's state is 'closed'."); - return true; - } - return false; -} - -bool RTCQuicTransport::RaiseExceptionIfNotConnected( - ExceptionState& exception_state) const { - if (state_ != RTCQuicTransportState::kConnected) { - exception_state.ThrowDOMException( - DOMExceptionCode::kInvalidStateError, - "RTCQuicTransport is not in the 'connected' state."); - return true; - } - return false; -} - -bool RTCQuicTransport::RaiseExceptionIfStarted( - ExceptionState& exception_state) const { - if (start_reason_ == StartReason::kServerListening) { - exception_state.ThrowDOMException( - DOMExceptionCode::kInvalidStateError, - "The RTCQuicTransport has already called listen()."); - return true; - } - if (start_reason_ == StartReason::kClientConnecting) { - exception_state.ThrowDOMException( - DOMExceptionCode::kInvalidStateError, - "The RTCQuicTransport has already called connect()."); - return true; - } - if (start_reason_ == StartReason::kP2PWithRemoteFingerprints) { - exception_state.ThrowDOMException( - DOMExceptionCode::kInvalidStateError, - "The RTCQuicTransport has already called start()."); - return true; - } - return false; -} - -void RTCQuicTransport::RejectPendingPromises() { - for (ScriptPromiseResolver* promise_resolver : stats_promise_map_.Values()) { - RejectPromise(promise_resolver, "getStats"); - } - stats_promise_map_.clear(); - if (ready_to_send_datagram_promise_) { - RejectPromise(ready_to_send_datagram_promise_.Release(), - "readyToSendDatagram"); - } - if (receive_datagrams_promise_) { - RejectPromise(receive_datagrams_promise_.Release(), "receiveDatagrams"); - } -} - -const AtomicString& RTCQuicTransport::InterfaceName() const { - return event_target_names::kRTCQuicTransport; -} - -ExecutionContext* RTCQuicTransport::GetExecutionContext() const { - return ExecutionContextClient::GetExecutionContext(); -} - -void RTCQuicTransport::Trace(Visitor* visitor) const { - visitor->Trace(transport_); - visitor->Trace(certificates_); - visitor->Trace(remote_certificates_); - visitor->Trace(remote_parameters_); - visitor->Trace(streams_); - visitor->Trace(key_); - visitor->Trace(stats_promise_map_); - visitor->Trace(receive_datagrams_promise_); - visitor->Trace(ready_to_send_datagram_promise_); - visitor->Trace(received_datagrams_); - EventTargetWithInlineData::Trace(visitor); - ExecutionContextClient::Trace(visitor); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.h b/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.h deleted file mode 100644 index 11ff5be..0000000 --- a/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.h +++ /dev/null
@@ -1,273 +0,0 @@ -// Copyright 2018 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_PEERCONNECTION_RTC_QUIC_TRANSPORT_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_RTC_QUIC_TRANSPORT_H_ - -#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" -#include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_quic_parameters.h" -#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h" -#include "third_party/blink/renderer/core/typed_arrays/dom_array_piece.h" -#include "third_party/blink/renderer/modules/event_target_modules.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_proxy.h" -#include "third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.h" - -namespace blink { - -class DOMArrayBuffer; -class ExceptionState; -class RTCCertificate; -class RTCQuicStream; -class P2PQuicTransportFactory; - -enum class RTCQuicTransportState { - kNew, - kConnecting, - kConnected, - kClosed, - kFailed -}; - -// The number of datagrams we are willing to buffer send side. -// -// This buffer exists to account for the thread hop delay in knowing if the -// QUIC connection is congestion control blocked or not. Ideally it should -// stay small to keep latency for sending datagrams low, but a higher value -// allows for higher throughput. -// -// Note: This value is not based upon measurements, but a guess for suitable -// throughput. More investigation could be done to tune this value. -const uint16_t kMaxBufferedSendDatagrams = 5; - -// The number of datagrams we are willing to buffer on the receive side before -// dropping them. This is so that if the main thread freezes datagrams aren't -// lost, without buffering them indefinitely. -// -// This value was chosen because the max datagram size is ~1.2 KB, meaning -// a max ~6MB of buffering, which currently is the same arbitrary value used for -// buffering stream data currently. -const uint32_t kMaxBufferedRecvDatagrams = 5000; - -// The RTCQuicTransport does not need to be ActiveScriptWrappable since the -// RTCIceTransport to which it is attached holds a strong reference to it as -// long as it is alive. -class MODULES_EXPORT RTCQuicTransport final - : public EventTargetWithInlineData, - public ExecutionContextClient, - public QuicTransportProxy::Delegate { - DEFINE_WRAPPERTYPEINFO(); - - public: - enum class CloseReason { - // stop() was called. - kLocalStopped, - // The remote side closed the QUIC connection. - kRemoteStopped, - // The QUIC connection failed. - kFailed, - // The RTCIceTransport was closed. - kIceTransportClosed, - // The ExecutionContext is being destroyed. - kContextDestroyed, - }; - - static RTCQuicTransport* Create(ExecutionContext* context, - RTCIceTransport* transport, - ExceptionState& exception_state); - static RTCQuicTransport* Create( - ExecutionContext* context, - RTCIceTransport* transport, - const HeapVector<Member<RTCCertificate>>& certificates, - ExceptionState& exception_state); - static RTCQuicTransport* Create( - ExecutionContext* context, - RTCIceTransport* transport, - const HeapVector<Member<RTCCertificate>>& certificates, - ExceptionState& exception_state, - std::unique_ptr<P2PQuicTransportFactory> p2p_quic_transport_factory); - - RTCQuicTransport( - ExecutionContext* context, - RTCIceTransport* transport, - DOMArrayBuffer* key, - const HeapVector<Member<RTCCertificate>>& certificates, - ExceptionState& exception_state, - std::unique_ptr<P2PQuicTransportFactory> p2p_quic_transport_factory); - ~RTCQuicTransport() override; - - // Called by the RTCIceTransport when it is being closed. - void OnIceTransportClosed(RTCIceTransport::CloseReason reason); - - // Called by the RTCIceTransport when its start() method is called. - void OnIceTransportStarted(); - - RTCQuicStream* AddStream(QuicStreamProxy* stream_proxy); - void RemoveStream(RTCQuicStream* stream); - - // https://w3c.github.io/webrtc-quic/#quic-transport* - RTCIceTransport* transport() const; - - // The pre shared key to be used in the QUIC handshake with connect(). - // This should be signaled to the remote endpoint and used with the remote - // endpoint's listen() function to begin a connection. - DOMArrayBuffer* getKey() const; - - // The maximum datagram size in bytes allowed with sendDatagram. - // Before the transport has become connected this will be 0. - base::Optional<uint16_t> maxDatagramLength() const { - return max_datagram_length_; - } - - String state() const; - // Note: The listen/connect functions encourage an API user to connect() - // before the remote endpoint has called listen(), which can result in the - // CHLO being sent before the server side is ready. Although the CHLO is - // cached by the RTCIceTransport (if it is connected), the API user is - // encouraged to not connect() until the remote endpoint has called listen(). - // An API design with the server side generating the pre shared key would - // enforce this, but we purposely constrained the client side to generate the - // key to enforce that a browser endpoint is generating the key in the case of - // communicating with a non-browser, server side endpoint. - // - // Begins the QUIC handshake as a client endpoint, using the internal |key_| - // as the pre shared key for the QUIC handshake. - void connect(ExceptionState& exception_state); - // Begins listening for the QUIC handshake as a server endpoint. Uses - // the |remote_key| from the remote side as a pre shared key in the QUIC - // handshake. - void listen(const DOMArrayPiece& remote_key, ExceptionState& exception_state); - // The following APIs that include certificates/parameters (including start()) - // are not used (or exposed to JavaScript) until QUIC supports both side - // certificate verification. - RTCQuicParameters* getLocalParameters() const; - RTCQuicParameters* getRemoteParameters() const; - const HeapVector<Member<RTCCertificate>>& getCertificates() const; - const HeapVector<Member<DOMArrayBuffer>>& getRemoteCertificates() const; - void start(RTCQuicParameters* remote_parameters, - ExceptionState& exception_state); - - void stop(); - RTCQuicStream* createStream(ExceptionState& exception_state); - // Throws InvalidStateError if called when previous promise returned from - // readyToSendDatagram is still pending. Resolves when transport is not - // blocked by congestion control for sending a datagram. This will resolve - // immediately if transport is not blocked. - ScriptPromise readyToSendDatagram(ScriptState* script_state, - ExceptionState& exception_state); - // Note: This deviates from the spec, which returns a promise that fulfills if - // the datagram is acked/lost. See unresolved issue: - // https://github.com/w3c/webrtc-quic/issues/117 - void sendDatagram(const DOMArrayPiece& data, ExceptionState& exception_state); - // Throws InvalidStateError if called when previous promise returned from - // receiveDatagrams is still pending. If datagrams have been buffered since - // the last call to receiveDatagrams, this will resolve immediately with the - // buffered datagrams. Otherwise it will resolve when a datagram is received. - // When too many datagrams are buffered they will be dropped. This will be - // reflected in the stats. - // - // Note: This deviates from the spec, which specifies adding a null value to - // the end of the sequence if datagrams are dropped. Instead, stats includes - // numReceivedDatagramsDropped. See issue: - // https://github.com/w3c/webrtc-quic/issues/124 - ScriptPromise receiveDatagrams(ScriptState* script_state, - ExceptionState& exception_state); - - // Resolves the promise with an RTCQuicTransportStats dictionary. - ScriptPromise getStats(ScriptState* script_state, - ExceptionState& exception_state); - DEFINE_ATTRIBUTE_EVENT_LISTENER(statechange, kStatechange) - DEFINE_ATTRIBUTE_EVENT_LISTENER(error, kError) - DEFINE_ATTRIBUTE_EVENT_LISTENER(quicstream, kQuicstream) - - // EventTarget overrides. - const AtomicString& InterfaceName() const override; - ExecutionContext* GetExecutionContext() const override; - - // For garbage collection. - void Trace(Visitor* visitor) const override; - - private: - enum class StartReason { - // listen() was called with the remote key. - kServerListening, - // connect() was called. - kClientConnecting, - // start() was called with the remote fingerprints. - // Note that start() is not currently exposed to JavaScript. - kP2PWithRemoteFingerprints, - // Initial default state. - kNotStarted, - }; - - // QuicTransportProxy::Delegate overrides; - void OnConnected(P2PQuicNegotiatedParams negotiated_params) override; - void OnConnectionFailed(const std::string& error_details, - bool from_remote) override; - void OnRemoteStopped() override; - void OnStream(QuicStreamProxy* stream_proxy) override; - void OnStats(uint32_t request_id, - const P2PQuicTransportStats& stats) override; - void OnDatagramSent() override; - void OnDatagramReceived(Vector<uint8_t> datagram) override; - - // Starts the underlying QUIC connection, by creating the underlying QUIC - // transport objects and starting the QUIC handshake. - void StartConnection(quic::Perspective role, - P2PQuicTransport::StartConfig start_config); - - // Permenantly closes the RTCQuicTransport with the given reason. - // The RTCQuicTransport must not already be closed or failed. - // This will transition the state to either closed or failed according to the - // reason. - void Close(CloseReason reason); - - bool IsClosed() const { return state_ == RTCQuicTransportState::kClosed; } - // The transport is no longer usable once it has reached the "failed" or - // "closed" state. - bool IsDisposed() const { - return (state_ == RTCQuicTransportState::kClosed || - state_ == RTCQuicTransportState::kFailed); - } - bool CanWriteDatagram() const { - return num_buffered_sent_datagrams_ < kMaxBufferedSendDatagrams; - } - bool RaiseExceptionIfClosed(ExceptionState& exception_state) const; - bool RaiseExceptionIfNotConnected(ExceptionState& exception_state) const; - bool RaiseExceptionIfStarted(ExceptionState& exception_state) const; - void RejectPendingPromises(); - - Member<RTCIceTransport> transport_; - RTCQuicTransportState state_ = RTCQuicTransportState::kNew; - StartReason start_reason_ = StartReason::kNotStarted; - // The pre shared key to be used in the QUIC handshake. It is used with - // connect() on the local side, and listen() on the remote side. - Member<DOMArrayBuffer> key_; - // The certificates/parameters are not being used until the QUIC library - // supports both side certificate verification in the crypto handshake. - HeapVector<Member<RTCCertificate>> certificates_; - HeapVector<Member<DOMArrayBuffer>> remote_certificates_; - Member<RTCQuicParameters> remote_parameters_; - std::unique_ptr<P2PQuicTransportFactory> p2p_quic_transport_factory_; - std::unique_ptr<QuicTransportProxy> proxy_; - HeapHashSet<Member<RTCQuicStream>> streams_; - // Maps from the ID of the stats request to the promise to be resolved. - HeapHashMap<uint32_t, Member<ScriptPromiseResolver>> stats_promise_map_; - uint32_t get_stats_id_counter_ = 0; - // The number of datagrams that have been given to QUIC but not sent on the - // network yet. This could be due to congestion control. - int num_buffered_sent_datagrams_ = 0; - // The number of datagrams that dropped because the RTCQuicTransport has - // received more datagrams than its max buffer size and there is no way to - // indicate backpressure to the send side. - uint32_t num_dropped_received_datagrams_ = 0; - HeapVector<Member<DOMArrayBuffer>> received_datagrams_; - base::Optional<uint16_t> max_datagram_length_; - Member<ScriptPromiseResolver> receive_datagrams_promise_; - Member<ScriptPromiseResolver> ready_to_send_datagram_promise_; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_RTC_QUIC_TRANSPORT_H_
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.idl b/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.idl deleted file mode 100644 index 54524edf..0000000 --- a/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.idl +++ /dev/null
@@ -1,39 +0,0 @@ -// Copyright 2018 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://w3c.github.io/webrtc-quic/#dom-rtcquictransportstate -enum RTCQuicTransportState { - "new", - "connecting", - "connected", - "closed", - "failed", -}; - -// https://w3c.github.io/webrtc-quic/#quic-transport* -[ - Exposed=Window, - RuntimeEnabled=RTCQuicTransport, - SecureContext -] interface RTCQuicTransport : EventTarget { - [CallWith=ExecutionContext, RaisesException, Measure] constructor(RTCIceTransport transport); - [Measure] readonly attribute RTCIceTransport transport; - [Measure] readonly attribute RTCQuicTransportState state; - [Measure] readonly attribute unsigned short? maxDatagramLength; - [Measure] ArrayBuffer getKey(); - [Measure, RaisesException] void connect(); - [Measure, RaisesException] void listen(BufferSource remote_key); - [Measure] void stop(); - [Measure, RaisesException] RTCQuicStream createStream(); - [CallWith=ScriptState, Measure, RaisesException] - Promise<void> readyToSendDatagram(); - [Measure, RaisesException] void sendDatagram(BufferSource data); - [CallWith=ScriptState, Measure, RaisesException] - Promise<sequence<ArrayBuffer>> receiveDatagrams(); - [CallWith=ScriptState, Measure, RaisesException] - Promise<RTCQuicTransportStats> getStats(); - attribute EventHandler onstatechange; - attribute EventHandler onerror; - attribute EventHandler onquicstream; -};
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport_stats.idl b/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport_stats.idl deleted file mode 100644 index 935dc653..0000000 --- a/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport_stats.idl +++ /dev/null
@@ -1,32 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -dictionary RTCQuicTransportStats { - double timestamp; - unsigned long long bytesSent; - unsigned long long packetsSent; - unsigned long long streamBytesSent; - unsigned long long streamBytesReceived; - unsigned long numOutgoingStreamsCreated; - unsigned long numIncomingStreamsCreated; - unsigned long long bytesReceived; - unsigned long long packetsReceived; - unsigned long long packetsProcessed; - unsigned long long bytesRetransmitted; - unsigned long long packetsRetransmitted; - unsigned long long packetsLost; - unsigned long long packetsDropped; - unsigned long long cryptoRetransmitCount; - unsigned long long minRttUs; - unsigned long long smoothedRttUs; - unsigned long long maxPacketSize; - unsigned long long maxReceivedPacketSize; - unsigned long long estimatedBandwidthBps; - unsigned long long packetsReordered; - unsigned long long blockedFramesReceived; - unsigned long long blockedFramesSent; - unsigned long long connectivityProbingPacketsReceived; - unsigned long numReceivedDatagramsDropped; - unsigned long numDatagramsLost; -};
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport_test.cc b/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport_test.cc deleted file mode 100644 index 64ef497..0000000 --- a/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport_test.cc +++ /dev/null
@@ -1,1169 +0,0 @@ -// Copyright 2018 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. - -// This file tests the RTCQuicTransport Blink bindings, QuicTransportProxy and -// QuicTransportHost by mocking out the underlying P2PQuicTransport. -// Everything is run on a single thread but with separate TestSimpleTaskRunners -// for the main thread / worker thread. - -#include "third_party/blink/renderer/modules/peerconnection/rtc_quic_transport_test.h" -#include "base/containers/span.h" -#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h" -#include "third_party/blink/renderer/bindings/core/v8/v8_array_buffer.h" -#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h" -#include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_ice_gather_options.h" -#include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_quic_transport_stats.h" -#include "third_party/blink/renderer/core/dom/dom_high_res_time_stamp.h" -#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_stats.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/test/mock_p2p_quic_packet_transport.h" -#include "third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.h" -#include "third_party/blink/renderer/platform/bindings/exception_state.h" -#include "third_party/webrtc/rtc_base/rtc_certificate_generator.h" - -namespace blink { -namespace { - -using testing::_; -using testing::Assign; -using testing::ElementsAre; -using testing::Invoke; -using testing::Mock; -using testing::Return; - -HeapVector<Member<RTCCertificate>> GenerateLocalRTCCertificates() { - HeapVector<Member<RTCCertificate>> certificates; - certificates.push_back(MakeGarbageCollected<RTCCertificate>( - rtc::RTCCertificateGenerator::GenerateCertificate(rtc::KeyParams::ECDSA(), - absl::nullopt))); - return certificates; -} - -constexpr char kRemoteFingerprintAlgorithm1[] = "sha-256"; -constexpr char kRemoteFingerprintValue1[] = - "8E:57:5F:8E:65:D2:83:7B:05:97:BB:72:DE:09:DE:03:BD:95:9B:A0:03:10:50:82:" - "5E:73:38:16:4C:E0:C5:84"; -const size_t kKeyLength = 16; -const uint8_t kKey[kKeyLength] = {0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15}; -// Arbitrary datagram. -const size_t kDatagramLength = 4; -const uint8_t kDatagram[kDatagramLength] = {0, 1, 2, 3}; -const uint16_t kMaxDatagramLengthBytes = 1000; - -RTCDtlsFingerprint* CreateRemoteFingerprint1() { - RTCDtlsFingerprint* dtls_fingerprint = RTCDtlsFingerprint::Create(); - dtls_fingerprint->setAlgorithm(kRemoteFingerprintAlgorithm1); - dtls_fingerprint->setValue(kRemoteFingerprintValue1); - return dtls_fingerprint; -} - -RTCQuicParameters* CreateRemoteRTCQuicParameters1() { - HeapVector<Member<RTCDtlsFingerprint>> fingerprints; - fingerprints.push_back(CreateRemoteFingerprint1()); - RTCQuicParameters* quic_parameters = RTCQuicParameters::Create(); - quic_parameters->setFingerprints(fingerprints); - return quic_parameters; -} - -// Sends datagrams without getting callbacks that they have been sent on the -// network until the buffer becomes full. -void FillDatagramBuffer(RTCQuicTransport* transport) { - for (size_t i = 0; i < kMaxBufferedSendDatagrams; ++i) { - transport->sendDatagram(DOMArrayBuffer::Create(kDatagram, kDatagramLength), - ASSERT_NO_EXCEPTION); - } -} - -static base::span<uint8_t> SpanFromDOMArrayBuffer(DOMArrayBuffer* buffer) { - return base::span<uint8_t>(static_cast<uint8_t*>(buffer->Data()), - buffer->ByteLengthAsSizeT()); -} - -} // namespace - -RTCQuicTransport* RTCQuicTransportTest::CreateQuicTransport( - V8TestingScope& scope, - RTCIceTransport* ice_transport, - const HeapVector<Member<RTCCertificate>>& certificates, - std::unique_ptr<MockP2PQuicTransport> mock_transport, - P2PQuicTransport::Delegate** delegate_out) { - return CreateQuicTransport(scope, ice_transport, certificates, - std::make_unique<MockP2PQuicTransportFactory>( - std::move(mock_transport), delegate_out)); -} - -RTCQuicTransport* RTCQuicTransportTest::CreateQuicTransport( - V8TestingScope& scope, - RTCIceTransport* ice_transport, - const HeapVector<Member<RTCCertificate>>& certificates, - std::unique_ptr<MockP2PQuicTransportFactory> mock_factory) { - return RTCQuicTransport::Create(scope.GetExecutionContext(), ice_transport, - certificates, ASSERT_NO_EXCEPTION, - std::move(mock_factory)); -} - -RTCQuicTransport* RTCQuicTransportTest::CreateConnectedQuicTransport( - V8TestingScope& scope, - P2PQuicTransport::Delegate** delegate_out) { - return CreateConnectedQuicTransport( - scope, std::make_unique<MockP2PQuicTransport>(), delegate_out); -} - -RTCQuicTransport* RTCQuicTransportTest::CreateConnectedQuicTransport( - V8TestingScope& scope, - std::unique_ptr<MockP2PQuicTransport> mock_transport, - P2PQuicTransport::Delegate** delegate_out) { - Persistent<RTCIceTransport> ice_transport = CreateIceTransport(scope); - ice_transport->start(CreateRemoteRTCIceParameters1(), "controlling", - ASSERT_NO_EXCEPTION); - P2PQuicTransport::Delegate* delegate = nullptr; - Persistent<RTCQuicTransport> quic_transport = - CreateQuicTransport(scope, ice_transport, GenerateLocalRTCCertificates(), - std::move(mock_transport), &delegate); - quic_transport->start(CreateRemoteRTCQuicParameters1(), ASSERT_NO_EXCEPTION); - RunUntilIdle(); - DCHECK(delegate); - P2PQuicNegotiatedParams params; - params.set_max_datagram_length(kMaxDatagramLengthBytes); - delegate->OnConnected(params); - RunUntilIdle(); - DCHECK_EQ("connected", quic_transport->state()); - if (delegate_out) { - *delegate_out = delegate; - } - return quic_transport; -} - -// Test that calling start() creates a P2PQuicTransport with the correct -// P2PQuicTransportConfig. The config should have: -// 1. The P2PQuicPacketTransport returned by the MockIceTransportAdapter. -// 2. Server mode configured since the ICE role is 'controlling'. -// 3. The certificates passed in the RTCQuicTransport constructor. -TEST_F(RTCQuicTransportTest, P2PQuicTransportConstructedByStart) { - V8TestingScope scope; - - auto quic_packet_transport = std::make_unique<MockP2PQuicPacketTransport>(); - auto* quic_packet_transport_ptr = quic_packet_transport.get(); - auto ice_transport_adapter_mock = std::make_unique<MockIceTransportAdapter>( - std::move(quic_packet_transport)); - Persistent<RTCIceTransport> ice_transport = - CreateIceTransport(scope, std::move(ice_transport_adapter_mock)); - ice_transport->start(CreateRemoteRTCIceParameters1(), "controlling", - ASSERT_NO_EXCEPTION); - - rtc::scoped_refptr<rtc::RTCCertificate> certificate = - rtc::RTCCertificateGenerator::GenerateCertificate(rtc::KeyParams::ECDSA(), - absl::nullopt); - auto mock_factory = std::make_unique<MockP2PQuicTransportFactory>(); - EXPECT_CALL(*mock_factory, CreateQuicTransport(_, _, _)) - .WillOnce(Invoke([quic_packet_transport_ptr, certificate]( - P2PQuicTransport::Delegate* delegate, - P2PQuicPacketTransport* packet_transport, - const P2PQuicTransportConfig& config) { - EXPECT_EQ(quic_packet_transport_ptr, packet_transport); - EXPECT_EQ(quic::Perspective::IS_SERVER, config.perspective); - EXPECT_THAT(config.certificates, ElementsAre(certificate)); - return std::make_unique<MockP2PQuicTransport>(); - })); - HeapVector<Member<RTCCertificate>> certificates; - certificates.push_back(MakeGarbageCollected<RTCCertificate>(certificate)); - Persistent<RTCQuicTransport> quic_transport = CreateQuicTransport( - scope, ice_transport, certificates, std::move(mock_factory)); - quic_transport->start(CreateRemoteRTCQuicParameters1(), ASSERT_NO_EXCEPTION); -} - -// Test that calling connect() creates a P2PQuicTransport with the correct -// P2PQuicTransportConfig. The config should have: -// 1. The P2PQuicPacketTransport returned by the MockIceTransportAdapter. -// 2. Client mode configured. -TEST_F(RTCQuicTransportTest, P2PQuicTransportConstructedByConnect) { - V8TestingScope scope; - - auto quic_packet_transport = std::make_unique<MockP2PQuicPacketTransport>(); - auto* quic_packet_transport_ptr = quic_packet_transport.get(); - auto ice_transport_adapter_mock = std::make_unique<MockIceTransportAdapter>( - std::move(quic_packet_transport)); - Persistent<RTCIceTransport> ice_transport = - CreateIceTransport(scope, std::move(ice_transport_adapter_mock)); - ice_transport->start(CreateRemoteRTCIceParameters1(), "controlling", - ASSERT_NO_EXCEPTION); - - auto mock_factory = std::make_unique<MockP2PQuicTransportFactory>(); - EXPECT_CALL(*mock_factory, CreateQuicTransport(_, _, _)) - .WillOnce(Invoke( - [quic_packet_transport_ptr](P2PQuicTransport::Delegate* delegate, - P2PQuicPacketTransport* packet_transport, - const P2PQuicTransportConfig& config) { - EXPECT_EQ(quic_packet_transport_ptr, packet_transport); - EXPECT_EQ(quic::Perspective::IS_CLIENT, config.perspective); - return std::make_unique<MockP2PQuicTransport>(); - })); - - Persistent<RTCQuicTransport> quic_transport = - CreateQuicTransport(scope, ice_transport, {}, std::move(mock_factory)); - quic_transport->connect(ASSERT_NO_EXCEPTION); -} - -// Test that calling listen() creates a P2PQuicTransport with the correct -// P2PQuicTransportConfig. The config should have: -// 1. The P2PQuicPacketTransport returned by the MockIceTransportAdapter. -// 2. Server mode configured. -TEST_F(RTCQuicTransportTest, P2PQuicTransportConstructedByListen) { - V8TestingScope scope; - - auto quic_packet_transport = std::make_unique<MockP2PQuicPacketTransport>(); - auto* quic_packet_transport_ptr = quic_packet_transport.get(); - auto ice_transport_adapter_mock = std::make_unique<MockIceTransportAdapter>( - std::move(quic_packet_transport)); - Persistent<RTCIceTransport> ice_transport = - CreateIceTransport(scope, std::move(ice_transport_adapter_mock)); - ice_transport->start(CreateRemoteRTCIceParameters1(), "controlling", - ASSERT_NO_EXCEPTION); - - auto mock_factory = std::make_unique<MockP2PQuicTransportFactory>(); - EXPECT_CALL(*mock_factory, CreateQuicTransport(_, _, _)) - .WillOnce(Invoke( - [quic_packet_transport_ptr](P2PQuicTransport::Delegate* delegate, - P2PQuicPacketTransport* packet_transport, - const P2PQuicTransportConfig& config) { - EXPECT_EQ(quic_packet_transport_ptr, packet_transport); - EXPECT_EQ(quic::Perspective::IS_SERVER, config.perspective); - return std::make_unique<MockP2PQuicTransport>(); - })); - - Persistent<RTCQuicTransport> quic_transport = - CreateQuicTransport(scope, ice_transport, {}, std::move(mock_factory)); - quic_transport->listen(DOMArrayBuffer::Create(kKey, kKeyLength), - ASSERT_NO_EXCEPTION); -} - -// Test that calling start() creates a P2PQuicTransport with client perspective -// if the RTCIceTransport role is 'controlled'. -TEST_F(RTCQuicTransportTest, P2PQuicTransportConstructedByStartClient) { - V8TestingScope scope; - - auto ice_transport_adapter_mock = std::make_unique<MockIceTransportAdapter>( - std::make_unique<MockP2PQuicPacketTransport>()); - Persistent<RTCIceTransport> ice_transport = - CreateIceTransport(scope, std::move(ice_transport_adapter_mock)); - ice_transport->start(CreateRemoteRTCIceParameters1(), "controlled", - ASSERT_NO_EXCEPTION); - - auto mock_factory = std::make_unique<MockP2PQuicTransportFactory>( - std::make_unique<MockP2PQuicTransport>()); - EXPECT_CALL(*mock_factory, CreateQuicTransport(_, _, _)) - .WillOnce(Invoke([](P2PQuicTransport::Delegate* delegate, - P2PQuicPacketTransport* packet_transport, - const P2PQuicTransportConfig& config) { - EXPECT_EQ(quic::Perspective::IS_CLIENT, config.perspective); - return std::make_unique<MockP2PQuicTransport>(); - })); - Persistent<RTCQuicTransport> quic_transport = - CreateQuicTransport(scope, ice_transport, GenerateLocalRTCCertificates(), - std::move(mock_factory)); - quic_transport->start(CreateRemoteRTCQuicParameters1(), ASSERT_NO_EXCEPTION); -} - -// Test that calling start() calls Start() on the P2PQuicTransport with the -// correct remote fingerprints. -TEST_F(RTCQuicTransportTest, StartPassesRemoteFingerprints) { - V8TestingScope scope; - - Persistent<RTCIceTransport> ice_transport = CreateIceTransport(scope); - ice_transport->start(CreateRemoteRTCIceParameters1(), "controlling", - ASSERT_NO_EXCEPTION); - - auto mock_transport = std::make_unique<MockP2PQuicTransport>(); - EXPECT_CALL(*mock_transport, MockStart(_)) - .WillOnce(Invoke([](const P2PQuicTransport::StartConfig& config) { - ASSERT_EQ(1u, config.remote_fingerprints.size()); - EXPECT_EQ(kRemoteFingerprintAlgorithm1, - config.remote_fingerprints[0]->algorithm); - EXPECT_EQ(kRemoteFingerprintValue1, - config.remote_fingerprints[0]->GetRfc4572Fingerprint()); - })); - Persistent<RTCQuicTransport> quic_transport = - CreateQuicTransport(scope, ice_transport, GenerateLocalRTCCertificates(), - std::move(mock_transport)); - quic_transport->start(CreateRemoteRTCQuicParameters1(), ASSERT_NO_EXCEPTION); -} - -// Test that calling start() with a started RTCIceTransport changes its state to -// connecting. -TEST_F(RTCQuicTransportTest, StartWithConnectedTransportChangesToConnecting) { - V8TestingScope scope; - - Persistent<RTCIceTransport> ice_transport = CreateIceTransport(scope); - ice_transport->start(CreateRemoteRTCIceParameters1(), "controlling", - ASSERT_NO_EXCEPTION); - - auto mock_transport = std::make_unique<MockP2PQuicTransport>(); - Persistent<RTCQuicTransport> quic_transport = - CreateQuicTransport(scope, ice_transport, GenerateLocalRTCCertificates(), - std::move(mock_transport)); - quic_transport->start(CreateRemoteRTCQuicParameters1(), ASSERT_NO_EXCEPTION); - EXPECT_EQ("connecting", quic_transport->state()); -} - -// Test that calling start() changes its state to connecting once -// RTCIceTransport starts. -TEST_F(RTCQuicTransportTest, StartChangesToConnectingWhenIceStarts) { - V8TestingScope scope; - - Persistent<RTCIceTransport> ice_transport = CreateIceTransport(scope); - - auto mock_transport = std::make_unique<MockP2PQuicTransport>(); - Persistent<RTCQuicTransport> quic_transport = - CreateQuicTransport(scope, ice_transport, GenerateLocalRTCCertificates(), - std::move(mock_transport)); - quic_transport->start(CreateRemoteRTCQuicParameters1(), ASSERT_NO_EXCEPTION); - EXPECT_EQ("new", quic_transport->state()); - - ice_transport->start(CreateRemoteRTCIceParameters1(), "controlling", - ASSERT_NO_EXCEPTION); - EXPECT_EQ("connecting", quic_transport->state()); -} - -// Test that calling start() twice throws a kInvalidStateError. -TEST_F(RTCQuicTransportTest, StartTwiceThrowsError) { - V8TestingScope scope; - - Persistent<RTCIceTransport> ice_transport = CreateIceTransport(scope); - ice_transport->start(CreateRemoteRTCIceParameters1(), "controlling", - ASSERT_NO_EXCEPTION); - - auto mock_transport = std::make_unique<MockP2PQuicTransport>(); - Persistent<RTCQuicTransport> quic_transport = - CreateQuicTransport(scope, ice_transport, GenerateLocalRTCCertificates(), - std::move(mock_transport)); - quic_transport->start(CreateRemoteRTCQuicParameters1(), ASSERT_NO_EXCEPTION); - - quic_transport->start(CreateRemoteRTCQuicParameters1(), - scope.GetExceptionState()); - EXPECT_EQ(DOMExceptionCode::kInvalidStateError, - scope.GetExceptionState().CodeAs<DOMExceptionCode>()); -} - -// Test that calling start() after connect() throws a kInvalidStateError. -TEST_F(RTCQuicTransportTest, StartAfterConnectThrowsError) { - V8TestingScope scope; - - Persistent<RTCIceTransport> ice_transport = CreateIceTransport(scope); - ice_transport->start(CreateRemoteRTCIceParameters1(), "controlling", - ASSERT_NO_EXCEPTION); - - auto mock_transport = std::make_unique<MockP2PQuicTransport>(); - Persistent<RTCQuicTransport> quic_transport = - CreateQuicTransport(scope, ice_transport, GenerateLocalRTCCertificates(), - std::move(mock_transport)); - quic_transport->connect(ASSERT_NO_EXCEPTION); - - quic_transport->start(CreateRemoteRTCQuicParameters1(), - scope.GetExceptionState()); - EXPECT_EQ(DOMExceptionCode::kInvalidStateError, - scope.GetExceptionState().CodeAs<DOMExceptionCode>()); -} - -// Test that calling start() after listen() throws a kInvalidStateError. -TEST_F(RTCQuicTransportTest, StartAfterListenThrowsError) { - V8TestingScope scope; - - Persistent<RTCIceTransport> ice_transport = CreateIceTransport(scope); - ice_transport->start(CreateRemoteRTCIceParameters1(), "controlling", - ASSERT_NO_EXCEPTION); - - auto mock_transport = std::make_unique<MockP2PQuicTransport>(); - Persistent<RTCQuicTransport> quic_transport = - CreateQuicTransport(scope, ice_transport, GenerateLocalRTCCertificates(), - std::move(mock_transport)); - quic_transport->listen(DOMArrayBuffer::Create(kKey, kKeyLength), - ASSERT_NO_EXCEPTION); - - quic_transport->start(CreateRemoteRTCQuicParameters1(), - scope.GetExceptionState()); - EXPECT_EQ(DOMExceptionCode::kInvalidStateError, - scope.GetExceptionState().CodeAs<DOMExceptionCode>()); -} - -// Test that calling start() after stop() throws a kInvalidStateError. -TEST_F(RTCQuicTransportTest, StartAfterStopThrowsError) { - V8TestingScope scope; - - Persistent<RTCIceTransport> ice_transport = CreateIceTransport(scope); - ice_transport->start(CreateRemoteRTCIceParameters1(), "controlling", - ASSERT_NO_EXCEPTION); - - auto mock_transport = std::make_unique<MockP2PQuicTransport>(); - Persistent<RTCQuicTransport> quic_transport = - CreateQuicTransport(scope, ice_transport, GenerateLocalRTCCertificates(), - std::move(mock_transport)); - - quic_transport->stop(); - quic_transport->start(CreateRemoteRTCQuicParameters1(), - scope.GetExceptionState()); - EXPECT_EQ(DOMExceptionCode::kInvalidStateError, - scope.GetExceptionState().CodeAs<DOMExceptionCode>()); -} - -// Test that calling start() after RTCIceTransport::stop() throws a -// kInvalidStateError. -TEST_F(RTCQuicTransportTest, StartAfterIceStopsThrowsError) { - V8TestingScope scope; - - Persistent<RTCIceTransport> ice_transport = CreateIceTransport(scope); - ice_transport->start(CreateRemoteRTCIceParameters1(), "controlling", - ASSERT_NO_EXCEPTION); - - auto mock_transport = std::make_unique<MockP2PQuicTransport>(); - Persistent<RTCQuicTransport> quic_transport = - CreateQuicTransport(scope, ice_transport, GenerateLocalRTCCertificates(), - std::move(mock_transport)); - - ice_transport->stop(); - quic_transport->start(CreateRemoteRTCQuicParameters1(), - scope.GetExceptionState()); - EXPECT_EQ(DOMExceptionCode::kInvalidStateError, - scope.GetExceptionState().CodeAs<DOMExceptionCode>()); -} - -// Test that calling connect() calls Start() on the P2PQuicTransport with the -// generated pre shared key from the local side. -TEST_F(RTCQuicTransportTest, ConnectPassesPreSharedKey) { - V8TestingScope scope; - - Persistent<RTCIceTransport> ice_transport = CreateIceTransport(scope); - ice_transport->start(CreateRemoteRTCIceParameters1(), "controlling", - ASSERT_NO_EXCEPTION); - - auto mock_transport = std::make_unique<MockP2PQuicTransport>(); - auto* mock_transport_ptr = mock_transport.get(); - Persistent<RTCQuicTransport> quic_transport = - CreateQuicTransport(scope, ice_transport, {}, std::move(mock_transport)); - DOMArrayBuffer* key = quic_transport->getKey(); - std::string pre_shared_key(static_cast<const char*>(key->Data()), - key->ByteLengthAsSizeT()); - - EXPECT_CALL(*mock_transport_ptr, MockStart(_)) - .WillOnce( - Invoke([pre_shared_key](const P2PQuicTransport::StartConfig& config) { - EXPECT_EQ(pre_shared_key, config.pre_shared_key); - })); - quic_transport->connect(ASSERT_NO_EXCEPTION); -} - -// Test that calling listen() calls Start() on the P2PQuicTransport with the -// correct given pre shared key from the remote side. -TEST_F(RTCQuicTransportTest, ListenPassesPreSharedKey) { - V8TestingScope scope; - - Persistent<RTCIceTransport> ice_transport = CreateIceTransport(scope); - ice_transport->start(CreateRemoteRTCIceParameters1(), "controlling", - ASSERT_NO_EXCEPTION); - auto mock_transport = std::make_unique<MockP2PQuicTransport>(); - auto* mock_transport_ptr = mock_transport.get(); - Persistent<RTCQuicTransport> quic_transport = - CreateQuicTransport(scope, ice_transport, {}, std::move(mock_transport)); - - std::string pre_shared_key = "foobar"; - EXPECT_CALL(*mock_transport_ptr, MockStart(_)) - .WillOnce( - Invoke([pre_shared_key](const P2PQuicTransport::StartConfig& config) { - EXPECT_EQ(pre_shared_key, config.pre_shared_key); - })); - - quic_transport->listen( - DOMArrayBuffer::Create(pre_shared_key.c_str(), pre_shared_key.length()), - ASSERT_NO_EXCEPTION); -} - -// Test that calling stop() deletes the underlying P2PQuicTransport. -TEST_F(RTCQuicTransportTest, StopCallsStopThenDeletesQuicTransportAdapter) { - V8TestingScope scope; - - Persistent<RTCIceTransport> ice_transport = CreateIceTransport(scope); - ice_transport->start(CreateRemoteRTCIceParameters1(), "controlling", - ASSERT_NO_EXCEPTION); - - bool mock_deleted = false; - auto mock_transport = std::make_unique<MockP2PQuicTransport>(); - EXPECT_CALL(*mock_transport, Stop()).Times(1); - EXPECT_CALL(*mock_transport, Die()).WillOnce(Assign(&mock_deleted, true)); - - Persistent<RTCQuicTransport> quic_transport = - CreateQuicTransport(scope, ice_transport, GenerateLocalRTCCertificates(), - std::move(mock_transport)); - quic_transport->start(CreateRemoteRTCQuicParameters1(), ASSERT_NO_EXCEPTION); - - quic_transport->stop(); - RunUntilIdle(); - - EXPECT_TRUE(mock_deleted); -} - -// Test that calling stop() on the underlying RTCIceTransport deletes the -// underlying P2PQuicTransport. -TEST_F(RTCQuicTransportTest, RTCIceTransportStopDeletesP2PQuicTransport) { - V8TestingScope scope; - - Persistent<RTCIceTransport> ice_transport = CreateIceTransport(scope); - ice_transport->start(CreateRemoteRTCIceParameters1(), "controlling", - ASSERT_NO_EXCEPTION); - - bool mock_deleted = false; - auto mock_transport = std::make_unique<MockP2PQuicTransport>(); - EXPECT_CALL(*mock_transport, Die()).WillOnce(Assign(&mock_deleted, true)); - - Persistent<RTCQuicTransport> quic_transport = - CreateQuicTransport(scope, ice_transport, GenerateLocalRTCCertificates(), - std::move(mock_transport)); - quic_transport->start(CreateRemoteRTCQuicParameters1(), ASSERT_NO_EXCEPTION); - - ice_transport->stop(); - RunUntilIdle(); - - EXPECT_TRUE(mock_deleted); -} - -// Test that the P2PQuicTransport is deleted and the RTCQuicTransport goes to -// the "failed" state when the QUIC connection fails. -TEST_F(RTCQuicTransportTest, - ConnectionFailedBecomesClosedAndDeletesP2PQuicTransport) { - V8TestingScope scope; - - bool mock_deleted = false; - auto mock_transport = std::make_unique<MockP2PQuicTransport>(); - EXPECT_CALL(*mock_transport, Die()).WillOnce(Assign(&mock_deleted, true)); - - P2PQuicTransport::Delegate* delegate = nullptr; - Persistent<RTCQuicTransport> quic_transport = - CreateConnectedQuicTransport(scope, std::move(mock_transport), &delegate); - DCHECK(delegate); - delegate->OnConnectionFailed("test_failure", /*from_remote=*/false); - RunUntilIdle(); - - EXPECT_TRUE(mock_deleted); - EXPECT_EQ("failed", quic_transport->state()); -} - -// Test that after the connection fails, stop() will change the state -// of the transport to "closed". -TEST_F(RTCQuicTransportTest, StopAfterConnectionFailed) { - V8TestingScope scope; - - P2PQuicTransport::Delegate* delegate = nullptr; - Persistent<RTCQuicTransport> quic_transport = CreateConnectedQuicTransport( - scope, std::make_unique<MockP2PQuicTransport>(), &delegate); - DCHECK(delegate); - delegate->OnConnectionFailed("test_failure", /*from_remote=*/false); - RunUntilIdle(); - - EXPECT_EQ("failed", quic_transport->state()); - - quic_transport->stop(); - EXPECT_EQ("closed", quic_transport->state()); -} - -// Test that the P2PQuicTransport is deleted when the underlying RTCIceTransport -// is ContextDestroyed. -TEST_F(RTCQuicTransportTest, - RTCIceTransportContextDestroyedDeletesP2PQuicTransport) { - bool mock_deleted = false; - { - V8TestingScope scope; - - Persistent<RTCIceTransport> ice_transport = CreateIceTransport(scope); - ice_transport->start(CreateRemoteRTCIceParameters1(), "controlling", - ASSERT_NO_EXCEPTION); - - auto mock_transport = std::make_unique<MockP2PQuicTransport>(); - EXPECT_CALL(*mock_transport, Die()).WillOnce(Assign(&mock_deleted, true)); - - Persistent<RTCQuicTransport> quic_transport = CreateQuicTransport( - scope, ice_transport, GenerateLocalRTCCertificates(), - std::move(mock_transport)); - quic_transport->start(CreateRemoteRTCQuicParameters1(), - ASSERT_NO_EXCEPTION); - } // ContextDestroyed when V8TestingScope goes out of scope. - - RunUntilIdle(); - - EXPECT_TRUE(mock_deleted); -} - -// Test that the certificate passed to RTCQuicTransport is the same -// returned by getCertificates(). -TEST_F(RTCQuicTransportTest, GetCertificatesReturnsGivenCertificates) { - V8TestingScope scope; - - Persistent<RTCIceTransport> ice_transport = CreateIceTransport(scope); - - auto mock_transport = std::make_unique<MockP2PQuicTransport>(); - auto certificates = GenerateLocalRTCCertificates(); - Persistent<RTCQuicTransport> quic_transport = CreateQuicTransport( - scope, ice_transport, certificates, std::move(mock_transport)); - auto returned_certificates = quic_transport->getCertificates(); - - EXPECT_EQ(certificates[0], returned_certificates[0]); -} - -// Test that the fingerprint returned by getLocalParameters() is -// the fingerprint of the certificate passed to the RTCQuicTransport. -TEST_F(RTCQuicTransportTest, - GetLocalParametersReturnsGivenCertificatesFingerprints) { - V8TestingScope scope; - - Persistent<RTCIceTransport> ice_transport = CreateIceTransport(scope); - - auto mock_transport = std::make_unique<MockP2PQuicTransport>(); - auto certificates = GenerateLocalRTCCertificates(); - auto fingerprints = certificates[0]->getFingerprints(); - Persistent<RTCQuicTransport> quic_transport = CreateQuicTransport( - scope, ice_transport, certificates, std::move(mock_transport)); - auto returned_fingerprints = - quic_transport->getLocalParameters()->fingerprints(); - - EXPECT_EQ(1u, returned_fingerprints.size()); - EXPECT_EQ(fingerprints.size(), returned_fingerprints.size()); - EXPECT_EQ(fingerprints[0]->value(), returned_fingerprints[0]->value()); - EXPECT_EQ(fingerprints[0]->algorithm(), - returned_fingerprints[0]->algorithm()); -} - -TEST_F(RTCQuicTransportTest, ExpiredCertificateThrowsError) { - V8TestingScope scope; - - Persistent<RTCIceTransport> ice_transport = CreateIceTransport(scope); - auto mock_factory = std::make_unique<MockP2PQuicTransportFactory>(); - HeapVector<Member<RTCCertificate>> certificates; - certificates.push_back(MakeGarbageCollected<RTCCertificate>( - rtc::RTCCertificateGenerator::GenerateCertificate(rtc::KeyParams::ECDSA(), - /*expires_ms=*/0))); - RTCQuicTransport::Create(scope.GetExecutionContext(), ice_transport, - certificates, scope.GetExceptionState(), - std::move(mock_factory)); - EXPECT_EQ(ESErrorType::kTypeError, - scope.GetExceptionState().CodeAs<ESErrorType>()); -} - -// Test that the key returned has at least 128 bits of entropy as required by -// QUIC. -TEST_F(RTCQuicTransportTest, GetKeyReturnsValidKey) { - V8TestingScope scope; - - Persistent<RTCIceTransport> ice_transport = CreateIceTransport(scope); - auto mock_transport = std::make_unique<MockP2PQuicTransport>(); - Persistent<RTCQuicTransport> quic_transport = - CreateQuicTransport(scope, ice_transport, {}, std::move(mock_transport)); - auto* key = quic_transport->getKey(); - - EXPECT_GE(key->ByteLengthAsSizeT(), 16u); -} - -// Test that stats are converted correctly to the RTCQuicTransportStats -// dictionary. -TEST_F(RTCQuicTransportTest, OnStatsConvertsRTCStatsDictionary) { - V8TestingScope scope; - - auto mock_transport = std::make_unique<MockP2PQuicTransport>(); - MockP2PQuicTransport* mock_transport_ptr = mock_transport.get(); - P2PQuicTransport::Delegate* delegate = nullptr; - Persistent<RTCQuicTransport> quic_transport = - CreateConnectedQuicTransport(scope, std::move(mock_transport), &delegate); - DCHECK(delegate); - - // Create some dummy values. - P2PQuicTransportStats stats; - stats.bytes_sent = 0; - stats.packets_sent = 1; - stats.stream_bytes_sent = 2; - stats.stream_bytes_received = 3; - stats.num_outgoing_streams_created = 4; - stats.num_incoming_streams_created = 5; - stats.bytes_received = 6; - stats.packets_received = 7; - stats.packets_processed = 8; - stats.bytes_retransmitted = 9; - stats.packets_retransmitted = 10; - stats.packets_lost = 11; - stats.packets_dropped = 12; - stats.crypto_retransmit_count = 13; - stats.min_rtt_us = 14; - stats.srtt_us = 15; - stats.max_packet_size = 16; - stats.max_received_packet_size = 17; - stats.estimated_bandwidth_bps = 18; - stats.packets_reordered = 19; - stats.blocked_frames_received = 20; - stats.blocked_frames_sent = 21; - stats.connectivity_probing_packets_received = 22; - stats.num_datagrams_lost = 23; - EXPECT_CALL(*mock_transport_ptr, GetStats()).WillOnce(Return(stats)); - ScriptPromise stats_promise = - quic_transport->getStats(scope.GetScriptState(), ASSERT_NO_EXCEPTION); - - RunUntilIdle(); - - ASSERT_EQ(v8::Promise::kFulfilled, - stats_promise.V8Value().As<v8::Promise>()->State()); - - RTCQuicTransportStats* rtc_quic_stats = - NativeValueTraits<RTCQuicTransportStats>::NativeValue( - scope.GetIsolate(), - stats_promise.V8Value().As<v8::Promise>()->Result(), - ASSERT_NO_EXCEPTION); - ASSERT_TRUE(rtc_quic_stats->hasTimestamp()); - EXPECT_EQ(ConvertTimeTicksToDOMHighResTimeStamp(stats.timestamp), - rtc_quic_stats->timestamp()); - ASSERT_TRUE(rtc_quic_stats->hasBytesSent()); - EXPECT_EQ(stats.bytes_sent, rtc_quic_stats->bytesSent()); - ASSERT_TRUE(rtc_quic_stats->hasPacketsSent()); - EXPECT_EQ(stats.packets_sent, rtc_quic_stats->packetsSent()); - ASSERT_TRUE(rtc_quic_stats->hasStreamBytesSent()); - EXPECT_EQ(stats.stream_bytes_sent, rtc_quic_stats->streamBytesSent()); - ASSERT_TRUE(rtc_quic_stats->hasStreamBytesSent()); - EXPECT_EQ(stats.stream_bytes_received, rtc_quic_stats->streamBytesReceived()); - ASSERT_TRUE(rtc_quic_stats->hasNumOutgoingStreamsCreated()); - EXPECT_EQ(stats.num_outgoing_streams_created, - rtc_quic_stats->numOutgoingStreamsCreated()); - ASSERT_TRUE(rtc_quic_stats->hasNumIncomingStreamsCreated()); - EXPECT_EQ(stats.num_incoming_streams_created, - rtc_quic_stats->numIncomingStreamsCreated()); - ASSERT_TRUE(rtc_quic_stats->hasBytesReceived()); - EXPECT_EQ(stats.bytes_received, rtc_quic_stats->bytesReceived()); - ASSERT_TRUE(rtc_quic_stats->hasPacketsReceived()); - EXPECT_EQ(stats.packets_received, rtc_quic_stats->packetsReceived()); - ASSERT_TRUE(rtc_quic_stats->hasPacketsProcessed()); - EXPECT_EQ(stats.packets_processed, rtc_quic_stats->packetsProcessed()); - ASSERT_TRUE(rtc_quic_stats->hasBytesRetransmitted()); - EXPECT_EQ(stats.bytes_retransmitted, rtc_quic_stats->bytesRetransmitted()); - ASSERT_TRUE(rtc_quic_stats->hasPacketsRetransmitted()); - EXPECT_EQ(stats.packets_retransmitted, - rtc_quic_stats->packetsRetransmitted()); - ASSERT_TRUE(rtc_quic_stats->hasPacketsLost()); - EXPECT_EQ(stats.packets_lost, rtc_quic_stats->packetsLost()); - ASSERT_TRUE(rtc_quic_stats->hasPacketsDropped()); - EXPECT_EQ(stats.packets_dropped, rtc_quic_stats->packetsDropped()); - ASSERT_TRUE(rtc_quic_stats->hasCryptoRetransmitCount()); - EXPECT_EQ(stats.crypto_retransmit_count, - rtc_quic_stats->cryptoRetransmitCount()); - ASSERT_TRUE(rtc_quic_stats->hasMinRttUs()); - EXPECT_EQ(stats.min_rtt_us, rtc_quic_stats->minRttUs()); - ASSERT_TRUE(rtc_quic_stats->hasSmoothedRttUs()); - EXPECT_EQ(stats.srtt_us, rtc_quic_stats->smoothedRttUs()); - ASSERT_TRUE(rtc_quic_stats->hasMaxPacketSize()); - EXPECT_EQ(stats.max_packet_size, rtc_quic_stats->maxPacketSize()); - ASSERT_TRUE(rtc_quic_stats->hasMaxReceivedPacketSize()); - EXPECT_EQ(stats.max_received_packet_size, - rtc_quic_stats->maxReceivedPacketSize()); - ASSERT_TRUE(rtc_quic_stats->hasEstimatedBandwidthBps()); - EXPECT_EQ(stats.estimated_bandwidth_bps, - rtc_quic_stats->estimatedBandwidthBps()); - ASSERT_TRUE(rtc_quic_stats->hasPacketsReordered()); - EXPECT_EQ(stats.packets_reordered, rtc_quic_stats->packetsReordered()); - ASSERT_TRUE(rtc_quic_stats->hasBlockedFramesReceived()); - EXPECT_EQ(stats.blocked_frames_received, - rtc_quic_stats->blockedFramesReceived()); - ASSERT_TRUE(rtc_quic_stats->hasBlockedFramesSent()); - EXPECT_EQ(stats.blocked_frames_sent, rtc_quic_stats->blockedFramesSent()); - ASSERT_TRUE(rtc_quic_stats->hasConnectivityProbingPacketsReceived()); - EXPECT_EQ(stats.connectivity_probing_packets_received, - rtc_quic_stats->connectivityProbingPacketsReceived()); - ASSERT_TRUE(rtc_quic_stats->hasNumDatagramsLost()); - EXPECT_EQ(stats.num_datagrams_lost, rtc_quic_stats->numDatagramsLost()); -} - -// Test that all promises are rejected if the connection closes before -// the OnStats callback is called. -TEST_F(RTCQuicTransportTest, FailedConnectionRejectsStatsPromises) { - V8TestingScope scope; - - auto mock_transport = std::make_unique<MockP2PQuicTransport>(); - P2PQuicTransport::Delegate* delegate = nullptr; - Persistent<RTCQuicTransport> quic_transport = - CreateConnectedQuicTransport(scope, std::move(mock_transport), &delegate); - DCHECK(delegate); - - ScriptPromise promise_1 = - quic_transport->getStats(scope.GetScriptState(), ASSERT_NO_EXCEPTION); - ScriptPromise promise_2 = - quic_transport->getStats(scope.GetScriptState(), ASSERT_NO_EXCEPTION); - delegate->OnConnectionFailed("test_failure", /*from_remote=*/false); - - RunUntilIdle(); - - EXPECT_EQ(v8::Promise::kRejected, - promise_1.V8Value().As<v8::Promise>()->State()); - EXPECT_EQ(v8::Promise::kRejected, - promise_2.V8Value().As<v8::Promise>()->State()); -} - -// Test that all promises are rejected if the remote side closes before -// the OnStats callback is called. -TEST_F(RTCQuicTransportTest, RemoteStopRejectsStatsPromises) { - V8TestingScope scope; - - auto mock_transport = std::make_unique<MockP2PQuicTransport>(); - P2PQuicTransport::Delegate* delegate = nullptr; - Persistent<RTCQuicTransport> quic_transport = - CreateConnectedQuicTransport(scope, std::move(mock_transport), &delegate); - DCHECK(delegate); - - ScriptPromise promise_1 = - quic_transport->getStats(scope.GetScriptState(), ASSERT_NO_EXCEPTION); - ScriptPromise promise_2 = - quic_transport->getStats(scope.GetScriptState(), ASSERT_NO_EXCEPTION); - delegate->OnRemoteStopped(); - - RunUntilIdle(); - - EXPECT_EQ(v8::Promise::kRejected, - promise_1.V8Value().As<v8::Promise>()->State()); - EXPECT_EQ(v8::Promise::kRejected, - promise_2.V8Value().As<v8::Promise>()->State()); -} - -// Test that calling getStats() after going to the "failed" state -// raises a kInvalidStateError. -TEST_F(RTCQuicTransportTest, FailedStateGetStatsRaisesInvalidStateError) { - V8TestingScope scope; - - auto mock_transport = std::make_unique<MockP2PQuicTransport>(); - P2PQuicTransport::Delegate* delegate = nullptr; - Persistent<RTCQuicTransport> quic_transport = - CreateConnectedQuicTransport(scope, std::move(mock_transport), &delegate); - DCHECK(delegate); - - delegate->OnRemoteStopped(); - RunUntilIdle(); - - quic_transport->getStats(scope.GetScriptState(), scope.GetExceptionState()); - EXPECT_EQ(DOMExceptionCode::kInvalidStateError, - scope.GetExceptionState().CodeAs<DOMExceptionCode>()); -} - -// Test that the max datagram length is updated properly when the transport -// becomes connected. -TEST_F(RTCQuicTransportTest, MaxDatagramLengthComesFromNegotiatedParams) { - V8TestingScope scope; - Persistent<RTCIceTransport> ice_transport = CreateIceTransport(scope); - ice_transport->start(CreateRemoteRTCIceParameters1(), "controlling", - ASSERT_NO_EXCEPTION); - P2PQuicTransport::Delegate* delegate = nullptr; - auto mock_transport = std::make_unique<MockP2PQuicTransport>(); - Persistent<RTCQuicTransport> quic_transport = - CreateQuicTransport(scope, ice_transport, GenerateLocalRTCCertificates(), - std::move(mock_transport), &delegate); - quic_transport->start(CreateRemoteRTCQuicParameters1(), ASSERT_NO_EXCEPTION); - RunUntilIdle(); - P2PQuicNegotiatedParams params; - uint16_t max_datagram_length = 10; - params.set_max_datagram_length(max_datagram_length); - delegate->OnConnected(params); - RunUntilIdle(); - ASSERT_EQ("connected", quic_transport->state()); - ASSERT_TRUE(quic_transport->maxDatagramLength().has_value()); - EXPECT_EQ(max_datagram_length, quic_transport->maxDatagramLength().value()); -} - -// Test that sending a datagram after the buffer is full will raise a -// kInvalidStateError. -TEST_F(RTCQuicTransportTest, SendingWhenNotReadyRaisesInvalidStateError) { - V8TestingScope scope; - - P2PQuicTransport::Delegate* delegate = nullptr; - Persistent<RTCQuicTransport> quic_transport = - CreateConnectedQuicTransport(scope, &delegate); - DCHECK(delegate); - - FillDatagramBuffer(quic_transport); - RunUntilIdle(); - - quic_transport->sendDatagram( - DOMArrayBuffer::Create(kDatagram, kDatagramLength), - scope.GetExceptionState()); - EXPECT_EQ(DOMExceptionCode::kInvalidStateError, - scope.GetExceptionState().CodeAs<DOMExceptionCode>()); -} - -// Test that calling readyToSend before the last promise has resolved raises a -// kInvalidStateError. -TEST_F(RTCQuicTransportTest, ReadyToSendTwiceRaisesInvalidStateError) { - V8TestingScope scope; - - P2PQuicTransport::Delegate* delegate = nullptr; - Persistent<RTCQuicTransport> quic_transport = - CreateConnectedQuicTransport(scope, &delegate); - DCHECK(delegate); - - FillDatagramBuffer(quic_transport); - RunUntilIdle(); - - quic_transport->readyToSendDatagram(scope.GetScriptState(), - ASSERT_NO_EXCEPTION); - quic_transport->readyToSendDatagram(scope.GetScriptState(), - scope.GetExceptionState()); - EXPECT_EQ(DOMExceptionCode::kInvalidStateError, - scope.GetExceptionState().CodeAs<DOMExceptionCode>()); -} - -// Test that readyToSend promise will be pending until transport is no longer -// congestion control blocked. -TEST_F(RTCQuicTransportTest, ReadyToSendPromiseResolvesWhenReady) { - V8TestingScope scope; - - P2PQuicTransport::Delegate* delegate = nullptr; - Persistent<RTCQuicTransport> quic_transport = - CreateConnectedQuicTransport(scope, &delegate); - DCHECK(delegate); - FillDatagramBuffer(quic_transport); - RunUntilIdle(); - - ScriptPromise promise = quic_transport->readyToSendDatagram( - scope.GetScriptState(), ASSERT_NO_EXCEPTION); - EXPECT_EQ(v8::Promise::kPending, - promise.V8Value().As<v8::Promise>()->State()); - - delegate->OnDatagramSent(); - RunUntilIdle(); - EXPECT_EQ(v8::Promise::kFulfilled, - promise.V8Value().As<v8::Promise>()->State()); -} - -// Test that the pending readyToSend proimise will be rejected if stop() is -// called. -TEST_F(RTCQuicTransportTest, ReadyToSendPromiseRejectedWithStop) { - V8TestingScope scope; - - P2PQuicTransport::Delegate* delegate = nullptr; - Persistent<RTCQuicTransport> quic_transport = - CreateConnectedQuicTransport(scope, &delegate); - DCHECK(delegate); - FillDatagramBuffer(quic_transport); - RunUntilIdle(); - - ScriptPromise promise = quic_transport->readyToSendDatagram( - scope.GetScriptState(), ASSERT_NO_EXCEPTION); - EXPECT_EQ(v8::Promise::kPending, - promise.V8Value().As<v8::Promise>()->State()); - quic_transport->stop(); - RunUntilIdle(); - - EXPECT_EQ(v8::Promise::kRejected, - promise.V8Value().As<v8::Promise>()->State()); -} - -// Test that the pending readyToSend proimise will be rejected if stop() is -// called on the RTCIceTransport. -TEST_F(RTCQuicTransportTest, ReadyToSendPromiseRejectedWithIceStop) { - V8TestingScope scope; - - P2PQuicTransport::Delegate* delegate = nullptr; - Persistent<RTCQuicTransport> quic_transport = - CreateConnectedQuicTransport(scope, &delegate); - DCHECK(delegate); - FillDatagramBuffer(quic_transport); - RunUntilIdle(); - - ScriptPromise promise = quic_transport->readyToSendDatagram( - scope.GetScriptState(), ASSERT_NO_EXCEPTION); - EXPECT_EQ(v8::Promise::kPending, - promise.V8Value().As<v8::Promise>()->State()); - quic_transport->transport()->stop(); - RunUntilIdle(); - - EXPECT_EQ(v8::Promise::kRejected, - promise.V8Value().As<v8::Promise>()->State()); -} - -// Test that the pending readyToSend proimise will be rejected if connection -// fails. -TEST_F(RTCQuicTransportTest, ReadyToSendPromiseRejectedWithFailedConnection) { - V8TestingScope scope; - - P2PQuicTransport::Delegate* delegate = nullptr; - Persistent<RTCQuicTransport> quic_transport = - CreateConnectedQuicTransport(scope, &delegate); - DCHECK(delegate); - FillDatagramBuffer(quic_transport); - RunUntilIdle(); - - ScriptPromise promise = quic_transport->readyToSendDatagram( - scope.GetScriptState(), ASSERT_NO_EXCEPTION); - EXPECT_EQ(v8::Promise::kPending, - promise.V8Value().As<v8::Promise>()->State()); - delegate->OnConnectionFailed("test_failure", /*from_remote=*/false); - RunUntilIdle(); - - EXPECT_EQ(v8::Promise::kRejected, - promise.V8Value().As<v8::Promise>()->State()); -} - -// Test that the pending readyToSend proimise will be rejected if the remote -// side stops. -TEST_F(RTCQuicTransportTest, ReadyToSendPromiseRejectedWithRemoteStop) { - V8TestingScope scope; - - P2PQuicTransport::Delegate* delegate = nullptr; - Persistent<RTCQuicTransport> quic_transport = - CreateConnectedQuicTransport(scope, &delegate); - DCHECK(delegate); - FillDatagramBuffer(quic_transport); - RunUntilIdle(); - - ScriptPromise promise = quic_transport->readyToSendDatagram( - scope.GetScriptState(), ASSERT_NO_EXCEPTION); - EXPECT_EQ(v8::Promise::kPending, - promise.V8Value().As<v8::Promise>()->State()); - delegate->OnRemoteStopped(); - RunUntilIdle(); - - EXPECT_EQ(v8::Promise::kRejected, - promise.V8Value().As<v8::Promise>()->State()); -} - -// Test that the pending receiveDatagrams proimise will be rejected if -// connection fails. -TEST_F(RTCQuicTransportTest, - ReceiveDatagramsPromiseRejectedWithFailedConnection) { - V8TestingScope scope; - - P2PQuicTransport::Delegate* delegate = nullptr; - Persistent<RTCQuicTransport> quic_transport = - CreateConnectedQuicTransport(scope, &delegate); - DCHECK(delegate); - ScriptPromise promise = quic_transport->receiveDatagrams( - scope.GetScriptState(), ASSERT_NO_EXCEPTION); - EXPECT_EQ(v8::Promise::kPending, - promise.V8Value().As<v8::Promise>()->State()); - delegate->OnConnectionFailed("test_failure", /*from_remote=*/false); - RunUntilIdle(); - - EXPECT_EQ(v8::Promise::kRejected, - promise.V8Value().As<v8::Promise>()->State()); -} - -// Test that the pending receiveDatagrams proimise will be rejected if -// connection fails. -TEST_F(RTCQuicTransportTest, ReceiveDatagramsPromiseRejectedWithRemoteStop) { - V8TestingScope scope; - - P2PQuicTransport::Delegate* delegate = nullptr; - Persistent<RTCQuicTransport> quic_transport = - CreateConnectedQuicTransport(scope, &delegate); - DCHECK(delegate); - - ScriptPromise promise = quic_transport->receiveDatagrams( - scope.GetScriptState(), ASSERT_NO_EXCEPTION); - EXPECT_EQ(v8::Promise::kPending, - promise.V8Value().As<v8::Promise>()->State()); - delegate->OnRemoteStopped(); - RunUntilIdle(); - - EXPECT_EQ(v8::Promise::kRejected, - promise.V8Value().As<v8::Promise>()->State()); -} - -// Test that calling receiveDatagrams before the last promise has resolved -// raises a kInvalidStateError. -TEST_F(RTCQuicTransportTest, ReceiveDatagramsTwiceRaisesInvalidStateError) { - V8TestingScope scope; - - P2PQuicTransport::Delegate* delegate = nullptr; - Persistent<RTCQuicTransport> quic_transport = - CreateConnectedQuicTransport(scope, &delegate); - DCHECK(delegate); - - quic_transport->receiveDatagrams(scope.GetScriptState(), ASSERT_NO_EXCEPTION); - quic_transport->receiveDatagrams(scope.GetScriptState(), - scope.GetExceptionState()); - EXPECT_EQ(DOMExceptionCode::kInvalidStateError, - scope.GetExceptionState().CodeAs<DOMExceptionCode>()); -} - -// Test that if datagrams are buffered before asking for a receiveDatagrams -// promise, that calling receiveDatagrams will return a promise immediately -// resolved with buffered datagrams. -TEST_F(RTCQuicTransportTest, ReceiveBufferedDatagrams) { - V8TestingScope scope; - - P2PQuicTransport::Delegate* delegate = nullptr; - Persistent<RTCQuicTransport> quic_transport = - CreateConnectedQuicTransport(scope, &delegate); - DCHECK(delegate); - - delegate->OnDatagramReceived({1, 2, 3}); - delegate->OnDatagramReceived({4, 5, 6}); - delegate->OnDatagramReceived({7, 8, 9}); - RunUntilIdle(); - - ScriptPromise promise = quic_transport->receiveDatagrams( - scope.GetScriptState(), ASSERT_NO_EXCEPTION); - EXPECT_EQ(v8::Promise::kFulfilled, - promise.V8Value().As<v8::Promise>()->State()); - HeapVector<Member<DOMArrayBuffer>> received_datagrams = - NativeValueTraits<IDLSequence<DOMArrayBuffer>>::NativeValue( - scope.GetIsolate(), promise.V8Value().As<v8::Promise>()->Result(), - ASSERT_NO_EXCEPTION); - - ASSERT_EQ(3u, received_datagrams.size()); - EXPECT_THAT(SpanFromDOMArrayBuffer(received_datagrams[0]), - ElementsAre(1, 2, 3)); - EXPECT_THAT(SpanFromDOMArrayBuffer(received_datagrams[1]), - ElementsAre(4, 5, 6)); - EXPECT_THAT(SpanFromDOMArrayBuffer(received_datagrams[2]), - ElementsAre(7, 8, 9)); -} - -// Test that if datagrams are dropped once we have buffered the max amount. -TEST_F(RTCQuicTransportTest, ReceiveBufferedDatagramsLost) { - V8TestingScope scope; - - auto mock_transport = std::make_unique<MockP2PQuicTransport>(); - MockP2PQuicTransport* mock_transport_ptr = mock_transport.get(); - P2PQuicTransport::Delegate* delegate = nullptr; - Persistent<RTCQuicTransport> quic_transport = - CreateConnectedQuicTransport(scope, std::move(mock_transport), &delegate); - DCHECK(delegate); - - size_t num_dropped_datagrams = 5; - size_t num_received_datagrams = - kMaxBufferedRecvDatagrams + num_dropped_datagrams; - for (size_t i = 0; i < num_received_datagrams; ++i) { - delegate->OnDatagramReceived({1}); - } - RunUntilIdle(); - - ScriptPromise received_datagrams_promise = quic_transport->receiveDatagrams( - scope.GetScriptState(), ASSERT_NO_EXCEPTION); - ASSERT_EQ(v8::Promise::kFulfilled, - received_datagrams_promise.V8Value().As<v8::Promise>()->State()); - HeapVector<Member<DOMArrayBuffer>> received_datagrams = - NativeValueTraits<IDLSequence<DOMArrayBuffer>>::NativeValue( - scope.GetIsolate(), - received_datagrams_promise.V8Value().As<v8::Promise>()->Result(), - ASSERT_NO_EXCEPTION); - - EXPECT_CALL(*mock_transport_ptr, GetStats()) - .WillOnce(Return(P2PQuicTransportStats())); - ScriptPromise stats_promise = - quic_transport->getStats(scope.GetScriptState(), ASSERT_NO_EXCEPTION); - RunUntilIdle(); - ASSERT_EQ(v8::Promise::kFulfilled, - stats_promise.V8Value().As<v8::Promise>()->State()); - - RTCQuicTransportStats* rtc_quic_stats = - NativeValueTraits<RTCQuicTransportStats>::NativeValue( - scope.GetIsolate(), - stats_promise.V8Value().As<v8::Promise>()->Result(), - ASSERT_NO_EXCEPTION); - - EXPECT_EQ(kMaxBufferedRecvDatagrams, received_datagrams.size()); - ASSERT_TRUE(rtc_quic_stats->hasNumReceivedDatagramsDropped()); - EXPECT_EQ(num_dropped_datagrams, - rtc_quic_stats->numReceivedDatagramsDropped()); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport_test.h b/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport_test.h deleted file mode 100644 index 191e299d..0000000 --- a/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport_test.h +++ /dev/null
@@ -1,52 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LQUICNSE file. - -#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_RTC_QUIC_TRANSPORT_TEST_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_RTC_QUIC_TRANSPORT_TEST_H_ - -#include "third_party/blink/renderer/modules/peerconnection/adapters/test/mock_p2p_quic_transport.h" -#include "third_party/blink/renderer/modules/peerconnection/adapters/test/mock_p2p_quic_transport_factory.h" -#include "third_party/blink/renderer/modules/peerconnection/rtc_certificate.h" -#include "third_party/blink/renderer/modules/peerconnection/rtc_ice_transport_test.h" -#include "third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.h" - -namespace blink { - -class V8TestingScope; - -class RTCQuicTransportTest : public RTCIceTransportTest { - public: - // Construct a new RTCQuicTransport with the given RTCIceTransport, - // certificates, and mock P2PQuicTransport. - // |delegate_out|, if non-null, will be populated once the P2PQuicTransport is - // constructed on the worker thread. - RTCQuicTransport* CreateQuicTransport( - V8TestingScope& scope, - RTCIceTransport* ice_transport, - const HeapVector<Member<RTCCertificate>>& certificates, - std::unique_ptr<MockP2PQuicTransport> mock_transport, - P2PQuicTransport::Delegate** delegate_out = nullptr); - - // Construct a new RTCQuicTransport with the given RTCIceTransport, - // certificates, and mock P2PQuicTransportFactory. - RTCQuicTransport* CreateQuicTransport( - V8TestingScope& scope, - RTCIceTransport* ice_transport, - const HeapVector<Member<RTCCertificate>>& certificates, - std::unique_ptr<MockP2PQuicTransportFactory> mock_factory); - - // Construct a new RTCQuicTransport and RTCIceTransport and call start() on - // both objects. - RTCQuicTransport* CreateConnectedQuicTransport( - V8TestingScope& scope, - P2PQuicTransport::Delegate** delegate_out = nullptr); - RTCQuicTransport* CreateConnectedQuicTransport( - V8TestingScope& scope, - std::unique_ptr<MockP2PQuicTransport> mock_transport, - P2PQuicTransport::Delegate** delegate_out = nullptr); -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_RTC_QUIC_TRANSPORT_TEST_H_
diff --git a/third_party/blink/renderer/modules/plugins/navigator_plugins.cc b/third_party/blink/renderer/modules/plugins/navigator_plugins.cc index c1b446b..fdd8d03 100644 --- a/third_party/blink/renderer/modules/plugins/navigator_plugins.cc +++ b/third_party/blink/renderer/modules/plugins/navigator_plugins.cc
@@ -10,6 +10,7 @@ #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/navigator.h" #include "third_party/blink/renderer/core/frame/settings.h" +#include "third_party/blink/renderer/modules/plugins/dom_mime_type.h" #include "third_party/blink/renderer/modules/plugins/dom_mime_type_array.h" #include "third_party/blink/renderer/modules/plugins/dom_plugin_array.h" #include "third_party/blink/renderer/platform/privacy_budget/identifiability_digest_helpers.h" @@ -91,11 +92,40 @@ } DOMMimeTypeArray* NavigatorPlugins::mimeTypes(LocalFrame* frame) const { - if (!mime_types_) + if (!mime_types_) { mime_types_ = MakeGarbageCollected<DOMMimeTypeArray>(frame); + RecordMimeTypes(frame); + } return mime_types_.Get(); } +void NavigatorPlugins::RecordMimeTypes(LocalFrame* frame) const { + constexpr IdentifiableSurface surface = IdentifiableSurface::FromTypeAndToken( + IdentifiableSurface::Type::kWebFeature, WebFeature::kNavigatorMimeTypes); + if (!IdentifiabilityStudySettings::Get()->IsSurfaceAllowed(surface) || !frame) + return; + Document* document = frame->GetDocument(); + if (!document) + return; + IdentifiableTokenBuilder builder; + for (unsigned i = 0; i < mime_types_->length(); i++) { + DOMMimeType* mime_type = mime_types_->item(i); + builder.AddToken(IdentifiabilityBenignStringToken(mime_type->type())); + builder.AddToken( + IdentifiabilityBenignStringToken(mime_type->description())); + builder.AddToken(IdentifiabilityBenignStringToken(mime_type->suffixes())); + DOMPlugin* plugin = mime_type->enabledPlugin(); + if (plugin) { + builder.AddToken(IdentifiabilityBenignStringToken(plugin->name())); + builder.AddToken(IdentifiabilityBenignStringToken(plugin->filename())); + builder.AddToken(IdentifiabilityBenignStringToken(plugin->description())); + } + } + IdentifiabilityMetricBuilder(document->UkmSourceID()) + .Set(surface, builder.GetToken()) + .Record(document->UkmRecorder()); +} + void NavigatorPlugins::Trace(Visitor* visitor) const { visitor->Trace(plugins_); visitor->Trace(mime_types_);
diff --git a/third_party/blink/renderer/modules/plugins/navigator_plugins.h b/third_party/blink/renderer/modules/plugins/navigator_plugins.h index 7f424a4..e45d779 100644 --- a/third_party/blink/renderer/modules/plugins/navigator_plugins.h +++ b/third_party/blink/renderer/modules/plugins/navigator_plugins.h
@@ -35,6 +35,8 @@ DOMPluginArray* plugins(LocalFrame*) const; DOMMimeTypeArray* mimeTypes(LocalFrame*) const; + void RecordMimeTypes(LocalFrame*) const; + mutable Member<DOMPluginArray> plugins_; mutable Member<DOMMimeTypeArray> mime_types_; };
diff --git a/third_party/blink/renderer/modules/webcodecs/video_encoder.cc b/third_party/blink/renderer/modules/webcodecs/video_encoder.cc index 488ba741..d1c4c82 100644 --- a/third_party/blink/renderer/modules/webcodecs/video_encoder.cc +++ b/third_party/blink/renderer/modules/webcodecs/video_encoder.cc
@@ -53,7 +53,7 @@ std::unique_ptr<media::VideoEncoder> CreateAcceleratedVideoEncoder( media::VideoCodecProfile profile, const media::VideoEncoder::Options& options) { -#if defined(OS_MAC) || defined(OS_LINUX) +#if defined(OS_MAC) || defined(OS_LINUX) || defined(OS_CHROMEOS) // TODO(https://crbug.com/1110279) Flush() is not implemented on MacOS' // accelerated video encoder, so we can't use it yet. return nullptr; @@ -97,7 +97,7 @@ media::AsyncDestroyVideoEncoder<media::VideoEncodeAcceleratorAdapter>>( std::make_unique<media::VideoEncodeAcceleratorAdapter>( gpu_factories, std::move(task_runner))); -#endif // defined(OS_MAC) || defined(OS_LINUX) +#endif // defined(OS_MAC) || defined(OS_LINUX) || defined(OS_CHROMEOS) } std::unique_ptr<media::VideoEncoder> CreateVpxVideoEncoder() {
diff --git a/third_party/blink/renderer/platform/exported/web_runtime_features.cc b/third_party/blink/renderer/platform/exported/web_runtime_features.cc index 78974b8..e7ff7f9 100644 --- a/third_party/blink/renderer/platform/exported/web_runtime_features.cc +++ b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
@@ -221,10 +221,6 @@ RuntimeEnabledFeatures::SetImplicitRootScrollerEnabled(enable); } -void WebRuntimeFeatures::EnableCSSOMViewScrollCoordinates(bool enable) { - RuntimeEnabledFeatures::SetCSSOMViewScrollCoordinatesEnabled(enable); -} - void WebRuntimeFeatures::EnableInputMultipleFieldsUI(bool enable) { RuntimeEnabledFeatures::SetInputMultipleFieldsUIEnabled(enable); }
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer_test.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer_test.cc index d193ead..6058d91 100644 --- a/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer_test.cc +++ b/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer_test.cc
@@ -158,7 +158,7 @@ struct TestChunks { Vector<PaintChunk> chunks; - DisplayItemList items = DisplayItemList(0); + DisplayItemList items; // Add a paint chunk with a non-empty paint record and given property nodes. void AddChunk(
diff --git a/third_party/blink/renderer/platform/graphics/contiguous_container.cc b/third_party/blink/renderer/platform/graphics/contiguous_container.cc index 9ea0c88d..c3ebdca0 100644 --- a/third_party/blink/renderer/platform/graphics/contiguous_container.cc +++ b/third_party/blink/renderer/platform/graphics/contiguous_container.cc
@@ -14,10 +14,6 @@ namespace blink { -// Default number of max-sized elements to allocate space for, if there is no -// initial buffer. -static const unsigned kDefaultInitialBufferSize = 32; - class ContiguousContainerBase::Buffer { USING_FAST_MALLOC(Buffer); @@ -57,7 +53,7 @@ } private: - // m_begin <= m_end <= m_begin + m_capacity + // begin_ <= end_ <= begin_ + capacity_ char* begin_; char* end_; wtf_size_t capacity_; @@ -65,12 +61,18 @@ DISALLOW_COPY_AND_ASSIGN(Buffer); }; -ContiguousContainerBase::ContiguousContainerBase(wtf_size_t max_object_size) - : end_index_(0), max_object_size_(max_object_size) {} +ContiguousContainerBase::ContiguousContainerBase( + wtf_size_t max_object_size, + wtf_size_t initial_capacity_in_bytes) + : end_index_(0), + max_object_size_(max_object_size), + initial_capacity_in_bytes_( + std::max(max_object_size, initial_capacity_in_bytes)) {} ContiguousContainerBase::ContiguousContainerBase( ContiguousContainerBase&& source) - : ContiguousContainerBase(source.max_object_size_) { + : ContiguousContainerBase(source.max_object_size_, + source.initial_capacity_in_bytes_) { Swap(source); } @@ -101,11 +103,6 @@ elements_.capacity() * sizeof(elements_[0]); } -void ContiguousContainerBase::ReserveInitialCapacity(wtf_size_t buffer_size, - const char* type_name) { - AllocateNewBufferForNextAllocation(buffer_size, type_name); -} - void* ContiguousContainerBase::Allocate(wtf_size_t object_size, const char* type_name) { DCHECK_LE(object_size, max_object_size_); @@ -120,9 +117,9 @@ } if (!buffer_for_alloc) { - wtf_size_t new_buffer_size = - buffers_.IsEmpty() ? kDefaultInitialBufferSize * max_object_size_ - : 2 * buffers_.back()->Capacity(); + wtf_size_t new_buffer_size = buffers_.IsEmpty() + ? initial_capacity_in_bytes_ + : 2 * buffers_.back()->Capacity(); buffer_for_alloc = AllocateNewBufferForNextAllocation(new_buffer_size, type_name); } @@ -158,13 +155,7 @@ buffers_.swap(other.buffers_); std::swap(end_index_, other.end_index_); std::swap(max_object_size_, other.max_object_size_); -} - -void ContiguousContainerBase::ShrinkToFit() { - while (end_index_ < buffers_.size() - 1) { - DCHECK(buffers_.back()->IsEmpty()); - buffers_.pop_back(); - } + std::swap(initial_capacity_in_bytes_, other.initial_capacity_in_bytes_); } ContiguousContainerBase::Buffer*
diff --git a/third_party/blink/renderer/platform/graphics/contiguous_container.h b/third_party/blink/renderer/platform/graphics/contiguous_container.h index c81241eb..4f684741 100644 --- a/third_party/blink/renderer/platform/graphics/contiguous_container.h +++ b/third_party/blink/renderer/platform/graphics/contiguous_container.h
@@ -41,7 +41,9 @@ DISALLOW_NEW(); protected: - explicit ContiguousContainerBase(wtf_size_t max_object_size); + // The initial capacity will be allocated when the first item is added. + ContiguousContainerBase(wtf_size_t max_object_size, + wtf_size_t initial_capacity_in_bytes); ContiguousContainerBase(ContiguousContainerBase&&); ~ContiguousContainerBase(); @@ -54,16 +56,11 @@ wtf_size_t MemoryUsageInBytes() const; // These do not invoke constructors or destructors. - void ReserveInitialCapacity(wtf_size_t, const char* type_name); void* Allocate(wtf_size_t object_size, const char* type_name); void RemoveLast(); void Clear(); void Swap(ContiguousContainerBase&); - // Discards excess buffer capacity. Intended for use when no more appending - // is anticipated. - void ShrinkToFit(); - Vector<void*> elements_; private: @@ -74,6 +71,7 @@ Vector<std::unique_ptr<Buffer>> buffers_; unsigned end_index_; wtf_size_t max_object_size_; + wtf_size_t initial_capacity_in_bytes_; DISALLOW_COPY_AND_ASSIGN(ContiguousContainerBase); }; @@ -138,14 +136,10 @@ using value_type = BaseElementType; - explicit ContiguousContainer(wtf_size_t max_object_size) - : ContiguousContainerBase(Align(max_object_size)) {} - - ContiguousContainer(wtf_size_t max_object_size, wtf_size_t initial_size_bytes) - : ContiguousContainer(max_object_size) { - ReserveInitialCapacity(std::max(max_object_size, initial_size_bytes), - WTF_HEAP_PROFILER_TYPE_NAME(BaseElementType)); - } + ContiguousContainer(wtf_size_t max_object_size, + wtf_size_t initial_capacity_in_bytes) + : ContiguousContainerBase(Align(max_object_size), + initial_capacity_in_bytes) {} ContiguousContainer(ContiguousContainer&& source) : ContiguousContainerBase(std::move(source)) {} @@ -169,7 +163,6 @@ using ContiguousContainerBase::CapacityInBytes; using ContiguousContainerBase::IsEmpty; using ContiguousContainerBase::MemoryUsageInBytes; - using ContiguousContainerBase::ShrinkToFit; using ContiguousContainerBase::size; using ContiguousContainerBase::UsedCapacityInBytes;
diff --git a/third_party/blink/renderer/platform/graphics/contiguous_container_test.cc b/third_party/blink/renderer/platform/graphics/contiguous_container_test.cc index 5ad0bd5..0545dce 100644 --- a/third_party/blink/renderer/platform/graphics/contiguous_container_test.cc +++ b/third_party/blink/renderer/platform/graphics/contiguous_container_test.cc
@@ -25,16 +25,25 @@ }; // Maximum size of a subclass of Point2D. -static const size_t kMaxPointSize = sizeof(Point3D); +static const wtf_size_t kMaxPointSize = sizeof(Point3D); // Alignment for Point2D and its subclasses. -static const size_t kPointAlignment = sizeof(int); +static const wtf_size_t kPointAlignment = sizeof(int); // How many elements to use for tests with "plenty" of elements. -static const unsigned kNumElements = 150; +static const wtf_size_t kNumElements = 150; + +static const wtf_size_t kDefaultInitialCapacityInBytes = 256; + +class PointList : public ContiguousContainer<Point2D, kPointAlignment> { + public: + explicit PointList( + wtf_size_t initial_capacity_in_bytes = kDefaultInitialCapacityInBytes) + : ContiguousContainer(kMaxPointSize, initial_capacity_in_bytes) {} +}; TEST(ContiguousContainerTest, SimpleStructs) { - ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); + PointList list; list.AllocateAndConstruct<Point2D>(1, 2); list.AllocateAndConstruct<Point3D>(3, 4, 5); list.AllocateAndConstruct<Point2D>(6, 7); @@ -50,14 +59,14 @@ } TEST(ContiguousContainerTest, AllocateLots) { - ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); - for (int i = 0; i < (int)kNumElements; i++) { + PointList list; + for (int i = 0; i < static_cast<int>(kNumElements); i++) { list.AllocateAndConstruct<Point2D>(i, i); list.AllocateAndConstruct<Point2D>(i, i); list.RemoveLast(); } ASSERT_EQ(kNumElements, list.size()); - for (int i = 0; i < (int)kNumElements; i++) { + for (int i = 0; i < static_cast<int>(kNumElements); i++) { ASSERT_EQ(i, list[i].x); ASSERT_EQ(i, list[i].y); } @@ -71,15 +80,23 @@ MOCK_METHOD0(Destruct, void()); }; +class MockDestructibleList : public ContiguousContainer<MockDestructible> { + public: + explicit MockDestructibleList( + wtf_size_t initial_capacity_in_bytes = kDefaultInitialCapacityInBytes) + : ContiguousContainer(sizeof(MockDestructible), + initial_capacity_in_bytes) {} +}; + TEST(ContiguousContainerTest, DestructorCalled) { - ContiguousContainer<MockDestructible> list(sizeof(MockDestructible)); + MockDestructibleList list; auto& destructible = list.AllocateAndConstruct<MockDestructible>(); EXPECT_EQ(&destructible, &list.First()); EXPECT_CALL(destructible, Destruct()); } TEST(ContiguousContainerTest, DestructorCalledOnceWhenClear) { - ContiguousContainer<MockDestructible> list(sizeof(MockDestructible)); + MockDestructibleList list; auto& destructible = list.AllocateAndConstruct<MockDestructible>(); EXPECT_EQ(&destructible, &list.First()); @@ -96,7 +113,7 @@ } TEST(ContiguousContainerTest, DestructorCalledOnceWhenRemoveLast) { - ContiguousContainer<MockDestructible> list(sizeof(MockDestructible)); + MockDestructibleList list; auto& destructible = list.AllocateAndConstruct<MockDestructible>(); EXPECT_EQ(&destructible, &list.First()); @@ -115,8 +132,7 @@ TEST(ContiguousContainerTest, DestructorCalledWithMultipleRemoveLastCalls) { // This container only requests space for one, but the implementation is // free to use more space if the allocator provides it. - ContiguousContainer<MockDestructible> list(sizeof(MockDestructible), - 1 * sizeof(MockDestructible)); + MockDestructibleList list(1 * sizeof(MockDestructible)); testing::MockFunction<void()> separator; // We should be okay to allocate and remove a single one, like before. @@ -170,7 +186,7 @@ } TEST(ContiguousContainerTest, InsertionAndIndexedAccess) { - ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); + PointList list; auto& point1 = list.AllocateAndConstruct<Point2D>(); auto& point2 = list.AllocateAndConstruct<Point2D>(); @@ -185,27 +201,35 @@ } TEST(ContiguousContainerTest, InsertionAndClear) { - ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); + PointList list; EXPECT_TRUE(list.IsEmpty()); EXPECT_EQ(0u, list.size()); + EXPECT_EQ(0u, list.CapacityInBytes()); + EXPECT_EQ(0u, list.UsedCapacityInBytes()); list.AllocateAndConstruct<Point2D>(); EXPECT_FALSE(list.IsEmpty()); EXPECT_EQ(1u, list.size()); + EXPECT_GE(list.CapacityInBytes(), kDefaultInitialCapacityInBytes); + EXPECT_EQ(sizeof(Point2D), list.UsedCapacityInBytes()); list.Clear(); EXPECT_TRUE(list.IsEmpty()); EXPECT_EQ(0u, list.size()); + EXPECT_EQ(0u, list.CapacityInBytes()); + EXPECT_EQ(0u, list.UsedCapacityInBytes()); list.AllocateAndConstruct<Point2D>(); EXPECT_FALSE(list.IsEmpty()); EXPECT_EQ(1u, list.size()); + EXPECT_GE(list.CapacityInBytes(), kDefaultInitialCapacityInBytes); + EXPECT_EQ(sizeof(Point2D), list.UsedCapacityInBytes()); } TEST(ContiguousContainerTest, ElementAddressesAreStable) { - ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); + PointList list; Vector<Point2D*> pointers; - for (int i = 0; i < (int)kNumElements; i++) + for (int i = 0; i < static_cast<int>(kNumElements); i++) pointers.push_back(&list.AllocateAndConstruct<Point2D>()); EXPECT_EQ(kNumElements, list.size()); EXPECT_EQ(kNumElements, pointers.size()); @@ -217,12 +241,12 @@ } TEST(ContiguousContainerTest, ForwardIteration) { - ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); - for (int i = 0; i < (int)kNumElements; i++) + PointList list; + for (int i = 0; i < static_cast<int>(kNumElements); i++) list.AllocateAndConstruct<Point2D>(i, i); - unsigned count = 0; + wtf_size_t count = 0; for (Point2D& point : list) { - EXPECT_EQ((int)count, point.x); + EXPECT_EQ(static_cast<int>(count), point.x); count++; } EXPECT_EQ(kNumElements, count); @@ -232,14 +256,14 @@ } TEST(ContiguousContainerTest, ConstForwardIteration) { - ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); - for (int i = 0; i < (int)kNumElements; i++) + PointList list; + for (int i = 0; i < static_cast<int>(kNumElements); i++) list.AllocateAndConstruct<Point2D>(i, i); const auto& const_list = list; - unsigned count = 0; + wtf_size_t count = 0; for (const Point2D& point : const_list) { - EXPECT_EQ((int)count, point.x); + EXPECT_EQ(static_cast<int>(count), point.x); count++; } EXPECT_EQ(kNumElements, count); @@ -250,13 +274,13 @@ } TEST(ContiguousContainerTest, ReverseIteration) { - ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); - for (int i = 0; i < (int)kNumElements; i++) + PointList list; + for (int i = 0; i < static_cast<int>(kNumElements); i++) list.AllocateAndConstruct<Point2D>(i, i); - unsigned count = 0; + wtf_size_t count = 0; for (auto it = list.rbegin(); it != list.rend(); ++it) { - EXPECT_EQ((int)(kNumElements - 1 - count), it->x); + EXPECT_EQ(static_cast<int>(kNumElements - 1 - count), it->x); count++; } EXPECT_EQ(kNumElements, count); @@ -331,7 +355,7 @@ } TEST(ContiguousContainerTest, AppendByMovingSameList) { - ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); + PointList list; list.AllocateAndConstruct<Point3D>(1, 2, 3); // Moves the Point3D to the end, and default-constructs a Point2D in its @@ -368,11 +392,13 @@ }; bool destroyed = false; - ContiguousContainer<DestructionNotifier> list1(sizeof(DestructionNotifier)); + ContiguousContainer<DestructionNotifier> list1( + sizeof(DestructionNotifier), kDefaultInitialCapacityInBytes); list1.AllocateAndConstruct<DestructionNotifier>(&destroyed); { // Make sure destructor isn't called during appendByMoving. - ContiguousContainer<DestructionNotifier> list2(sizeof(DestructionNotifier)); + ContiguousContainer<DestructionNotifier> list2( + sizeof(DestructionNotifier), kDefaultInitialCapacityInBytes); list2.AppendByMoving(list1.Last(), sizeof(DestructionNotifier)); EXPECT_FALSE(destroyed); } @@ -381,8 +407,8 @@ } TEST(ContiguousContainerTest, AppendByMovingReturnsMovedPointer) { - ContiguousContainer<Point2D, kPointAlignment> list1(kMaxPointSize); - ContiguousContainer<Point2D, kPointAlignment> list2(kMaxPointSize); + PointList list1; + PointList list2; Point2D& point = list1.AllocateAndConstruct<Point2D>(); Point2D& moved_point1 = list2.AppendByMoving(point, sizeof(Point2D)); @@ -394,8 +420,8 @@ } TEST(ContiguousContainerTest, AppendByMovingReplacesSourceWithNewElement) { - ContiguousContainer<Point2D, kPointAlignment> list1(kMaxPointSize); - ContiguousContainer<Point2D, kPointAlignment> list2(kMaxPointSize); + PointList list1; + PointList list2; list1.AllocateAndConstruct<Point2D>(1, 2); EXPECT_EQ(1, list1.First().x); @@ -412,7 +438,7 @@ } TEST(ContiguousContainerTest, AppendByMovingElementsOfDifferentSizes) { - ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); + PointList list; list.AllocateAndConstruct<Point3D>(1, 2, 3); list.AllocateAndConstruct<Point2D>(4, 5); @@ -440,9 +466,9 @@ } TEST(ContiguousContainerTest, Swap) { - ContiguousContainer<Point2D, kPointAlignment> list1(kMaxPointSize); + PointList list1; list1.AllocateAndConstruct<Point2D>(1, 2); - ContiguousContainer<Point2D, kPointAlignment> list2(kMaxPointSize); + PointList list2; list2.AllocateAndConstruct<Point2D>(3, 4); list2.AllocateAndConstruct<Point2D>(5, 6); @@ -469,46 +495,30 @@ TEST(ContiguousContainerTest, CapacityInBytes) { const int kIterations = 500; - const size_t kInitialCapacity = 10 * kMaxPointSize; - const size_t kUpperBoundOnMinCapacity = kInitialCapacity; + const wtf_size_t kInitialCapacity = 10 * kMaxPointSize; + const wtf_size_t kUpperBoundOnMinCapacity = kInitialCapacity; + // In worst case, there are 2 buffers, and the second buffer contains only one + // element, so the factor is close to 3 as the second buffer is twice as big + // as the first buffer. + const size_t kMaxWasteFactor = 3; - // At time of writing, removing elements from the end can cause up to 7x the - // memory required to be consumed, in the worst case, since we can have up to - // two trailing inner lists that are empty (for 2*size + 4*size in unused - // memory, due to the exponential growth strategy). - // Unfortunately, this captures behaviour of the underlying allocator as - // well as this container, so we're pretty loose here. This constant may - // need to be adjusted. - const size_t kMaxWasteFactor = 8; - - ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize, - kInitialCapacity); + PointList list(kInitialCapacity); // The capacity should grow with the list. for (int i = 0; i < kIterations; i++) { size_t capacity = list.CapacityInBytes(); ASSERT_GE(capacity, list.size() * sizeof(Point2D)); - ASSERT_LE(capacity, std::max(list.size() * sizeof(Point2D), - kUpperBoundOnMinCapacity) * + ASSERT_LE(capacity, std::max<wtf_size_t>(list.size() * sizeof(Point2D), + kUpperBoundOnMinCapacity) * kMaxWasteFactor); list.AllocateAndConstruct<Point2D>(); } - - // The capacity should shrink with the list. - for (int i = 0; i < kIterations; i++) { - size_t capacity = list.CapacityInBytes(); - ASSERT_GE(capacity, list.size() * sizeof(Point2D)); - ASSERT_LE(capacity, std::max(list.size() * sizeof(Point2D), - kUpperBoundOnMinCapacity) * - kMaxWasteFactor); - list.RemoveLast(); - } } TEST(ContiguousContainerTest, CapacityInBytesAfterClear) { // Clearing should restore the capacity of the container to the same as a // newly allocated one (without reserved capacity requested). - ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); + PointList list; size_t empty_capacity = list.CapacityInBytes(); list.AllocateAndConstruct<Point2D>(); list.AllocateAndConstruct<Point2D>(); @@ -518,7 +528,8 @@ TEST(ContiguousContainerTest, Alignment) { const size_t kMaxAlign = alignof(long double); - ContiguousContainer<Point2D, kMaxAlign> list(kMaxPointSize); + ContiguousContainer<Point2D, kMaxAlign> list(kMaxPointSize, + kDefaultInitialCapacityInBytes); list.AllocateAndConstruct<Point2D>(); EXPECT_EQ(0u, reinterpret_cast<intptr_t>(&list.Last()) & (kMaxAlign - 1));
diff --git a/third_party/blink/renderer/platform/graphics/paint/display_item_list.h b/third_party/blink/renderer/platform/graphics/paint/display_item_list.h index c6b83e17..0f6f30e 100644 --- a/third_party/blink/renderer/platform/graphics/paint/display_item_list.h +++ b/third_party/blink/renderer/platform/graphics/paint/display_item_list.h
@@ -28,8 +28,16 @@ class PLATFORM_EXPORT DisplayItemList : public ContiguousContainer<DisplayItem, kDisplayItemAlignment> { public: - DisplayItemList(wtf_size_t initial_size_bytes) - : ContiguousContainer(kMaximumDisplayItemSize, initial_size_bytes) {} + static constexpr wtf_size_t kDefaultCapacityInBytes = 512; + + // Using 0 as the default value to make 0 also fall back to + // kDefaultCapacityInBytes. + explicit DisplayItemList(wtf_size_t initial_capacity_in_bytes = 0) + : ContiguousContainer(kMaximumDisplayItemSize, + initial_capacity_in_bytes + ? initial_capacity_in_bytes + : kDefaultCapacityInBytes) {} + DisplayItemList(DisplayItemList&& source) : ContiguousContainer(std::move(source)) {}
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc b/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc index 56e5366..8da84c21 100644 --- a/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc +++ b/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc
@@ -14,8 +14,6 @@ namespace blink { -PaintArtifact::PaintArtifact() : display_item_list_(0) {} - PaintArtifact::PaintArtifact(DisplayItemList display_items, Vector<PaintChunk> chunks) : display_item_list_(std::move(display_items)), chunks_(std::move(chunks)) {
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_artifact.h b/third_party/blink/renderer/platform/graphics/paint/paint_artifact.h index 83daf93..f67cf0c 100644 --- a/third_party/blink/renderer/platform/graphics/paint/paint_artifact.h +++ b/third_party/blink/renderer/platform/graphics/paint/paint_artifact.h
@@ -90,7 +90,7 @@ const PaintChunkSubset& paint_chunks) const; private: - PaintArtifact(); + PaintArtifact() = default; PaintArtifact(DisplayItemList, Vector<PaintChunk>); DisplayItemList display_item_list_;
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_controller.cc b/third_party/blink/renderer/platform/graphics/paint/paint_controller.cc index 700d609..3cd0438 100644 --- a/third_party/blink/renderer/platform/graphics/paint/paint_controller.cc +++ b/third_party/blink/renderer/platform/graphics/paint/paint_controller.cc
@@ -15,9 +15,7 @@ namespace blink { PaintController::PaintController(Usage usage) - : usage_(usage), - current_paint_artifact_(PaintArtifact::Empty()), - new_display_item_list_(0) { + : usage_(usage), current_paint_artifact_(PaintArtifact::Empty()) { // frame_first_paints_ should have one null frame since the beginning, so // that PaintController is robust even if it paints outside of BeginFrame // and EndFrame cycles. It will also enable us to combine the first paint @@ -61,7 +59,6 @@ } ++num_cached_new_items_; - EnsureNewDisplayItemListInitialCapacity(); if (!RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) ProcessNewItem(MoveItemFromCurrentListToNewList(cached_item)); @@ -127,8 +124,6 @@ return false; } - EnsureNewDisplayItemListInitialCapacity(); - if (next_item_to_match_ == start_item_index) { // We are matching new and cached display items sequentially. Skip the // subsequence for later sequential matching of individual display items. @@ -506,9 +501,6 @@ new_cached_subsequences_.swap(current_cached_subsequences_); new_cached_subsequences_.clear(); - // The new list will not be appended to again so we can release unused memory. - new_display_item_list_.ShrinkToFit(); - current_paint_artifact_ = PaintArtifact::Create(std::move(new_display_item_list_), new_paint_chunks_.ReleasePaintChunks()); @@ -517,7 +509,8 @@ out_of_order_item_id_index_map_.clear(); // We'll allocate the initial buffer when we start the next paint. - new_display_item_list_ = DisplayItemList(0); + new_display_item_list_ = + DisplayItemList(GetDisplayItemList().UsedCapacityInBytes()); #if DCHECK_IS_ON() num_indexed_items_ = 0;
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_controller.h b/third_party/blink/renderer/platform/graphics/paint/paint_controller.h index 0a718a8..5c02bbe 100644 --- a/third_party/blink/renderer/platform/graphics/paint/paint_controller.h +++ b/third_party/blink/renderer/platform/graphics/paint/paint_controller.h
@@ -29,8 +29,6 @@ namespace blink { -static constexpr wtf_size_t kInitialDisplayItemListCapacityBytes = 512; - enum class PaintBenchmarkMode { kNormal, kForceRasterInvalidationAndConvert, @@ -148,7 +146,6 @@ "DisplayItem subclass alignment is not a factor of " "kDisplayItemAlignment."); - EnsureNewDisplayItemListInitialCapacity(); DisplayItemClass& display_item = new_display_item_list_.AllocateAndConstruct<DisplayItemClass>( std::forward<Args>(args)...); @@ -303,17 +300,6 @@ void InvalidateAllForTesting() { InvalidateAllInternal(); } void InvalidateAllInternal(); - void EnsureNewDisplayItemListInitialCapacity() { - if (new_display_item_list_.IsEmpty()) { - // TODO(wangxianzhu): Consider revisiting this heuristic. - new_display_item_list_ = DisplayItemList( - current_paint_artifact_->GetDisplayItemList().IsEmpty() - ? kInitialDisplayItemListCapacityBytes - : current_paint_artifact_->GetDisplayItemList() - .UsedCapacityInBytes()); - } - } - // Set new item state (cache skipping, etc) for the last new display item. void ProcessNewItem(DisplayItem&);
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 0a8962b4..91e8178 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -547,10 +547,6 @@ status: "experimental", }, { - name: "CSSOMViewScrollCoordinates", - status: "stable", - }, - { name: "CSSPaintAPIArguments", status: "experimental", },
diff --git a/third_party/blink/renderer/platform/testing/test_paint_artifact.cc b/third_party/blink/renderer/platform/testing/test_paint_artifact.cc index 29353d7..7d1612d 100644 --- a/third_party/blink/renderer/platform/testing/test_paint_artifact.cc +++ b/third_party/blink/renderer/platform/testing/test_paint_artifact.cc
@@ -18,10 +18,6 @@ namespace blink { -TestPaintArtifact::TestPaintArtifact() : display_item_list_(0) {} - -TestPaintArtifact::~TestPaintArtifact() = default; - static DisplayItemClient& StaticDummyClient() { DEFINE_STATIC_LOCAL(FakeDisplayItemClient, client, ()); client.Validate();
diff --git a/third_party/blink/renderer/platform/testing/test_paint_artifact.h b/third_party/blink/renderer/platform/testing/test_paint_artifact.h index 773ce20..791dd8dd 100644 --- a/third_party/blink/renderer/platform/testing/test_paint_artifact.h +++ b/third_party/blink/renderer/platform/testing/test_paint_artifact.h
@@ -50,9 +50,6 @@ STACK_ALLOCATED(); public: - TestPaintArtifact(); - ~TestPaintArtifact(); - // Add a chunk to the artifact. Each chunk will have a different automatically // created client. TestPaintArtifact& Chunk() { return Chunk(NewClient()); }
diff --git a/third_party/blink/renderer/platform/transforms/interpolated_transform_operation.cc b/third_party/blink/renderer/platform/transforms/interpolated_transform_operation.cc index 5e45f996..0ff43c13 100644 --- a/third_party/blink/renderer/platform/transforms/interpolated_transform_operation.cc +++ b/third_party/blink/renderer/platform/transforms/interpolated_transform_operation.cc
@@ -57,8 +57,8 @@ const TransformOperation* from, double progress, bool blend_to_identity) { - if (from && !from->IsSameType(*this)) - return this; + DCHECK(!from || CanBlendWith(*from)); + TransformOperations to_operations; to_operations.Operations().push_back(this); TransformOperations from_operations;
diff --git a/third_party/blink/renderer/platform/transforms/interpolated_transform_operation.h b/third_party/blink/renderer/platform/transforms/interpolated_transform_operation.h index 5c8d303..9621a42f 100644 --- a/third_party/blink/renderer/platform/transforms/interpolated_transform_operation.h +++ b/third_party/blink/renderer/platform/transforms/interpolated_transform_operation.h
@@ -50,10 +50,6 @@ new InterpolatedTransformOperation(from, to, starting_index, progress)); } - bool CanBlendWith(const TransformOperation& other) const override { - return IsSameType(other); - } - private: OperationType GetType() const override { return kInterpolated; }
diff --git a/third_party/blink/renderer/platform/transforms/matrix_3d_transform_operation.cc b/third_party/blink/renderer/platform/transforms/matrix_3d_transform_operation.cc index 2d8da85b..f989a0e1 100644 --- a/third_party/blink/renderer/platform/transforms/matrix_3d_transform_operation.cc +++ b/third_party/blink/renderer/platform/transforms/matrix_3d_transform_operation.cc
@@ -93,8 +93,7 @@ const TransformOperation* from, double progress, bool blend_to_identity) { - if (from && !from->IsSameType(*this)) - return this; + DCHECK(!from || CanBlendWith(*from)); // Convert the TransformOperations into matrices. Fail the blend operation // if either of the matrices is non-invertible.
diff --git a/third_party/blink/renderer/platform/transforms/matrix_3d_transform_operation.h b/third_party/blink/renderer/platform/transforms/matrix_3d_transform_operation.h index 81d3fd8..f33c3f2 100644 --- a/third_party/blink/renderer/platform/transforms/matrix_3d_transform_operation.h +++ b/third_party/blink/renderer/platform/transforms/matrix_3d_transform_operation.h
@@ -41,10 +41,6 @@ TransformationMatrix Matrix() const { return matrix_; } - bool CanBlendWith(const TransformOperation& other) const override { - return false; - } - static bool IsMatchingOperationType(OperationType type) { return type == kMatrix3D; }
diff --git a/third_party/blink/renderer/platform/transforms/matrix_transform_operation.cc b/third_party/blink/renderer/platform/transforms/matrix_transform_operation.cc index ba42dc2..cfc0196 100644 --- a/third_party/blink/renderer/platform/transforms/matrix_transform_operation.cc +++ b/third_party/blink/renderer/platform/transforms/matrix_transform_operation.cc
@@ -64,8 +64,7 @@ const TransformOperation* from, double progress, bool blend_to_identity) { - if (from && !from->IsSameType(*this)) - return this; + DCHECK(!from || CanBlendWith(*from)); // convert the TransformOperations into matrices TransformationMatrix from_t;
diff --git a/third_party/blink/renderer/platform/transforms/matrix_transform_operation.h b/third_party/blink/renderer/platform/transforms/matrix_transform_operation.h index d601a30c..688c0c08 100644 --- a/third_party/blink/renderer/platform/transforms/matrix_transform_operation.h +++ b/third_party/blink/renderer/platform/transforms/matrix_transform_operation.h
@@ -52,10 +52,6 @@ return TransformationMatrix(a_, b_, c_, d_, e_, f_); } - bool CanBlendWith(const TransformOperation& other) const override { - return false; - } - static bool IsMatchingOperationType(OperationType type) { return type == kMatrix; }
diff --git a/third_party/blink/renderer/platform/transforms/perspective_transform_operation.h b/third_party/blink/renderer/platform/transforms/perspective_transform_operation.h index e89ec30..cae996b 100644 --- a/third_party/blink/renderer/platform/transforms/perspective_transform_operation.h +++ b/third_party/blink/renderer/platform/transforms/perspective_transform_operation.h
@@ -40,10 +40,6 @@ double Perspective() const { return p_; } - bool CanBlendWith(const TransformOperation& other) const override { - return IsSameType(other); - } - static bool IsMatchingOperationType(OperationType type) { return type == kPerspective; }
diff --git a/third_party/blink/renderer/platform/transforms/rotate_transform_operation.cc b/third_party/blink/renderer/platform/transforms/rotate_transform_operation.cc index 648e246..a493bb2 100644 --- a/third_party/blink/renderer/platform/transforms/rotate_transform_operation.cc +++ b/third_party/blink/renderer/platform/transforms/rotate_transform_operation.cc
@@ -71,8 +71,7 @@ const TransformOperation* from, double progress, bool blend_to_identity) { - if (from && !IsMatchingOperationType(from->GetType())) - return this; + DCHECK(!from || CanBlendWith(*from)); if (blend_to_identity) return RotateTransformOperation::Create( @@ -96,11 +95,6 @@ Rotation::Slerp(from_rotate.rotation_, rotation_, progress), type); } -bool RotateTransformOperation::CanBlendWith( - const TransformOperation& other) const { - return other.IsSameType(*this); -} - RotateAroundOriginTransformOperation::RotateAroundOriginTransformOperation( double angle, double origin_x, @@ -134,8 +128,8 @@ const TransformOperation* from, double progress, bool blend_to_identity) { - if (from && !from->IsSameType(*this)) - return this; + DCHECK(!from || CanBlendWith(*from)); + if (blend_to_identity) { return RotateAroundOriginTransformOperation::Create( Angle() * (1 - progress), origin_x_, origin_y_);
diff --git a/third_party/blink/renderer/platform/transforms/rotate_transform_operation.h b/third_party/blink/renderer/platform/transforms/rotate_transform_operation.h index b0e054c..d736a23a 100644 --- a/third_party/blink/renderer/platform/transforms/rotate_transform_operation.h +++ b/third_party/blink/renderer/platform/transforms/rotate_transform_operation.h
@@ -70,9 +70,8 @@ double& result_angle_a, double& result_angle_b); - bool CanBlendWith(const TransformOperation& other) const override; OperationType GetType() const override { return type_; } - OperationType PrimitiveType() const final { return kRotate3D; } + OperationType PrimitiveType() const override { return kRotate3D; } void Apply(TransformationMatrix& transform, const FloatSize& /*borderBoxSize*/) const override { @@ -130,6 +129,7 @@ static bool IsMatchingOperationType(OperationType type) { return type == kRotateAroundOrigin; } + OperationType PrimitiveType() const override { return kRotateAroundOrigin; } private: RotateAroundOriginTransformOperation(double angle,
diff --git a/third_party/blink/renderer/platform/transforms/scale_transform_operation.cc b/third_party/blink/renderer/platform/transforms/scale_transform_operation.cc index b6fb9a86..e440c7a6 100644 --- a/third_party/blink/renderer/platform/transforms/scale_transform_operation.cc +++ b/third_party/blink/renderer/platform/transforms/scale_transform_operation.cc
@@ -63,8 +63,7 @@ const TransformOperation* from, double progress, bool blend_to_identity) { - if (from && !from->CanBlendWith(*this)) - return this; + DCHECK(!from || CanBlendWith(*from)); if (blend_to_identity) return ScaleTransformOperation::Create( @@ -83,11 +82,4 @@ blink::Blend(from_z, z_, progress), is_3d ? kScale3D : kScale); } -bool ScaleTransformOperation::CanBlendWith( - const TransformOperation& other) const { - return other.GetType() == kScaleX || other.GetType() == kScaleY || - other.GetType() == kScaleZ || other.GetType() == kScale3D || - other.GetType() == kScale; -} - } // namespace blink
diff --git a/third_party/blink/renderer/platform/transforms/scale_transform_operation.h b/third_party/blink/renderer/platform/transforms/scale_transform_operation.h index 39c6788..c6352c030 100644 --- a/third_party/blink/renderer/platform/transforms/scale_transform_operation.h +++ b/third_party/blink/renderer/platform/transforms/scale_transform_operation.h
@@ -54,8 +54,6 @@ double Y() const { return y_; } double Z() const { return z_; } - bool CanBlendWith(const TransformOperation& other) const override; - void Apply(TransformationMatrix& transform, const FloatSize&) const override { transform.Scale3d(x_, y_, z_); }
diff --git a/third_party/blink/renderer/platform/transforms/skew_transform_operation.cc b/third_party/blink/renderer/platform/transforms/skew_transform_operation.cc index 30c27055d..d9d5a80 100644 --- a/third_party/blink/renderer/platform/transforms/skew_transform_operation.cc +++ b/third_party/blink/renderer/platform/transforms/skew_transform_operation.cc
@@ -37,8 +37,7 @@ const TransformOperation* from, double progress, bool blend_to_identity) { - if (from && !from->CanBlendWith(*this)) - return this; + DCHECK(!from || CanBlendWith(*from)); if (blend_to_identity) return SkewTransformOperation::Create(blink::Blend(angle_x_, 0.0, progress), @@ -54,10 +53,4 @@ blink::Blend(from_angle_y, angle_y_, progress), type_); } -bool SkewTransformOperation::CanBlendWith( - const TransformOperation& other) const { - return other.GetType() == kSkew || other.GetType() == kSkewX || - other.GetType() == kSkewY; -} - } // namespace blink
diff --git a/third_party/blink/renderer/platform/transforms/skew_transform_operation.h b/third_party/blink/renderer/platform/transforms/skew_transform_operation.h index ab38b71f..7a838f1 100644 --- a/third_party/blink/renderer/platform/transforms/skew_transform_operation.h +++ b/third_party/blink/renderer/platform/transforms/skew_transform_operation.h
@@ -42,8 +42,6 @@ double AngleX() const { return angle_x_; } double AngleY() const { return angle_y_; } - bool CanBlendWith(const TransformOperation& other) const override; - static bool IsMatchingOperationType(OperationType type) { return type == kSkewX || type == kSkewY || type == kSkew; }
diff --git a/third_party/blink/renderer/platform/transforms/transform_operation.h b/third_party/blink/renderer/platform/transforms/transform_operation.h index 21e2fe9a..e5a8f18b 100644 --- a/third_party/blink/renderer/platform/transforms/transform_operation.h +++ b/third_party/blink/renderer/platform/transforms/transform_operation.h
@@ -92,7 +92,9 @@ bool IsSameType(const TransformOperation& other) const { return other.GetType() == GetType(); } - virtual bool CanBlendWith(const TransformOperation& other) const = 0; + bool CanBlendWith(const TransformOperation& other) const { + return PrimitiveType() == other.PrimitiveType(); + } virtual bool PreservesAxisAlignment() const { return false; }
diff --git a/third_party/blink/renderer/platform/transforms/transform_operations.cc b/third_party/blink/renderer/platform/transforms/transform_operations.cc index 2b3a92f7..222f0e5 100644 --- a/third_party/blink/renderer/platform/transforms/transform_operations.cc +++ b/third_party/blink/renderer/platform/transforms/transform_operations.cc
@@ -98,10 +98,9 @@ wtf_size_t num_operations = std::min(Operations().size(), other.Operations().size()); for (wtf_size_t i = 0; i < num_operations; ++i) { - if (Operations()[i]->PrimitiveType() != - other.Operations()[i]->PrimitiveType()) { - // Remaining operations in each operations list require matrix/matrix3d - // interpolation. + if (!Operations()[i]->CanBlendWith(*other.Operations()[i])) { + // Remaining operations in each operations list require merging for + // matrix/matrix3d interpolation. return i; } }
diff --git a/third_party/blink/renderer/platform/transforms/transform_operations_test.cc b/third_party/blink/renderer/platform/transforms/transform_operations_test.cc index 88d776d..551db4e 100644 --- a/third_party/blink/renderer/platform/transforms/transform_operations_test.cc +++ b/third_party/blink/renderer/platform/transforms/transform_operations_test.cc
@@ -571,6 +571,75 @@ EXPECT_TRUE(ops.HasNonTrivial3DComponent()); } +TEST(TransformOperationsTest, CanBlendWithSkewTest) { + TransformOperations ops_x, ops_y, ops_skew, ops_skew2; + ops_x.Operations().push_back( + SkewTransformOperation::Create(45, 0, TransformOperation::kSkewX)); + ops_y.Operations().push_back( + SkewTransformOperation::Create(0, 45, TransformOperation::kSkewY)); + ops_skew.Operations().push_back( + SkewTransformOperation::Create(45, 0, TransformOperation::kSkew)); + ops_skew2.Operations().push_back( + SkewTransformOperation::Create(0, 45, TransformOperation::kSkew)); + + EXPECT_TRUE(ops_x.Operations()[0]->CanBlendWith(*ops_x.Operations()[0])); + EXPECT_TRUE(ops_y.Operations()[0]->CanBlendWith(*ops_y.Operations()[0])); + + EXPECT_FALSE(ops_x.Operations()[0]->CanBlendWith(*ops_y.Operations()[0])); + EXPECT_FALSE(ops_x.Operations()[0]->CanBlendWith(*ops_skew.Operations()[0])); + EXPECT_FALSE(ops_y.Operations()[0]->CanBlendWith(*ops_skew.Operations()[0])); + + EXPECT_TRUE( + ops_skew.Operations()[0]->CanBlendWith(*ops_skew2.Operations()[0])); + + ASSERT_TRUE(IsA<SkewTransformOperation>( + *ops_skew.Blend(ops_skew2, 0.5).Operations()[0])); + ASSERT_TRUE(IsA<Matrix3DTransformOperation>( + *ops_x.Blend(ops_y, 0.5).Operations()[0])); +} + +TEST(TransformOperationsTest, CanBlendWithMatrixTest) { + TransformOperations ops_a, ops_b; + ops_a.Operations().push_back( + MatrixTransformOperation::Create(1, 0, 0, 1, 0, 0)); + ops_a.Operations().push_back( + RotateTransformOperation::Create(0, TransformOperation::kRotate)); + ops_b.Operations().push_back( + MatrixTransformOperation::Create(2, 0, 0, 2, 0, 0)); + ops_b.Operations().push_back( + RotateTransformOperation::Create(360, TransformOperation::kRotate)); + + EXPECT_TRUE(ops_a.Operations()[0]->CanBlendWith(*ops_b.Operations()[0])); + + TransformOperations ops_blended = ops_a.Blend(ops_b, 0.5); + ASSERT_EQ(ops_blended.Operations().size(), 2u); + ASSERT_TRUE(IsA<MatrixTransformOperation>(*ops_blended.Operations()[0])); + ASSERT_TRUE(IsA<RotateTransformOperation>(*ops_blended.Operations()[1])); + EXPECT_EQ(To<RotateTransformOperation>(*ops_blended.Operations()[1]).Angle(), + 180.0); +} + +TEST(TransformOperationsTest, CanBlendWithMatrix3DTest) { + TransformOperations ops_a, ops_b; + ops_a.Operations().push_back(Matrix3DTransformOperation::Create( + TransformationMatrix(1, 0, 0, 1, 0, 0))); + ops_a.Operations().push_back( + RotateTransformOperation::Create(0, TransformOperation::kRotate)); + ops_b.Operations().push_back(Matrix3DTransformOperation::Create( + TransformationMatrix(2, 0, 0, 2, 0, 0))); + ops_b.Operations().push_back( + RotateTransformOperation::Create(360, TransformOperation::kRotate)); + + EXPECT_TRUE(ops_a.Operations()[0]->CanBlendWith(*ops_b.Operations()[0])); + + TransformOperations ops_blended = ops_a.Blend(ops_b, 0.5); + ASSERT_EQ(ops_blended.Operations().size(), 2u); + ASSERT_TRUE(IsA<Matrix3DTransformOperation>(*ops_blended.Operations()[0])); + ASSERT_TRUE(IsA<RotateTransformOperation>(*ops_blended.Operations()[1])); + EXPECT_EQ(To<RotateTransformOperation>(*ops_blended.Operations()[1]).Angle(), + 180.0); +} + TEST(TransformOperationsTest, InterpolatedTransformBlendIdentityTest) { // When interpolating transform lists of differing lengths, the length of the // shorter list behaves as if it is padded with identity transforms.
diff --git a/third_party/blink/renderer/platform/transforms/translate_transform_operation.cc b/third_party/blink/renderer/platform/transforms/translate_transform_operation.cc index 43dfa1f..da798565 100644 --- a/third_party/blink/renderer/platform/transforms/translate_transform_operation.cc +++ b/third_party/blink/renderer/platform/transforms/translate_transform_operation.cc
@@ -74,8 +74,7 @@ const TransformOperation* from, double progress, bool blend_to_identity) { - if (from && !from->CanBlendWith(*this)) - return this; + DCHECK(!from || CanBlendWith(*from)); const Length zero_length = Length::Fixed(0); if (blend_to_identity) { @@ -97,13 +96,6 @@ blink::Blend(from_z, z_, progress), is_3d ? kTranslate3D : kTranslate); } -bool TranslateTransformOperation::CanBlendWith( - const TransformOperation& other) const { - return other.GetType() == kTranslate || other.GetType() == kTranslateX || - other.GetType() == kTranslateY || other.GetType() == kTranslateZ || - other.GetType() == kTranslate3D; -} - scoped_refptr<TranslateTransformOperation> TranslateTransformOperation::ZoomTranslate(double factor) { return Create(x_.Zoom(factor), y_.Zoom(factor), z_ * factor, type_);
diff --git a/third_party/blink/renderer/platform/transforms/translate_transform_operation.h b/third_party/blink/renderer/platform/transforms/translate_transform_operation.h index 6cdf6d9..5b59533 100644 --- a/third_party/blink/renderer/platform/transforms/translate_transform_operation.h +++ b/third_party/blink/renderer/platform/transforms/translate_transform_operation.h
@@ -52,7 +52,6 @@ return *this == static_cast<const TransformOperation&>(other); } - bool CanBlendWith(const TransformOperation& other) const override; bool DependsOnBoxSize() const override { return x_.IsPercentOrCalc() || y_.IsPercentOrCalc(); }
diff --git a/third_party/blink/renderer/platform/widget/input/scroll_predictor.cc b/third_party/blink/renderer/platform/widget/input/scroll_predictor.cc index 64858a6..95e5f3f 100644 --- a/third_party/blink/renderer/platform/widget/input/scroll_predictor.cc +++ b/third_party/blink/renderer/platform/widget/input/scroll_predictor.cc
@@ -13,7 +13,8 @@ namespace blink { -ScrollPredictor::ScrollPredictor() { +ScrollPredictor::ScrollPredictor() + : metrics_handler_("Event.InputEventPrediction.Scroll") { // Get the predictor from feature flags std::string predictor_name = GetFieldTrialParamValueByFeature( blink::features::kResamplingScrollEvents, "predictor");
diff --git a/third_party/blink/web_tests/NeverFixTests b/third_party/blink/web_tests/NeverFixTests index 441c3109..93e2776 100644 --- a/third_party/blink/web_tests/NeverFixTests +++ b/third_party/blink/web_tests/NeverFixTests
@@ -471,6 +471,11 @@ external/wpt/css/css-text/white-space/trailing-ogham-002.html [ Skip ] external/wpt/css/css-text/white-space/trailing-ogham-003.html [ Skip ] +# 1px pixel differences that are not relevant to the tests. +external/wpt/css/CSS2/text/text-transform-bicameral-007.xht [ Skip ] +[ Mac ] external/wpt/css/CSS2/text/text-transform-bicameral-014.xht [ Skip ] +[ Mac ] external/wpt/css/CSS2/text/text-transform-bicameral-009.xht [ Skip ] + external/wpt/css/CSS2/linebox/inline-formatting-context-010b.xht [ Skip ] external/wpt/css/CSS2/normal-flow/inline-block-replaced-height-008.xht [ Skip ] external/wpt/css/CSS2/normal-flow/inline-replaced-height-008.xht [ Skip ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index e7c1afe3..a12138c 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -2609,14 +2609,6 @@ crbug.com/958381 [ Mac ] external/wpt/css/CSS2/tables/table-anonymous-objects-206.xht [ Failure ] # ====== New tests from wpt-importer added here ====== -crbug.com/626703 external/wpt/css/CSS2/text/text-transform-bicameral-007.xht [ Failure ] -crbug.com/626703 [ Mac10.12 ] external/wpt/css/CSS2/text/text-transform-bicameral-014.xht [ Failure ] -crbug.com/626703 [ Mac10.13 ] external/wpt/css/CSS2/text/text-transform-bicameral-014.xht [ Failure ] -crbug.com/626703 [ Mac10.14 ] external/wpt/css/CSS2/text/text-transform-bicameral-014.xht [ Failure ] -crbug.com/626703 [ Mac ] external/wpt/css/CSS2/text/text-transform-bicameral-009.xht [ Failure ] -crbug.com/626703 external/wpt/css/CSS2/text/text-indent-101.xht [ Failure ] -crbug.com/626703 external/wpt/css/CSS2/text/text-indent-100.xht [ Failure ] -crbug.com/626703 external/wpt/css/CSS2/text/text-indent-102.xht [ Failure ] crbug.com/626703 external/wpt/css/css-text/letter-spacing/letter-spacing-203.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/letter-spacing/letter-spacing-201.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/letter-spacing/letter-spacing-206.html [ Failure ] @@ -6622,6 +6614,9 @@ crbug.com/1057060 virtual/scroll-unification/fast/scrolling/scrollbars/mouse-autoscrolling-on-scrollbar.html [ Pass Failure Timeout ] crbug.com/1045599 fast/css-grid-layout/flex-content-sized-columns-resize.html [ Pass Failure Timeout ] +# TODO(michaelludwig) - Remove after Skia roll and rebaseline +crbug.com/1135225 fast/sub-pixel/transformed-iframe-copy-on-scroll.html [ Pass Failure ] + # Sheriff 2020-09-29 crbug.com/1133342 external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/reporting-observer.html [ Pass Failure Timeout ] crbug.com/1083605 media/controls-styling-strict.html [ Pass Failure ]
diff --git a/third_party/blink/web_tests/external/wpt/css/CSS2/text/text-indent-100.xht b/third_party/blink/web_tests/external/wpt/css/CSS2/text/text-indent-100.xht index 7c498d2b..977d321 100644 --- a/third_party/blink/web_tests/external/wpt/css/CSS2/text/text-indent-100.xht +++ b/third_party/blink/web_tests/external/wpt/css/CSS2/text/text-indent-100.xht
@@ -23,7 +23,7 @@ </style> </head> <body> - <p>Test passes if there is only one black box on this page (with no jagged edges).</p> + <p>Test passes if there is one black box on this page (with no jagged edges).</p> <div id="parent"> <div>X</div> <div id="test">X</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/CSS2/text/text-indent-101.xht b/third_party/blink/web_tests/external/wpt/css/CSS2/text/text-indent-101.xht index 5007ff6..35e155a 100644 --- a/third_party/blink/web_tests/external/wpt/css/CSS2/text/text-indent-101.xht +++ b/third_party/blink/web_tests/external/wpt/css/CSS2/text/text-indent-101.xht
@@ -23,7 +23,7 @@ </style> </head> <body> - <p>Test passes if there is only one black box on this page (with no jagged edges).</p> + <p>Test passes if there is one black box on this page (with no jagged edges).</p> <div id="parent"> <div>X</div> <div id="test">X</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/CSS2/text/text-indent-102.xht b/third_party/blink/web_tests/external/wpt/css/CSS2/text/text-indent-102.xht index b187c79..a0352dea 100644 --- a/third_party/blink/web_tests/external/wpt/css/CSS2/text/text-indent-102.xht +++ b/third_party/blink/web_tests/external/wpt/css/CSS2/text/text-indent-102.xht
@@ -23,7 +23,7 @@ </style> </head> <body> - <p>Test passes if there is only one black box on this page (with no jagged edges).</p> + <p>Test passes if there is one black box on this page (with no jagged edges).</p> <div id="parent"> <div>X</div> <div id="test">X</div>
diff --git a/third_party/blink/web_tests/external/wpt/dom/events/scrolling/overscroll-deltas.html b/third_party/blink/web_tests/external/wpt/dom/events/scrolling/overscroll-deltas.html index 091cfd06..6f0b77f22 100644 --- a/third_party/blink/web_tests/external/wpt/dom/events/scrolling/overscroll-deltas.html +++ b/third_party/blink/web_tests/external/wpt/dom/events/scrolling/overscroll-deltas.html
@@ -11,6 +11,11 @@ height: 500px; background: red; } +html, body { + /* Prevent any built-in browser overscroll features from consuming the scroll + * deltas */ + overscroll-behavior: none; +} </style> @@ -46,6 +51,11 @@ await waitFor(() => { return scrollend_received; }, 'Document did not receive scrollend event.'); + // Even though we request 300 pixels of scroll, the API above doesn't + // guarantee how much scroll delta will be generated - different browsers + // can consume different amounts for "touch slop" (for example). Ensure the + // overscroll reaches at least 100 pixels which is a fairly conservative + // value. assert_greater_than(overscrolled_y_deltas.length, 0, "There should be at least one overscroll events when overscrolling."); assert_equals(overscrolled_x_deltas.filter(function(x){ return x!=0; }).length, 0, "The deltaX attribute must be 0 when there is no scrolling in x direction."); assert_less_than_equal(Math.max(...overscrolled_y_deltas), 0, "The deltaY attribute must be <= 0 when there is overscrolling in up direction."); @@ -61,10 +71,14 @@ await waitFor(() => { return scrollend_received; }, 'Document did not receive scrollend event.'); + // TODO(bokan): It looks like Chrome inappropriately filters some scroll + // events despite |overscroll-behavior| being set to none. The overscroll + // amount here has been loosened but this should be fixed in Chrome. + // https://crbug.com/1112183. assert_greater_than(overscrolled_y_deltas.length, 0, "There should be at least one overscroll events when overscrolling."); assert_equals(overscrolled_y_deltas.filter(function(x){ return x!=0; }).length, 0, "The deltaY attribute must be 0 when there is no scrolling in y direction."); assert_less_than_equal(Math.max(...overscrolled_x_deltas), 0, "The deltaX attribute must be <= 0 when there is overscrolling in left direction."); - assert_less_than_equal(Math.min(...overscrolled_x_deltas),-100, "The deltaX attribute must be the number of pixels overscrolled."); + assert_less_than_equal(Math.min(...overscrolled_x_deltas),-50, "The deltaX attribute must be the number of pixels overscrolled."); }, 'Tests that the document gets overscroll event with right deltaX/Y attributes.'); }
diff --git a/third_party/blink/web_tests/external/wpt/editing/run/caret-navigation-around-line-break.html b/third_party/blink/web_tests/external/wpt/editing/run/caret-navigation-around-line-break.html deleted file mode 100644 index 7f8576c..0000000 --- a/third_party/blink/web_tests/external/wpt/editing/run/caret-navigation-around-line-break.html +++ /dev/null
@@ -1,136 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<title>Caret navigation around line break</title> -<link rel="author" title="Oriol Brufau" href="mailto:obrufau@igalia.com"> -<meta name="assert" content="This test checks that caret navigation works well around various kinds of line breaks." /> -<style> -.test { - font-size: 16px; - line-height: 20px; - padding: 4px; - width: 5.5ch; - padding: 5px; - font-family: monospace; - word-wrap: break-word; -} -</style> - -<div class="test" contenteditable data-title="no separator" - >line1line2</div> -<div class="test" contenteditable data-title="<br> separator" - >line1<br>line2</div> -<div class="test" contenteditable data-title="<wbr> separator" - >line1<wbr>line2</div> -<div class="test" contenteditable data-title="<span> separator" - >line1<span></span>line2</div> -<div class="test" contenteditable data-title="two <span> separators" - >line1<span></span><span></span>line2</div> - -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="/resources/testdriver.js"></script> -<script src="/resources/testdriver-vendor.js"></script> -<script src="/resources/testdriver-actions.js"></script> -<script> -const KEY_CODE_MAP = { - 'ArrowLeft': '\uE012', - 'ArrowUp': '\uE013', - 'ArrowRight': '\uE014', - 'ArrowDown': '\uE015', -}; - -function click(target, x, y) { - return new test_driver.Actions() - .pointerMove(x, y, {origin: target}) - .pointerDown() - .pointerUp() - .send(); -} - -const s = getSelection(); -for (const test of document.querySelectorAll(".test")) { - const padding = 4; - const halfLineWidth = Math.floor((test.offsetWidth - padding) / 2); - const halfLineHeight = Math.floor(20 / 2); - const hasSeparator = test.firstChild !== test.lastChild; - const line1 = { - node: test.firstChild, - start: 0, - end: "line1".length, - }; - const line2 = { - node: test.lastChild, - start: hasSeparator ? 0 : "line1".length, - end: hasSeparator ? "line2".length : "line1line2".length, - }; - - promise_test(async t => { - // Click at the start of line 1 - await click(test, -halfLineWidth, -halfLineHeight); - assert_equals(s.anchorNode, line1.node, "Caret is in line 1"); - assert_equals(s.anchorOffset, line1.start, "Caret is at the start of line 1"); - - // Move down, expect start of line 2 - await test_driver.send_keys(test, KEY_CODE_MAP.ArrowDown); - assert_equals(s.anchorNode, line2.node, "Caret moved to line 2"); - assert_equals(s.anchorOffset, line2.start, "Caret moved to the start of line 2"); - - // Click at the end of line 1 - await click(test, +halfLineWidth, -halfLineHeight); - range = getSelection().getRangeAt(0); - assert_equals(s.anchorNode, line1.node, "Caret is in line 1"); - assert_equals(s.anchorOffset, line1.end, "Caret is at the end of line 1"); - - // Move down, expect end of line 2 - await test_driver.send_keys(test, KEY_CODE_MAP.ArrowDown); - assert_equals(s.anchorNode, line2.node, "Caret moved to line 2"); - assert_equals(s.anchorOffset, line2.end, "Caret moved to the end of line 2"); - }, test.dataset.title + " - move down"); - - promise_test(async t => { - // Click at the start of line 2 - await click(test, -halfLineWidth, +halfLineHeight); - assert_equals(s.anchorNode, line2.node, "Caret is in line 2"); - assert_equals(s.anchorOffset, line2.start, "Caret is at the start of line 2"); - - // Move up, expect start of line 1 - await test_driver.send_keys(test, KEY_CODE_MAP.ArrowUp); - assert_equals(s.anchorNode, line1.node, "Caret moved to line 1"); - assert_equals(s.anchorOffset, line1.start, "Caret moved to the start of line 1"); - - // Click at the end of line 2 - await click(test, +halfLineWidth, +halfLineHeight); - assert_equals(s.anchorNode, line2.node, "Caret is in line 2"); - assert_equals(s.anchorOffset, line2.end, "Caret is at the end of line 2"); - - // Move up, expect end of line 1 - await test_driver.send_keys(test, KEY_CODE_MAP.ArrowUp); - assert_equals(s.anchorNode, line1.node, "Caret moved to line 1"); - assert_equals(s.anchorOffset, line1.end, "Caret moved to the end of line 1"); - }, test.dataset.title + " - move up"); - - promise_test(async t => { - // Click at the end of line 1 - await click(test, +halfLineWidth, -halfLineHeight); - assert_equals(s.anchorNode, line1.node, "Caret is in line 1"); - assert_equals(s.anchorOffset, line1.end, "Caret is at the end of line 1"); - - // Move right, expect start or start+1 of line 2 - await test_driver.send_keys(test, KEY_CODE_MAP.ArrowRight); - assert_equals(s.anchorNode, line2.node, "Caret moved to line 2"); - assert_in_array(s.anchorOffset, [line2.start, line2.start + 1], "Caret moved to the start or start+1 of line 2"); - }, test.dataset.title + " - move right"); - - promise_test(async t => { - // Click at the start of line 2 - await click(test, -halfLineWidth, +halfLineHeight); - assert_equals(s.anchorNode, line2.node, "Caret is in line 2"); - assert_equals(s.anchorOffset, line2.start, "Caret is at the start of line 2"); - - // Move left, expect end or end-1 of line 1 - await test_driver.send_keys(test, KEY_CODE_MAP.ArrowLeft); - assert_equals(s.anchorNode, line1.node, "Caret moved to line 1"); - assert_in_array(s.anchorOffset, [line1.end, line1.end - 1], "Caret moved to the end or end-1 of line 1"); - }, test.dataset.title + " - move left"); -} -</script>
diff --git a/third_party/blink/web_tests/http/tests/origin_trials/webexposed/rtc-quic-transport-origin-trial-interfaces.html b/third_party/blink/web_tests/http/tests/origin_trials/webexposed/rtc-quic-transport-origin-trial-interfaces.html index 4ae1c795..54e4fd7 100644 --- a/third_party/blink/web_tests/http/tests/origin_trials/webexposed/rtc-quic-transport-origin-trial-interfaces.html +++ b/third_party/blink/web_tests/http/tests/origin_trials/webexposed/rtc-quic-transport-origin-trial-interfaces.html
@@ -4,32 +4,23 @@ tools/origin_trials/generate_token.py http://127.0.0.1:8000 RTCQuicTransport --expire-timestamp=2000000000 --> <meta http-equiv="origin-trial" content="Atq6Jbo2/q1/mFJ9lErFsAqkyeHIwkjR2qIq0jIhkh3UCvNEYAwfwd0cMLR9EF/qobLllgi4vGKKAJ23kdnCNgUAAABYeyJvcmlnaW4iOiAiaHR0cDovLzEyNy4wLjAuMTo4MDAwIiwgImZlYXR1cmUiOiAiUlRDUXVpY1RyYW5zcG9ydCIsICJleHBpcnkiOiAyMDAwMDAwMDAwfQ==" /> -<title>RTCQuicTransport and RTCIceTransport - interfaces exposed by origin trial</title> +<title>RTCIceTransport - interfaces exposed by origin trial</title> <script src="../../resources/testharness.js"></script> <script src="../../resources/testharnessreport.js"></script> <script src="../../resources/origin-trials-helper.js"></script> <script> properties_to_check = { - 'RTCQuicTransport': ['transport', 'state', 'getKey', 'connect', 'listen', - 'stop', 'createStream', 'onstatechange', 'onerror', - 'onquicstream'], 'RTCIceTransport': ['role', 'state', 'gatheringState', 'getLocalCandidates', 'getRemoteCandidates', 'getSelectedCandidatePair', 'getLocalParameters', 'getRemoteParameters', 'onstatechange', 'ongatheringstatechange', 'onselectedcandidatepairchange', 'gather', 'start', 'addRemoteCandidate', 'onicecandidate'], - 'RTCQuicStream': ['transport', 'state', 'readBufferedAmount', - 'maxReadBufferedAmount', 'writeBufferedAmount', - 'readInto', 'write', 'reset', - 'waitForWriteBufferedAmountBelow', - 'waitForReadable', 'onstatechange'], - 'RTCQuicStreamEvent': ['stream'] }; test(t => { OriginTrialsHelper.check_properties_exist(this, properties_to_check); -}, 'RTCQuicTransport and RTCIceTransport properties are available.'); +}, 'RTCIceTransport properties are available.'); </script>
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt index 394b5ef..13c3d00 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -6490,47 +6490,6 @@ attribute @@toStringTag getter candidate method constructor -interface RTCQuicStream : EventTarget - attribute @@toStringTag - getter maxReadBufferedAmount - getter maxWriteBufferedAmount - getter onstatechange - getter readBufferedAmount - getter state - getter transport - getter writeBufferedAmount - method constructor - method readInto - method reset - method waitForReadable - method waitForWriteBufferedAmountBelow - method write - setter onstatechange -interface RTCQuicStreamEvent : Event - attribute @@toStringTag - getter stream - method constructor -interface RTCQuicTransport : EventTarget - attribute @@toStringTag - getter maxDatagramLength - getter onerror - getter onquicstream - getter onstatechange - getter state - getter transport - method connect - method constructor - method createStream - method getKey - method getStats - method listen - method readyToSendDatagram - method receiveDatagrams - method sendDatagram - method stop - setter onerror - setter onquicstream - setter onstatechange interface RTCRtpReceiver static method getCapabilities attribute @@toStringTag
diff --git a/third_party/node/node_modules.py b/third_party/node/node_modules.py index 7e38863..d45f1c3 100755 --- a/third_party/node/node_modules.py +++ b/third_party/node/node_modules.py
@@ -38,8 +38,8 @@ return _path_in_node_modules('svgo', 'bin', 'svgo') -def PathToUglify(): - return _path_in_node_modules('uglify-es', 'bin', 'uglifyjs') +def PathToTerser(): + return _path_in_node_modules('terser', 'bin', 'terser') # Typescript is not approved for general use in Chromium. Email chromium-dev # if you want to use it.
diff --git a/third_party/node/node_modules.tar.gz.sha1 b/third_party/node/node_modules.tar.gz.sha1 index 3a89d20..4cc191db 100644 --- a/third_party/node/node_modules.tar.gz.sha1 +++ b/third_party/node/node_modules.tar.gz.sha1
@@ -1 +1 @@ -a9603a3dc03fa41af9cc5c8ac28d23d1f98dfe3c +57ebd65121c4ed969896f4bd8441077850951083
diff --git a/third_party/node/package-lock.json b/third_party/node/package-lock.json index 5795bd76..2f766bb 100644 --- a/third_party/node/package-lock.json +++ b/third_party/node/package-lock.json
@@ -485,6 +485,11 @@ "concat-map": "0.0.1" } }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -607,11 +612,6 @@ "typical": "^2.6.0" } }, - "commander": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", - "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==" - }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -2212,6 +2212,22 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -2367,6 +2383,28 @@ "wordwrapjs": "^2.0.0-0" } }, + "terser": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.3.3.tgz", + "integrity": "sha512-vRQDIlD+2Pg8YMwVK9kMM3yGylG95EIwzBai1Bw7Ot4OBfn3VP1TZn3EWx4ep2jERN/AmnVaTiGuelZSN7ds/A==", + "requires": { + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.19" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==" + } + } + }, "test-value": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/test-value/-/test-value-2.1.0.tgz", @@ -2435,22 +2473,6 @@ "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=" }, - "uglify-es": { - "version": "3.3.9", - "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz", - "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==", - "requires": { - "commander": "~2.13.0", - "source-map": "~0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } - } - }, "unquote": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz",
diff --git a/third_party/node/package.json b/third_party/node/package.json index d0801ae..c3c1a14 100644 --- a/third_party/node/package.json +++ b/third_party/node/package.json
@@ -8,7 +8,7 @@ "eslint": "5.16.0", "polymer-bundler": "4.0.10", "polymer-css-build": "0.7.0", - "uglify-es": "3.3.9", + "terser": "5.3.3", "svgo": "1.2.0", "typescript": "3.5.3" }
diff --git a/tools/grit/minify_with_uglify.py b/tools/grit/minify_with_uglify.py index 788ffa6..1c12140 100755 --- a/tools/grit/minify_with_uglify.py +++ b/tools/grit/minify_with_uglify.py
@@ -23,8 +23,8 @@ tempfile.NamedTemporaryFile(suffix='.js') as outfile: infile.write(source) infile.flush(); - node.RunNode([ - node_modules.PathToUglify(), infile.name, '--output', outfile.name]) + node.RunNode( + [node_modules.PathToTerser(), infile.name, '--output', outfile.name]) result = outfile.read() return result
diff --git a/tools/memory/OWNERS b/tools/memory/OWNERS index b17b756c..98b6a02264 100644 --- a/tools/memory/OWNERS +++ b/tools/memory/OWNERS
@@ -1,4 +1,4 @@ -bruening@chromium.org glider@chromium.org thestig@chromium.org rnk@chromium.org +vitalybuka@chromium.org
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 9a926e3..3e3b6dd 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -35168,7 +35168,7 @@ <int value="2" label="Last session crashed"/> <int value="3" label="Received survey in current milestone"/> <int value="4" label="Profile too new"/> - <int value="5" label="Last survey too recent"/> + <int value="5" label="Last instance of this survey too recent"/> <int value="6" label="Below probability limit"/> <int value="7" label="Trigger string mismatch"/> <int value="8" label="Not regular browser"/> @@ -35182,6 +35182,7 @@ The survey is over its capacity. </int> <int value="14" label="A survey is already in progress"/> + <int value="15" label="Last instance of any survey too recent"/> </enum> <enum name="HardwareVerifierQualificationStatus">
diff --git a/tools/metrics/histograms/expand_owners.py b/tools/metrics/histograms/expand_owners.py index e57f6e59..762d2267 100644 --- a/tools/metrics/histograms/expand_owners.py +++ b/tools/metrics/histograms/expand_owners.py
@@ -5,7 +5,10 @@ """Functions for extracting emails and components from OWNERS files.""" import extract_histograms +import json import os +import subprocess +import sys import re _EMAIL_PATTERN = r'^[\w\-\+\%\.]+\@[\w\-\+\%\.]+$' @@ -193,6 +196,57 @@ return extracted_emails +def _ComponentFromDirmd(json_data, subpath): + """Returns the component for a subpath based on dirmd output. + + Returns an empty string if no component can be extracted + + Args: + json_data: json object output from dirmd. + subpath: The subpath for the directory being queried, e.g. src/storage'. + """ + # If no component exists for the directory, or if METADATA migration is + # incomplete there will be no component information. + return json_data.get('dirs', {}).get(subpath, + {}).get('monorail', + {}).get('component', '') + + +def _ExtractComponentViaDirmd(path): + """Returns the component for monorail issues at the given path. + + Examples are 'Blink>Storage>FileAPI' and 'UI'. + + Uses dirmd in third_party/depot_tools to parse metadata and walk parent + directories up to the top level of the repo. + + Returns an empty string if no component can be extracted. + + Args: + path: The path to an directory to query, e.g. 'src/storage'. + """ + # Verify that the paths are absolute and the root is a parent of the + # passed in path. + root_path = os.path.abspath(os.path.join(*_DIR_ABOVE_TOOLS)) + path = os.path.abspath(path) + if not path.startswith(root_path): + raise Error('Path {} is not a subpath of the root path {}.'.format( + path, root_path)) + subpath = path[len(root_path) + 1:] or '.' # E.g. content/public. + dirmd_exe = 'dirmd' + if sys.platform == 'win32': + dirmd_exe = 'dirmd.bat' + dirmd_path = os.path.join(*(_DIR_ABOVE_TOOLS + + ['third_party', 'depot_tools', dirmd_exe])) + dirmd = subprocess.Popen([dirmd_path, 'compute', '--root', root_path, path], + stdout=subprocess.PIPE) + if dirmd.wait() != 0: + raise Error('dirmd failed.') + json_out = json.load(dirmd.stdout) + return _ComponentFromDirmd(json_out, subpath) + + +# TODO(crbug/1102997): remove once metadata migration is complete def _ExtractComponentFromOWNERS(path): """Returns the string component associated with the file at the given path. @@ -361,7 +415,9 @@ _UpdateHistogramOwners(histogram, owner, owners_to_add) - component = _ExtractComponentFromOWNERS(path) + component = _ExtractComponentViaDirmd(os.path.dirname(path)) + if not component: + component = _ExtractComponentFromOWNERS(path) if component and component not in components_with_dom_elements: components_with_dom_elements.add(component) _AddHistogramComponent(histogram, component)
diff --git a/tools/metrics/histograms/expand_owners_unittest.py b/tools/metrics/histograms/expand_owners_unittest.py index a8457a1..6605362 100644 --- a/tools/metrics/histograms/expand_owners_unittest.py +++ b/tools/metrics/histograms/expand_owners_unittest.py
@@ -32,6 +32,7 @@ Args: path: An absolute path, e.g. '/some/directory/chromium/src/tools/OWNERS'. """ + # TODO(crbug/1126653): This fails if chromium is not in the path. return path.split('chromium/')[1] @@ -62,6 +63,61 @@ super(ExpandOwnersTest, self).tearDown() shutil.rmtree(self.temp_dir) + def testExpandOwnersUsesMetadataOverOwners(self): + """Checks that DIR_METADATA is used if available""" + with open(os.path.join(self.temp_dir, 'DIR_METADATA'), "w+") as md: + md.write("\n".join(['monorail {', 'component: "Bees"', '}'])) + absolute_path = _MakeOwnersFile('simple_OWNERS', self.temp_dir) + with open(absolute_path, 'w') as owners_file: + owners_file.write('\n'.join( + ['amy@chromium.org', _DEFAULT_COMPONENT, 'rae@chromium.org'])) + self.maxDiff = None + src_relative_path = _GetSrcRelativePath(absolute_path) + histograms = xml.dom.minidom.parseString(""" +<histograms> + +<histogram name="Caffeination" units="mg"> + <owner>joe@chromium.org</owner> + <owner>{path}</owner> + <summary>I like coffee.</summary> +</histogram> + +<histogram name="Maple.Syrup" units="units"> + <owner>joe@chromium.org</owner> + <owner>{path}</owner> + <owner>kim@chromium.org</owner> + <summary>I like maple syrup, too.</summary> +</histogram> + +</histograms> +""".format(path=src_relative_path)) + + expected_histograms = xml.dom.minidom.parseString(""" +<histograms> + +<histogram name="Caffeination" units="mg"> + <owner>joe@chromium.org</owner> + <owner>amy@chromium.org</owner> + <owner>rae@chromium.org</owner> + <summary>I like coffee.</summary> + <component>Bees</component> +</histogram> + +<histogram name="Maple.Syrup" units="units"> + <owner>joe@chromium.org</owner> + <owner>amy@chromium.org</owner> + <owner>rae@chromium.org</owner> + <owner>kim@chromium.org</owner> + <summary>I like maple syrup, too.</summary> + <component>Bees</component> +</histogram> + +</histograms> +""") + + expand_owners.ExpandHistogramsOWNERS(histograms) + self.assertMultiLineEqual(histograms.toxml(), expected_histograms.toxml()) + def testExpandOwnersWithSimpleOWNERSFilePath(self): """Checks that OWNERS files are expanded.""" absolute_path = _MakeOwnersFile('simple_OWNERS', self.temp_dir) @@ -326,7 +382,7 @@ with self.assertRaisesRegexp( expand_owners.Error, - 'The histogram Caffeination must have a valid first owner, i.e. a ' + 'The histogram Caffeination must have a valid primary owner, i.e. a ' 'person with an @google.com or @chromium.org email address.'): expand_owners.ExpandHistogramsOWNERS(histograms_without_valid_first_owner) @@ -349,7 +405,7 @@ with self.assertRaisesRegexp( expand_owners.Error, - 'The histogram Caffeination must have a valid first owner, i.e. a ' + 'The histogram Caffeination must have a valid primary owner, i.e. a ' 'person with an @google.com or @chromium.org email address.'): expand_owners.ExpandHistogramsOWNERS(histograms_without_valid_first_owner) @@ -372,7 +428,7 @@ with self.assertRaisesRegexp( expand_owners.Error, - 'The histogram Caffeination must have a valid first owner, i.e. a ' + 'The histogram Caffeination must have a valid primary owner, i.e. a ' 'person with an @google.com or @chromium.org email address.'): expand_owners.ExpandHistogramsOWNERS(histograms_without_valid_first_owner) @@ -420,11 +476,6 @@ r'No emails could be derived from .*empty_OWNERS\.'): expand_owners.ExpandHistogramsOWNERS(histograms_without_owners_from_file) - with self.assertRaisesRegexp( - expand_owners.Error, - r'The file at .*src/medium/medium/roast/OWNERS does not exist\.'): - expand_owners.ExpandHistogramsOWNERS(histograms_with_fake_file_path) - def testExpandOwnersWithSameOwners(self): """ Checks that no error is raised when all owners in a file are already in @@ -449,8 +500,7 @@ </histograms> """.format(src_relative_path)) - self.assertEqual( - expand_owners.ExpandHistogramsOWNERS(histograms_string), []) + self.assertIsNone(expand_owners.ExpandHistogramsOWNERS(histograms_string)) def testExpandOwnersWithoutOWNERSPathPrefix(self): """Checks that an error is raised when the path is not well-formatted."""
diff --git a/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml b/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml index 74c5dab..4200739 100644 --- a/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml +++ b/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml
@@ -546,7 +546,11 @@ </suffix> <suffix name="PercentSameOrigin2" label="The percentage of bytes loaded from the same origin as the root - frame of the page or ad."/> + frame of the page or ad."> + <obsolete> + Removed 09/20. + </obsolete> + </suffix> <suffix name="SameOrigin" label="The number of bytes loaded from the same origin as the root frame of the page or ad."> @@ -555,9 +559,13 @@ </obsolete> </suffix> <suffix name="SameOrigin2" - label="The number of bytes (including those from both the HTTP cache - and memory cache) loaded from the same origin as the root frame - of the page or ad."/> + label="The number of bytes (including those from both the HTTP cache and + memory cache) loaded from the same origin as the root frame of + the page or ad."> + <obsolete> + Removed 09/20. + </obsolete> + </suffix> <affected-histogram name="PageLoad.Clients.Ads.Bytes.AdFrames.PerFrame"/> <affected-histogram name="PageLoad.Clients.Ads.Bytes.FullPage"/> <affected-histogram
diff --git a/tools/metrics/histograms/histograms_xml/notifications/histograms.xml b/tools/metrics/histograms/histograms_xml/notifications/histograms.xml index 952472e..206327d 100644 --- a/tools/metrics/histograms/histograms_xml/notifications/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/notifications/histograms.xml
@@ -592,7 +592,7 @@ </histogram> <histogram name="Notifications.Triggers.DisplayDelay" units="ms" - expires_after="M82"> + expires_after="M91"> <owner>knollr@chromium.org</owner> <owner>peter@chromium.org</owner> <summary> @@ -601,6 +601,27 @@ </summary> </histogram> +<histogram name="Notifications.Triggers.HasShowTrigger" enum="Boolean" + expires_after="M91"> + <owner>knollr@chromium.org</owner> + <owner>peter@chromium.org</owner> + <summary> + Indicates if the notificaiton has a show trigger. This is recorded before a + notification is written to the database if the notification triggers feature + is enabled. + </summary> +</histogram> + +<histogram name="Notifications.Triggers.ShowTriggerDelay" units="days" + expires_after="M91"> + <owner>knollr@chromium.org</owner> + <owner>peter@chromium.org</owner> + <summary> + The specified delay until the notification is displayed. This is recorded + before writing a notification with a valid show trigger to the database. + </summary> +</histogram> + <histogram name="Notifications.UsingNativeNotificationCenter" enum="BooleanNativeNotifications" expires_after="never"> <!-- expires-never: core to the notification user experience. -->
diff --git a/tools/metrics/histograms/histograms_xml/obsolete_histograms.xml b/tools/metrics/histograms/histograms_xml/obsolete_histograms.xml index 092784b..53e31c4 100644 --- a/tools/metrics/histograms/histograms_xml/obsolete_histograms.xml +++ b/tools/metrics/histograms/histograms_xml/obsolete_histograms.xml
@@ -47725,33 +47725,6 @@ </summary> </histogram> -<histogram name="Notifications.Triggers.HasShowTrigger" enum="Boolean" - expires_after="M86"> - <obsolete> - Removed July 2020 as the Origin Trial is ramping down. - </obsolete> - <owner>knollr@chromium.org</owner> - <owner>peter@chromium.org</owner> - <summary> - Indicates if the notificaiton has a show trigger. This is recorded before a - notification is written to the database if the notification triggers feature - is enabled. - </summary> -</histogram> - -<histogram name="Notifications.Triggers.ShowTriggerDelay" units="days" - expires_after="M86"> - <obsolete> - Removed July 2020 as the Origin Trial is ramping down. - </obsolete> - <owner>knollr@chromium.org</owner> - <owner>peter@chromium.org</owner> - <summary> - The specified delay until the notification is displayed. This is recorded - before writing a notification with a valid show trigger to the database. - </summary> -</histogram> - <histogram name="Notifications.Windows.ImageRetainerDestructionTime" units="ms" expires_after="2018-10-23"> <obsolete>
diff --git a/tools/metrics/histograms/histograms_xml/payment/histograms.xml b/tools/metrics/histograms/histograms_xml/payment/histograms.xml index 3fb4d9d..510fc01 100644 --- a/tools/metrics/histograms/histograms_xml/payment/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/payment/histograms.xml
@@ -22,7 +22,7 @@ <histograms> <histogram name="PaymentRequest.CheckoutFunnel" - enum="PaymentRequestCheckoutFunnelSteps" expires_after="M90"> + enum="PaymentRequestCheckoutFunnelSteps" expires_after="2021-08-01"> <owner>danyao@chromium.org</owner> <owner>web-payments-team@google.com</owner> <summary> @@ -35,14 +35,14 @@ </histogram> <histogram name="PaymentRequest.CheckoutFunnel.Aborted" - enum="PaymentRequestAbortReason" expires_after="M85"> + enum="PaymentRequestAbortReason" expires_after="2021-08-01"> <owner>danyao@chromium.org</owner> <owner>web-payments-team@google.com</owner> <summary>The reason that lead to an abort of the Payment Request.</summary> </histogram> <histogram name="PaymentRequest.CheckoutFunnel.NoShow" - enum="PaymentRequestNoShowReason" expires_after="2020-05-24"> + enum="PaymentRequestNoShowReason" expires_after="2021-08-01"> <owner>danyao@chromium.org</owner> <owner>web-payments-team@google.com</owner> <summary> @@ -51,7 +51,7 @@ </histogram> <histogram name="PaymentRequest.Events" units="bitfield value" - expires_after="2021-01-31"> + expires_after="2021-08-01"> <owner>danyao@chromium.org</owner> <owner>web-payments-team@google.com</owner> <summary> @@ -61,8 +61,8 @@ </histogram> <histogram name="PaymentRequest.JourneyLoggerHasRecorded" enum="Boolean" - expires_after="2021-01-31"> - <owner>sahel@chromium.org</owner> + expires_after="2021-08-01"> + <owner>danyao@chromium.org</owner> <owner>web-payments-team@google.com</owner> <summary> Whether a journey logger has recorded an events bit field or not. @@ -70,8 +70,8 @@ </histogram> <histogram name="PaymentRequest.JourneyLoggerHasRecordedMultipleTimes" - enum="Boolean" expires_after="M85"> - <owner>sahel@chromium.org</owner> + enum="Boolean" expires_after="2021-08-01"> + <owner>danyao@chromium.org</owner> <owner>web-payments-team@google.com</owner> <summary> When a journey logger attempts to record multiple events bit fields. @@ -79,8 +79,8 @@ </histogram> <histogram name="PaymentRequest.MissingContactFields" - enum="PaymentRequestMissingContactFields" expires_after="2021-03-01"> - <owner>sahel@chromium.org</owner> + enum="PaymentRequestMissingContactFields" expires_after="2021-08-01"> + <owner>danyao@chromium.org</owner> <owner>web-payments-team@google.com</owner> <summary> A bitfield representing different missing fields of the contact section in @@ -92,8 +92,8 @@ </histogram> <histogram name="PaymentRequest.MissingPaymentFields" - enum="PaymentRequestMissingPaymentFields" expires_after="2021-03-01"> - <owner>sahel@chromium.org</owner> + enum="PaymentRequestMissingPaymentFields" expires_after="2021-08-01"> + <owner>danyao@chromium.org</owner> <owner>web-payments-team@google.com</owner> <summary> A bitfield representing different missing fields of the payment info section @@ -105,8 +105,8 @@ </histogram> <histogram name="PaymentRequest.MissingShippingFields" - enum="PaymentRequestMissingShippingFields" expires_after="2021-03-01"> - <owner>sahel@chromium.org</owner> + enum="PaymentRequestMissingShippingFields" expires_after="2021-08-01"> + <owner>danyao@chromium.org</owner> <owner>web-payments-team@google.com</owner> <summary> A bitfield representing different missing fields of the shipping section in @@ -118,7 +118,7 @@ </histogram> <histogram name="PaymentRequest.NumberOfSuggestionsShown" units="units" - expires_after="2021-01-24"> + expires_after="2021-08-01"> <owner>danyao@chromium.org</owner> <owner>web-payments-team@google.com</owner> <summary> @@ -127,8 +127,8 @@ </histogram> <histogram name="PaymentRequest.RefetchIconForInstalledApp" enum="Boolean" - expires_after="2021-06-24"> - <owner>sahel@chromium.org</owner> + expires_after="2021-08-01"> + <owner>danyao@chromium.org</owner> <owner>web-payments-team@google.com</owner> <summary> True when chrome crawls to refetch the missing icon of an already installed @@ -138,7 +138,7 @@ <histogram name="PaymentRequest.SecurePaymentConfirmationCredentialIdSizeInBytes" - units="bytes" expires_after="M93"> + units="bytes" expires_after="2021-08-01"> <owner>danyao@chromium.org</owner> <owner>web-payments-team@google.com</owner> <summary> @@ -148,15 +148,15 @@ </histogram> <histogram name="PaymentRequest.ServiceWorkerStatusCodeTimeout" enum="Boolean" - expires_after="2021-05-24"> - <owner>sahel@chromium.org</owner> + expires_after="2021-08-01"> + <owner>danyao@chromium.org</owner> <owner>web-payments-team@google.com</owner> <summary>True when a service worker times out 5 mins after request.</summary> </histogram> <histogram name="PaymentRequest.TimeToCheckout.Completed" units="ms" - expires_after="2021-01-31"> - <owner>sahel@chromium.org</owner> + expires_after="2021-08-01"> + <owner>danyao@chromium.org</owner> <owner>web-payments-team@google.com</owner> <summary> Records the time between a payment request .show() and its completion. @@ -164,10 +164,10 @@ </histogram> <histogram name="PaymentRequest.TimeToCheckout.Completed.Shown" units="ms" - expires_after="2021-01-31"> + expires_after="2021-08-01"> <!-- Name completed by histogram_suffixes name="PaymentRequestCompletedInstrument" --> - <owner>sahel@chromium.org</owner> + <owner>danyao@chromium.org</owner> <owner>web-payments-team@google.com</owner> <summary> Records the time between a payment request .show() and its completion when @@ -176,10 +176,10 @@ </histogram> <histogram name="PaymentRequest.TimeToCheckout.Completed.SkippedShow" - units="ms" expires_after="2021-01-31"> + units="ms" expires_after="2021-08-01"> <!-- Name completed by histogram_suffixes name="PaymentRequestCompletedInstrument" --> - <owner>sahel@chromium.org</owner> + <owner>danyao@chromium.org</owner> <owner>web-payments-team@google.com</owner> <summary> Records the time between a payment request .show() and its completion when @@ -188,8 +188,8 @@ </histogram> <histogram name="PaymentRequest.TimeToCheckout.OtherAborted" units="ms" - expires_after="2021-01-31"> - <owner>sahel@chromium.org</owner> + expires_after="2021-08-01"> + <owner>danyao@chromium.org</owner> <owner>web-payments-team@google.com</owner> <summary> Records the time between a payment request .show() and its termination by @@ -198,10 +198,10 @@ </histogram> <histogram name="PaymentRequest.TimeToCheckout.UserAborted" units="ms" - expires_after="2021-01-31"> + expires_after="2021-08-01"> <!-- Name completed by histogram_suffixes name="PaymentRequestPaymentSheetShowStatus" --> - <owner>sahel@chromium.org</owner> + <owner>danyao@chromium.org</owner> <owner>web-payments-team@google.com</owner> <summary> Records the time between a payment request .show() and its termination by @@ -210,8 +210,8 @@ </histogram> <histogram name="PaymentRequest.TransactionAmount.Completed" - enum="PaymentRequestTransactionSize" expires_after="2021-01-24"> - <owner>sahel@chromium.org</owner> + enum="PaymentRequestTransactionSize" expires_after="2021-08-01"> + <owner>danyao@chromium.org</owner> <owner>web-payments-team@google.com</owner> <summary> Records the transaction amounts completed using payment request API after @@ -220,8 +220,8 @@ </histogram> <histogram name="PaymentRequest.TransactionAmount.Triggered" - enum="PaymentRequestTransactionSize" expires_after="2021-01-31"> - <owner>sahel@chromium.org</owner> + enum="PaymentRequestTransactionSize" expires_after="2021-08-01"> + <owner>danyao@chromium.org</owner> <owner>web-payments-team@google.com</owner> <summary> Records the transaction amounts triggered using payment request API after
diff --git a/tools/metrics/histograms/histograms_xml/service/histograms.xml b/tools/metrics/histograms/histograms_xml/service/histograms.xml index 9fd509f0..799de5b 100644 --- a/tools/metrics/histograms/histograms_xml/service/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/service/histograms.xml
@@ -22,8 +22,9 @@ <histograms> <histogram name="ServiceWorker.AbortPaymentEvent.Time" units="ms" - expires_after="M85"> - <owner>nhiroki@chromium.org</owner> + expires_after="2021-08-01"> + <owner>danyao@chromium.org</owner> + <owner>web-payments-team@google.com</owner> <owner>jinho.bang@samsung.com</owner> <summary> The time taken between dispatching an AbortPaymentEvent to a Service Worker @@ -169,8 +170,9 @@ </histogram> <histogram name="ServiceWorker.CanMakePaymentEvent.Time" units="ms" - expires_after="2020-04-19"> - <owner>nhiroki@chromium.org</owner> + expires_after="2021-08-01"> + <owner>danyao@chromium.org</owner> + <owner>web-payments-team@google.com</owner> <owner>jinho.bang@samsung.com</owner> <summary> The time taken between dispatching an CanMakePaymentEvent to a Service @@ -661,8 +663,9 @@ </histogram> <histogram name="ServiceWorker.PaymentRequestEvent.Time" units="ms" - expires_after="M81"> - <owner>nhiroki@chromium.org</owner> + expires_after="2021-08-01"> + <owner>danyao@chromium.org</owner> + <owner>web-payments-team@google.com</owner> <owner>jinho.bang@samsung.com</owner> <summary> The time taken between dispatching an PaymentRequestEvent to a Service
diff --git a/tools/metrics/histograms/histograms_xml/windows/histograms.xml b/tools/metrics/histograms/histograms_xml/windows/histograms.xml index 727b22f..e30e2381 100644 --- a/tools/metrics/histograms/histograms_xml/windows/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/windows/histograms.xml
@@ -154,7 +154,7 @@ <owner>wfh@chromium.org</owner> <owner>brucedawson@chromium.org</owner> <summary> - The Windows version (base::win::Version) as reported by VeryQueryValue() on + The Windows version (base::win::Version) as reported by VerQueryValue() on kernel32.dll. This is queried shortly after startup. </summary> </histogram> @@ -222,11 +222,28 @@ <owner>brucedawson@chromium.org</owner> <summary> A 32-bit value formed from combining the minor and patch level of the - currently running Windows operating system. E.g. "Windows 10 OS Version - 1809 (Build 17763.503)" would be 17763 (0x4563), combined with 503 - (0x1F7) = 0x456301F7. If either minor or patch level exceeds the value that - can fit in a 16-bit unsigned integer, then this histogram will report 0. - Reported once, shortly after browser startup. + currently running Windows operating system as reported by GetVersionEx(). + E.g. "Windows 10 OS Version 1809 (Build 17763.503)" would be 17763 + (0x4563), combined with 503 (0x1F7) = 0x456301F7. If either minor or patch + level exceeds the value that can fit in a 16-bit unsigned integer, then this + histogram will report 0. Reported once, shortly after browser startup. + </summary> +</histogram> + +<histogram name="Windows.PatchLevelKernel32" enum="WindowsPatchLevel" + expires_after="never"> +<!-- expires-never: Needed to measure Windows ecosystem. --> + + <owner>wfh@chromium.org</owner> + <owner>brucedawson@chromium.org</owner> + <summary> + A 32-bit value formed from combining the minor and patch level of the + currently running Windows operating system as reported by VerQueryValue() of + kernel32.dll. E.g. "Windows 10 OS Version 1809 (Build 17763.503)" + would be 17763 (0x4563), combined with 503 (0x1F7) = 0x456301F7. If either + minor or patch level exceeds the value that can fit in a 16-bit unsigned + integer, then this histogram will report 0. Reported once, shortly after + browser startup. </summary> </histogram>
diff --git a/tools/metrics/histograms/merge_xml.py b/tools/metrics/histograms/merge_xml.py index 510a7d6..697412f 100755 --- a/tools/metrics/histograms/merge_xml.py +++ b/tools/metrics/histograms/merge_xml.py
@@ -128,8 +128,8 @@ """ node = doc.createElement(tag) for child in children: - # if child.tagName == 'histograms': - # expand_owners.ExpandHistogramsOWNERS(child) + if child.tagName == 'histograms': + expand_owners.ExpandHistogramsOWNERS(child) node.appendChild(child) return node
diff --git a/tools/metrics/metrics_python_tests.py b/tools/metrics/metrics_python_tests.py index a51946ec..5c9cafa 100755 --- a/tools/metrics/metrics_python_tests.py +++ b/tools/metrics/metrics_python_tests.py
@@ -23,6 +23,8 @@ sys.exit( typ.main(tests=resolve( 'actions/extract_actions_test.py', + # TODO(crbug/1126653): Turn back on once tests can pass again. + # 'histograms/expand_owners_unittest.py', 'histograms/extract_histograms_test.py', 'histograms/generate_expired_histograms_array_unittest.py', 'histograms/pretty_print_test.py',
diff --git a/tools/perf/core/tbmv3/metrics/webview_power_usage_metric.proto b/tools/perf/core/tbmv3/metrics/webview_power_usage_metric.proto index 53141c8..2809a8253 100644 --- a/tools/perf/core/tbmv3/metrics/webview_power_usage_metric.proto +++ b/tools/perf/core/tbmv3/metrics/webview_power_usage_metric.proto
@@ -11,21 +11,28 @@ // power use through the CPU time they consume at different core frequencies. // Output values are in milliampere-seconds. +message UsageByCoreType { + double little_cores_mas = 1; + double big_cores_mas = 2; + double bigger_core_mas = 3; + double total_mas = 4; // sum of the fields above +} + message EstimatedWebViewAppPowerUsage { // Host app package name. string app_name = 1; - // Total app’s power consumption in milliampere-seconds. - // Includes renderer processes. - double total_app_power_mas = 2; + // Only browser + in-process renderer slices. + double webview_browser_slices_mas = 2; - // This is the sum of the following 3 fields. - // Includes renderer processes. - double webview_power_mas = 3; + // WebView-only browser + in-process renderer threads. + UsageByCoreType webview_only_usage = 3; - double webview_power_little_cores_mas = 4; - double webview_power_big_cores_mas = 5; - double webview_power_bigger_cores_mas = 6; + // All threads of the host app. + UsageByCoreType total_app_usage = 4; + + // All out-of-process renderers. + UsageByCoreType renderer_usage = 5; } message WebViewPowerUsageMetric {
diff --git a/tools/perf/core/tbmv3/metrics/webview_power_usage_metric.sql b/tools/perf/core/tbmv3/metrics/webview_power_usage_metric.sql index c9a0dc98..f66c37b 100644 --- a/tools/perf/core/tbmv3/metrics/webview_power_usage_metric.sql +++ b/tools/perf/core/tbmv3/metrics/webview_power_usage_metric.sql
@@ -13,15 +13,38 @@ 'estimated_webview_app_power_usage', (SELECT RepeatedField( EstimatedWebViewAppPowerUsage( - 'app_name', app_name, - 'webview_power_mas', webview_power_mas, - 'total_app_power_mas', total_app_power_mas, - 'webview_power_little_cores_mas', webview_power_little_cores_mas, - 'webview_power_big_cores_mas', webview_power_big_cores_mas, - 'webview_power_bigger_cores_mas', webview_power_bigger_cores_mas - ) + 'app_name', webview_browser_slices_power_summary.app_name, + 'webview_browser_slices_mas', webview_browser_slices_power_summary.power_mas, + 'webview_only_usage', + (SELECT UsageByCoreType( + 'little_cores_mas', webview_only_power_output.little_cores_mas, + 'big_cores_mas', webview_only_power_output.big_cores_mas, + 'bigger_cores_mas', webview_only_power_output.bigger_cores_mas, + 'total_mas', webview_only_power_output.total_mas + )), + 'total_app_usage', + (SELECT UsageByCoreType( + 'little_cores_mas', total_app_power_output.little_cores_mas, + 'big_cores_mas', total_app_power_output.big_cores_mas, + 'bigger_cores_mas', total_app_power_output.bigger_cores_mas, + 'total_mas', total_app_power_output.total_mas + )), + 'renderer_usage', + (SELECT UsageByCoreType( + 'little_cores_mas', webview_renderer_power_output.little_cores_mas, + 'big_cores_mas', webview_renderer_power_output.big_cores_mas, + 'bigger_cores_mas', webview_renderer_power_output.bigger_cores_mas, + 'total_mas', webview_renderer_power_output.total_mas + )) + ) ) - FROM webview_power_summary + FROM webview_browser_slices_power_summary + INNER JOIN webview_only_power_output + ON webview_browser_slices_power_summary.app_name = webview_only_power_output.app_name + INNER JOIN total_app_power_output + ON webview_browser_slices_power_summary.app_name = total_app_power_output.app_name + INNER JOIN webview_renderer_power_output + ON webview_browser_slices_power_summary.app_name = webview_renderer_power_output.app_name ), 'total_device_power_mas', (SELECT power_mas FROM total_device_power)
diff --git a/tools/valgrind/OWNERS b/tools/valgrind/OWNERS index 2989131..e52b970 100644 --- a/tools/valgrind/OWNERS +++ b/tools/valgrind/OWNERS
@@ -1,3 +1 @@ -bruening@chromium.org -glider@chromium.org -thestig@chromium.org +file://tools/memory/OWNERS
diff --git a/tools/vscode/keybindings.json5 b/tools/vscode/keybindings.json5 index e1e0b06..3a83b89f 100644 --- a/tools/vscode/keybindings.json5 +++ b/tools/vscode/keybindings.json5
@@ -1,6 +1,6 @@ // Place your key bindings in this file to overwrite the defaults [ - // Run the task marked as "isTestCommand": true, see tasks.json. + // Run the task marked as "group": "test", see tasks.json. { "key": "ctrl+shift+t", "command": "workbench.action.tasks.test" }, // Jump to the previous change in the built-in diff tool. { "key": "ctrl+up", "command": "workbench.action.compareEditor.previousChange" }, @@ -16,7 +16,7 @@ // key binding from the C/C++ extension as I found it to be slow). { "key": "alt+o", "command": "togglehs.toggleHS" }, // Quickly run a task, see tasks.json. Since we named them 1-, 2- etc., it is - // suffucient to press the corresponding number. + // sufficient to press the corresponding number. { "key": "ctrl+r", "command": "workbench.action.tasks.runTask", "when": "!inDebugMode" }, // The following keybindings are useful on laptops with small keyboards such as
diff --git a/ui/accessibility/accessibility_features.cc b/ui/accessibility/accessibility_features.cc index 73789da..403fc18 100644 --- a/ui/accessibility/accessibility_features.cc +++ b/ui/accessibility/accessibility_features.cc
@@ -21,7 +21,7 @@ // Enable exposing the <html> element to the browser process AXTree // (as an ignored node). const base::Feature kEnableAccessibilityExposeHTMLElement{ - "AccessibilityExposeHTMLElement", base::FEATURE_DISABLED_BY_DEFAULT}; + "AccessibilityExposeHTMLElement", base::FEATURE_ENABLED_BY_DEFAULT}; bool IsAccessibilityExposeHTMLElementEnabled() { return base::FeatureList::IsEnabled(
diff --git a/ui/base/prediction/prediction_metrics_handler.cc b/ui/base/prediction/prediction_metrics_handler.cc index e782e67..f1d9b1d8 100644 --- a/ui/base/prediction/prediction_metrics_handler.cc +++ b/ui/base/prediction/prediction_metrics_handler.cc
@@ -2,14 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <utility> + #include "ui/base/prediction/prediction_metrics_handler.h" #include "base/metrics/histogram_functions.h" +#include "base/strings/strcat.h" namespace ui { -PredictionMetricsHandler::PredictionMetricsHandler() {} -PredictionMetricsHandler::~PredictionMetricsHandler() {} +PredictionMetricsHandler::PredictionMetricsHandler(const char* histogram_name) + : histogram_name_(std::move(histogram_name)) {} +PredictionMetricsHandler::~PredictionMetricsHandler() = default; void PredictionMetricsHandler::AddRealEvent(const gfx::PointF& pos, const base::TimeTicks& time_stamp, @@ -130,25 +134,25 @@ for (int i = 0; i < first_needed_event - 1; i++) events_queue_.pop_front(); - std::string kPredictionMetrics = "Event.InputEventPrediction.Scroll."; - double score = ComputeOverUnderPredictionMetric(); if (score >= 0) { - base::UmaHistogramCounts1000(kPredictionMetrics + "OverPrediction", score); + base::UmaHistogramCounts1000( + base::StrCat({histogram_name_, ".OverPrediction"}), score); } else { - base::UmaHistogramCounts1000(kPredictionMetrics + "UnderPrediction", - -score); + base::UmaHistogramCounts1000( + base::StrCat({histogram_name_, ".UnderPrediction"}), -score); } // Need |last_predicted_| to compute WrongDirection and Jitter metrics. if (!last_predicted_.has_value()) return; - base::UmaHistogramBoolean(kPredictionMetrics + "WrongDirection", + base::UmaHistogramBoolean(base::StrCat({histogram_name_, ".WrongDirection"}), ComputeWrongDirectionMetric()); - base::UmaHistogramCounts1000(kPredictionMetrics + "PredictionJitter", - ComputePredictionJitterMetric()); - base::UmaHistogramCounts1000(kPredictionMetrics + "VisualJitter", + base::UmaHistogramCounts1000( + base::StrCat({histogram_name_, ".PredictionJitter"}), + ComputePredictionJitterMetric()); + base::UmaHistogramCounts1000(base::StrCat({histogram_name_, ".VisualJitter"}), ComputeVisualJitterMetric()); }
diff --git a/ui/base/prediction/prediction_metrics_handler.h b/ui/base/prediction/prediction_metrics_handler.h index 648ccdd..24167f5 100644 --- a/ui/base/prediction/prediction_metrics_handler.h +++ b/ui/base/prediction/prediction_metrics_handler.h
@@ -25,7 +25,7 @@ // few metrics. class COMPONENT_EXPORT(UI_BASE_PREDICTION) PredictionMetricsHandler { public: - explicit PredictionMetricsHandler(); + explicit PredictionMetricsHandler(const char* histogram_name); ~PredictionMetricsHandler(); // Struct used to store predicted and real event information. @@ -103,6 +103,12 @@ base::Optional<gfx::PointF> last_predicted_ = base::nullopt; // The first real event position which time is later than the predicted time. gfx::PointF next_real_; + + // Beginning of the full histogram name. It will have the various metrics' + // names (.OverPrediction, .UnderPrediction, .WrongDirection, + // .PredictionJitter, .VisualJitter) appended to it when counting the metric + // in a histogram. + const char* const histogram_name_; }; } // namespace ui
diff --git a/ui/base/prediction/prediction_metrics_handler_unittest.cc b/ui/base/prediction/prediction_metrics_handler_unittest.cc index f44df0d..fcfa9c0 100644 --- a/ui/base/prediction/prediction_metrics_handler_unittest.cc +++ b/ui/base/prediction/prediction_metrics_handler_unittest.cc
@@ -29,7 +29,8 @@ explicit PredictionMetricsHandlerTest() {} void SetUp() override { - metrics_handler_ = std::make_unique<PredictionMetricsHandler>(); + metrics_handler_ = std::make_unique<PredictionMetricsHandler>( + "Event.InputEventPrediction.Scroll"); histogram_tester_ = std::make_unique<base::HistogramTester>(); }
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc index e15964c0..c3d7fdc 100644 --- a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc +++ b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc
@@ -152,6 +152,19 @@ plane_list->atomic_property_set.reset(drmModeAtomicAlloc()); } +void HardwareDisplayPlaneManager::RestoreCurrentPlaneList( + HardwareDisplayPlaneList* plane_list) const { + for (auto* plane : plane_list->plane_list) { + plane->set_in_use(false); + } + for (auto* plane : plane_list->old_plane_list) { + plane->set_in_use(true); + } + plane_list->plane_list.clear(); + plane_list->legacy_page_flips.clear(); + plane_list->atomic_property_set.reset(drmModeAtomicAlloc()); +} + void HardwareDisplayPlaneManager::BeginFrame( HardwareDisplayPlaneList* plane_list) { for (auto* plane : plane_list->old_plane_list) { @@ -174,8 +187,7 @@ HardwareDisplayPlane* hw_plane = FindNextUnusedPlane(&plane_idx, crtc_index, plane); if (!hw_plane) { - LOG(ERROR) << "Failed to find a free plane for crtc " << crtc_id; - ResetCurrentPlaneList(plane_list); + RestoreCurrentPlaneList(plane_list); return false; } @@ -191,7 +203,7 @@ crop_rect.width() << 16, crop_rect.height() << 16); if (!SetPlaneData(plane_list, hw_plane, plane, crtc_id, fixed_point_rect)) { - ResetCurrentPlaneList(plane_list); + RestoreCurrentPlaneList(plane_list); return false; }
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h index e5d3448..92d24a5 100644 --- a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h +++ b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h
@@ -223,7 +223,13 @@ const DrmOverlayPlane& overlay, uint32_t crtc_index) const; + // Resets |plane_list| setting all planes to unused. + // Frees any temporary data structure in |plane_list| used for pageflipping. void ResetCurrentPlaneList(HardwareDisplayPlaneList* plane_list) const; + // Restores |plane_list| planes |in_use| flag to what it was before + // BeginFrame was called. + // Frees any temporary data structure in |plane_list| used for pageflipping. + void RestoreCurrentPlaneList(HardwareDisplayPlaneList* plane_list) const; // Populates scanout formats supported by all planes. void PopulateSupportedFormats();
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.cc b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.cc index a79fea8..27db5f99 100644 --- a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.cc +++ b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.cc
@@ -168,9 +168,12 @@ } if (test_only) { - for (HardwareDisplayPlane* plane : plane_list->plane_list) { + for (auto* plane : plane_list->plane_list) { plane->set_in_use(false); } + for (auto* plane : plane_list->old_plane_list) { + plane->set_in_use(true); + } } else { plane_list->plane_list.swap(plane_list->old_plane_list); }
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc index 5e0beab9..a14bfff1 100644 --- a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc +++ b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc
@@ -619,6 +619,72 @@ EXPECT_EQ(0u, GetPlanePropertyValue(kPlaneOffset + 1, "FB_ID")); } +TEST_P(HardwareDisplayPlaneManagerAtomicTest, AssignPlanesRestoresInUse) { + InitializeDrmState(/*crtc_count=*/2, /*planes_per_crtc=*/2); + fake_drm_->InitializeState(crtc_properties_, connector_properties_, + plane_properties_, property_names_, use_atomic_); + + ui::DrmOverlayPlaneList assigns; + scoped_refptr<ui::DrmFramebuffer> primary_buffer = + CreateBuffer(kDefaultBufferSize); + scoped_refptr<ui::DrmFramebuffer> overlay_buffer = + CreateBuffer(gfx::Size(1, 1)); + assigns.push_back(ui::DrmOverlayPlane(primary_buffer, nullptr)); + assigns.push_back(ui::DrmOverlayPlane(overlay_buffer, nullptr)); + ui::HardwareDisplayPlaneList hdpl; + + scoped_refptr<ui::PageFlipRequest> page_flip_request = + base::MakeRefCounted<ui::PageFlipRequest>(base::TimeDelta()); + fake_drm_->plane_manager()->BeginFrame(&hdpl); + EXPECT_TRUE(fake_drm_->plane_manager()->AssignOverlayPlanes( + &hdpl, assigns, crtc_properties_[0].id)); + EXPECT_TRUE(fake_drm_->plane_manager()->Commit( + &hdpl, /*should_modeset*/ false, page_flip_request, nullptr)); + EXPECT_TRUE(fake_drm_->plane_manager()->planes().front()->in_use()); + assigns.push_back(ui::DrmOverlayPlane(overlay_buffer, nullptr)); + + fake_drm_->plane_manager()->BeginFrame(&hdpl); + // Assign overlay planes will fail since there aren't enough planes. + EXPECT_FALSE(fake_drm_->plane_manager()->AssignOverlayPlanes( + &hdpl, assigns, crtc_properties_[0].id)); + + // The primary plane should still be in use since we failed to assign + // planes and did not commit a new configuration. + EXPECT_TRUE(fake_drm_->plane_manager()->planes().front()->in_use()); +} + +TEST_P(HardwareDisplayPlaneManagerAtomicTest, PageflipTestRestoresInUse) { + InitializeDrmState(/*crtc_count=*/2, /*planes_per_crtc=*/2); + fake_drm_->InitializeState(crtc_properties_, connector_properties_, + plane_properties_, property_names_, use_atomic_); + + ui::DrmOverlayPlaneList assigns; + scoped_refptr<ui::DrmFramebuffer> primary_buffer = + CreateBuffer(kDefaultBufferSize); + scoped_refptr<ui::DrmFramebuffer> overlay_buffer = + CreateBuffer(gfx::Size(1, 1)); + assigns.push_back(ui::DrmOverlayPlane(primary_buffer, nullptr)); + assigns.push_back(ui::DrmOverlayPlane(overlay_buffer, nullptr)); + ui::HardwareDisplayPlaneList hdpl; + + scoped_refptr<ui::PageFlipRequest> page_flip_request = + base::MakeRefCounted<ui::PageFlipRequest>(base::TimeDelta()); + fake_drm_->plane_manager()->BeginFrame(&hdpl); + EXPECT_TRUE(fake_drm_->plane_manager()->AssignOverlayPlanes( + &hdpl, assigns, crtc_properties_[0].id)); + EXPECT_TRUE(fake_drm_->plane_manager()->Commit( + &hdpl, /*should_modeset*/ false, page_flip_request, nullptr)); + assigns.clear(); + fake_drm_->plane_manager()->BeginFrame(&hdpl); + EXPECT_TRUE(fake_drm_->plane_manager()->AssignOverlayPlanes( + &hdpl, assigns, crtc_properties_[0].id)); + EXPECT_TRUE(fake_drm_->plane_manager()->Commit( + &hdpl, /*should_modeset*/ false, nullptr, nullptr)); + // The primary plane should still be in use since the commit was + // a pageflip test and did not change any KMS state. + EXPECT_TRUE(fake_drm_->plane_manager()->planes().front()->in_use()); +} + TEST_P(HardwareDisplayPlaneManagerAtomicTest, MultipleFrames) { ui::DrmOverlayPlaneList assigns; assigns.push_back(ui::DrmOverlayPlane(fake_buffer_, nullptr));
diff --git a/ui/views/bubble/bubble_dialog_model_host.cc b/ui/views/bubble/bubble_dialog_model_host.cc index 64376a9b..f467c97f 100644 --- a/ui/views/bubble/bubble_dialog_model_host.cc +++ b/ui/views/bubble/bubble_dialog_model_host.cc
@@ -207,7 +207,11 @@ // TODO(pbos): Note that this is in place because GridLayout doesn't handle // View removal correctly (keeps stale pointers). This is in place to prevent // UAFs between Widget::Close() and destroying |this|. - SetLayoutManager(nullptr); + // TODO(pbos): This uses a non-nullptr LayoutManager only to prevent infinite + // recursion in CalculatePreferredSize(). CalculatePreferredSize calls + // GetHeightForWidth(), which if there is no LayoutManager calls + // GetPreferredSize(). See https://crbug.com/1128500. + SetLayoutManager(std::make_unique<GridLayout>()); // TODO(pbos): Consider turning this into for-each-field remove field. RemoveAllChildViews(true);
diff --git a/ui/views/controls/scroll_view.cc b/ui/views/controls/scroll_view.cc index 8143051..36ee16f 100644 --- a/ui/views/controls/scroll_view.cc +++ b/ui/views/controls/scroll_view.cc
@@ -24,12 +24,28 @@ #include "ui/views/border.h" #include "ui/views/controls/focus_ring.h" #include "ui/views/style/platform_style.h" +#include "ui/views/view.h" #include "ui/views/widget/widget.h" namespace views { namespace { +// Returns the combined scroll amount given separate x and y offsets. This is +// used in the "treat all scroll events as horizontal" case when there is both +// an x and y offset and we do not want them to add in unintuitive ways. +// +// The current approach is to return whichever offset has the larger absolute +// value, which should at least handle the case in which the gesture is mostly +// vertical or horizontal. It does mean that for a gesture at 135° or 315° from +// the x axis there is a breakpoint where scroll direction reverses, but we do +// not typically expect users to try to scroll a horizontal-scroll-only view at +// this exact angle. +template <class T> +T CombineScrollOffsets(T x, T y) { + return std::abs(x) >= std::abs(y) ? x : y; +} + class ScrollCornerView : public View { public: ScrollCornerView() = default; @@ -303,11 +319,42 @@ contents_viewport_->height()); } -void ScrollView::SetHideHorizontalScrollBar(bool visible) { - if (hide_horizontal_scrollbar_ == visible) +void ScrollView::SetHorizontalScrollBarMode( + ScrollBarMode horizontal_scroll_bar_mode) { + if (horizontal_scroll_bar_mode_ == horizontal_scroll_bar_mode) return; - hide_horizontal_scrollbar_ = visible; - OnPropertyChanged(&hide_horizontal_scrollbar_, kPropertyEffectsPaint); + horizontal_scroll_bar_mode_ = horizontal_scroll_bar_mode; + OnPropertyChanged(&horizontal_scroll_bar_mode_, kPropertyEffectsPaint); +} + +void ScrollView::SetVerticalScrollBarMode( + ScrollBarMode vertical_scroll_bar_mode) { + if (vertical_scroll_bar_mode_ == vertical_scroll_bar_mode) + return; + + // Enabling vertical scrolling is incompatible with all scrolling being + // interpreted as horizontal. + DCHECK(!treat_all_scroll_events_as_horizontal_ || + vertical_scroll_bar_mode == ScrollBarMode::kDisabled); + + vertical_scroll_bar_mode_ = vertical_scroll_bar_mode; + OnPropertyChanged(&vertical_scroll_bar_mode_, kPropertyEffectsPaint); +} + +void ScrollView::SetTreatAllScrollEventsAsHorizontal( + bool treat_all_scroll_events_as_horizontal) { + if (treat_all_scroll_events_as_horizontal_ == + treat_all_scroll_events_as_horizontal) { + return; + } + treat_all_scroll_events_as_horizontal_ = + treat_all_scroll_events_as_horizontal; + OnPropertyChanged(&treat_all_scroll_events_as_horizontal_, + kPropertyEffectsNone); + + // Since this effectively disables vertical scrolling, don't show a + // vertical scrollbar. + SetVerticalScrollBarMode(ScrollBarMode::kDisabled); } void ScrollView::SetDrawOverflowIndicator(bool draw_overflow_indicator) { @@ -383,9 +430,10 @@ } void ScrollView::Layout() { - // When horizontal scrollbar is disabled, it should not matter - // if its OverlapsContent matches vertical bar's. - if (!hide_horizontal_scrollbar_) { + // When either scrollbar is disabled, it should not matter + // if its OverlapsContent matches other bar's. + if (horizontal_scroll_bar_mode_ == ScrollBarMode::kEnabled && + vertical_scroll_bar_mode_ == ScrollBarMode::kEnabled) { #if defined(OS_APPLE) // On Mac, scrollbars may update their style one at a time, so they may // temporarily be of different types. Refuse to lay out at this point. @@ -578,10 +626,10 @@ bool processed = false; // Give vertical scrollbar priority - if (vert_sb_->GetVisible()) + if (IsVerticalScrollEnabled()) processed = vert_sb_->OnKeyPressed(event); - if (!processed && horiz_sb_->GetVisible()) + if (!processed && IsHorizontalScrollEnabled()) processed = horiz_sb_->OnKeyPressed(event); return processed; @@ -590,12 +638,21 @@ bool ScrollView::OnMouseWheel(const ui::MouseWheelEvent& e) { bool processed = false; - // TODO(https://crbug.com/615948): Use composited scrolling. - if (vert_sb_->GetVisible()) - processed = vert_sb_->OnMouseWheel(e); + const ui::MouseWheelEvent to_propagate = + treat_all_scroll_events_as_horizontal_ + ? ui::MouseWheelEvent( + e, CombineScrollOffsets(e.x_offset(), e.y_offset()), 0) + : e; - if (horiz_sb_->GetVisible()) - processed = horiz_sb_->OnMouseWheel(e) || processed; + // TODO(https://crbug.com/615948): Use composited scrolling. + if (IsVerticalScrollEnabled()) + processed = vert_sb_->OnMouseWheel(to_propagate); + + if (IsHorizontalScrollEnabled()) { + // When there is no vertical scrollbar, allow vertical scroll events to be + // interpreted as horizontal scroll events. + processed |= horiz_sb_->OnMouseWheel(to_propagate); + } return processed; } @@ -604,13 +661,28 @@ if (!contents_) return; + // Possibly force the scroll event to horizontal based on the configuration + // option. + ui::ScrollEvent e = + treat_all_scroll_events_as_horizontal_ + ? ui::ScrollEvent( + event->type(), event->location_f(), event->root_location_f(), + event->time_stamp(), event->flags(), + CombineScrollOffsets(event->x_offset(), event->y_offset()), + 0.0f, + CombineScrollOffsets(event->y_offset_ordinal(), + event->x_offset_ordinal()), + 0.0f, event->finger_count(), event->momentum_phase(), + event->scroll_event_phase()) + : *event; + ui::ScrollInputHandler* compositor_scroller = GetWidget()->GetCompositor()->scroll_input_handler(); if (compositor_scroller) { DCHECK(scroll_with_layers_enabled_); - if (compositor_scroller->OnScrollEvent(*event, contents_->layer())) { - event->SetHandled(); - event->StopPropagation(); + if (compositor_scroller->OnScrollEvent(e, contents_->layer())) { + e.SetHandled(); + e.StopPropagation(); } } @@ -618,9 +690,15 @@ // scrollbars that they may be about scroll, or that they may need to cancel // UI feedback once the scrolling direction is known. if (horiz_sb_) - horiz_sb_->ObserveScrollEvent(*event); + horiz_sb_->ObserveScrollEvent(e); if (vert_sb_) - vert_sb_->ObserveScrollEvent(*event); + vert_sb_->ObserveScrollEvent(e); + + // Need to copy state back to original event. + if (e.handled()) + event->SetHandled(); + if (e.stopped_propagation()) + event->StopPropagation(); } void ScrollView::OnGestureEvent(ui::GestureEvent* event) { @@ -632,14 +710,20 @@ event->type() == ui::ET_GESTURE_SCROLL_END || event->type() == ui::ET_SCROLL_FLING_START; + // Note: we will not invert gesture events because it will be confusing to + // have a vertical finger gesture on a touchscreen cause the scroll pane to + // scroll horizontally. + // TODO(https://crbug.com/615948): Use composited scrolling. - if (vert_sb_->GetVisible()) { - if (vert_sb_->bounds().Contains(event->location()) || scroll_event) - vert_sb_->OnGestureEvent(event); + if (IsVerticalScrollEnabled() && + (scroll_event || (vert_sb_->GetVisible() && + vert_sb_->bounds().Contains(event->location())))) { + vert_sb_->OnGestureEvent(event); } - if (!event->handled() && horiz_sb_->GetVisible()) { - if (horiz_sb_->bounds().Contains(event->location()) || scroll_event) - horiz_sb_->OnGestureEvent(event); + if (!event->handled() && IsHorizontalScrollEnabled() && + (scroll_event || (horiz_sb_->GetVisible() && + horiz_sb_->bounds().Contains(event->location())))) { + horiz_sb_->OnGestureEvent(event); } } @@ -719,13 +803,13 @@ return; gfx::ScrollOffset offset = CurrentOffset(); - if (source == horiz_sb_.get() && horiz_sb_->GetVisible()) { + if (source == horiz_sb_.get() && IsHorizontalScrollEnabled()) { position = AdjustPosition(offset.x(), position, contents_->width(), contents_viewport_->width()); if (offset.x() == position) return; offset.set_x(position); - } else if (source == vert_sb_.get() && vert_sb_->GetVisible()) { + } else if (source == vert_sb_.get() && IsVerticalScrollEnabled()) { position = AdjustPosition(offset.y(), position, contents_->height(), contents_viewport_->height()); if (offset.y() == position) @@ -783,8 +867,10 @@ } void ScrollView::ScrollContentsRegionToBeVisible(const gfx::Rect& rect) { - if (!contents_ || (!horiz_sb_->GetVisible() && !vert_sb_->GetVisible())) + if (!contents_ || + (!IsHorizontalScrollEnabled() && !IsVerticalScrollEnabled())) { return; + } // Figure out the maximums for this scroll view. const int contents_max_x = @@ -830,9 +916,19 @@ const gfx::Size& content_size, bool* horiz_is_shown, bool* vert_is_shown) const { - if (hide_horizontal_scrollbar_) { + const bool horizontal_enabled = + horizontal_scroll_bar_mode_ == ScrollBarMode::kEnabled; + const bool vertical_enabled = + vertical_scroll_bar_mode_ == ScrollBarMode::kEnabled; + if (!horizontal_enabled) { *horiz_is_shown = false; - *vert_is_shown = content_size.height() > vp_size.height(); + *vert_is_shown = + vertical_enabled && content_size.height() > vp_size.height(); + return; + } + if (!vertical_enabled) { + *vert_is_shown = false; + *horiz_is_shown = content_size.width() > vp_size.width(); return; } @@ -876,12 +972,12 @@ return; const gfx::ScrollOffset offset = CurrentOffset(); - if (horiz_sb_->GetVisible()) { + if (IsHorizontalScrollEnabled()) { int vw = contents_viewport_->width(); int cw = contents_->width(); horiz_sb_->Update(vw, cw, offset.x()); } - if (vert_sb_->GetVisible()) { + if (IsVerticalScrollEnabled()) { int vh = contents_viewport_->height(); int ch = contents_->height(); vert_sb_->Update(vh, ch, offset.y()); @@ -919,6 +1015,28 @@ return contents_viewport_->layer() != nullptr; } +bool ScrollView::IsHorizontalScrollEnabled() const { + switch (horizontal_scroll_bar_mode_) { + case ScrollBarMode::kDisabled: + return false; + case ScrollBarMode::kHiddenButEnabled: + return bool{horiz_sb_}; + case ScrollBarMode::kEnabled: + return horiz_sb_ && horiz_sb_->GetVisible(); + } +} + +bool ScrollView::IsVerticalScrollEnabled() const { + switch (vertical_scroll_bar_mode_) { + case ScrollBarMode::kDisabled: + return false; + case ScrollBarMode::kHiddenButEnabled: + return bool{vert_sb_}; + case ScrollBarMode::kEnabled: + return vert_sb_ && vert_sb_->GetVisible(); + } +} + void ScrollView::EnableViewportLayer() { if (DoesViewportOrScrollViewHaveLayer()) return; @@ -1013,20 +1131,21 @@ void ScrollView::UpdateOverflowIndicatorVisibility( const gfx::ScrollOffset& offset) { SetControlVisibility(more_content_top_.get(), - !draw_border_ && !header_ && vert_sb_->GetVisible() && + !draw_border_ && !header_ && IsVerticalScrollEnabled() && offset.y() > vert_sb_->GetMinPosition() && draw_overflow_indicator_); SetControlVisibility( more_content_bottom_.get(), !draw_border_ && vert_sb_->GetVisible() && !horiz_sb_->GetVisible() && offset.y() < vert_sb_->GetMaxPosition() && draw_overflow_indicator_); + SetControlVisibility(more_content_left_.get(), - !draw_border_ && horiz_sb_->GetVisible() && + !draw_border_ && IsHorizontalScrollEnabled() && offset.x() > horiz_sb_->GetMinPosition() && draw_overflow_indicator_); SetControlVisibility( more_content_right_.get(), - !draw_border_ && horiz_sb_->GetVisible() && !vert_sb_->GetVisible() && + !draw_border_ && IsHorizontalScrollEnabled() && !vert_sb_->GetVisible() && offset.x() < horiz_sb_->GetMaxPosition() && draw_overflow_indicator_); } @@ -1038,7 +1157,9 @@ BackgroundThemeColorId) ADD_PROPERTY_METADATA(bool, DrawOverflowIndicator) ADD_PROPERTY_METADATA(bool, HasFocusIndicator) -ADD_PROPERTY_METADATA(bool, HideHorizontalScrollBar) +ADD_PROPERTY_METADATA(ScrollView::ScrollBarMode, HorizontalScrollBarMode) +ADD_PROPERTY_METADATA(ScrollView::ScrollBarMode, VerticalScrollBarMode) +ADD_PROPERTY_METADATA(bool, TreatAllScrollEventsAsHorizontal) END_METADATA // VariableRowHeightScrollHelper ----------------------------------------------
diff --git a/ui/views/controls/scroll_view.h b/ui/views/controls/scroll_view.h index e37d0f6..690b2a4 100644 --- a/ui/views/controls/scroll_view.h +++ b/ui/views/controls/scroll_view.h
@@ -50,6 +50,19 @@ // Indicates whether or not scroll view is initialized with layer-scrolling. enum class ScrollWithLayers { kDisabled, kEnabled }; + // Controls how a scroll bar appears and functions. + enum class ScrollBarMode { + // The scrollbar is hidden, and the pane will not respond to e.g. mousewheel + // events even if the contents are larger than the viewport. + kDisabled, + // The scrollbar is hidden whether or not the contents are larger than the + // viewport, but the pane will respond to scroll events. + kHiddenButEnabled, + // The scrollbar will be visible if the contents are larger than the + // viewport and the pane will respond to scroll events. + kEnabled + }; + ScrollView(); // Additional constructor for overriding scrolling as defined by @@ -110,8 +123,19 @@ bool GetUseColorId() const { return !!background_color_id_; } - bool GetHideHorizontalScrollBar() const { return hide_horizontal_scrollbar_; } - void SetHideHorizontalScrollBar(bool visible); + ScrollBarMode GetHorizontalScrollBarMode() const { + return horizontal_scroll_bar_mode_; + } + ScrollBarMode GetVerticalScrollBarMode() const { + return vertical_scroll_bar_mode_; + } + bool GetTreatAllScrollEventsAsHorizontal() const { + return treat_all_scroll_events_as_horizontal_; + } + void SetHorizontalScrollBarMode(ScrollBarMode horizontal_scroll_bar_mode); + void SetVerticalScrollBarMode(ScrollBarMode vertical_scroll_bar_mode); + void SetTreatAllScrollEventsAsHorizontal( + bool treat_all_scroll_events_as_horizontal); bool GetDrawOverflowIndicator() const { return draw_overflow_indicator_; } void SetDrawOverflowIndicator(bool draw_overflow_indicator); @@ -165,6 +189,9 @@ class Viewport; + bool IsHorizontalScrollEnabled() const; + bool IsVerticalScrollEnabled() const; + // Forces |contents_viewport_| to have a Layer (assuming it doesn't already). void EnableViewportLayer(); @@ -269,9 +296,14 @@ base::Optional<ui::NativeTheme::ColorId> background_color_id_ = ui::NativeTheme::kColorId_DialogBackground; - // If true, never show the horizontal scrollbar (even if the contents is wider - // than the viewport). - bool hide_horizontal_scrollbar_ = false; + // How to handle the case when the contents overflow the viewport. + ScrollBarMode horizontal_scroll_bar_mode_ = ScrollBarMode::kEnabled; + ScrollBarMode vertical_scroll_bar_mode_ = ScrollBarMode::kEnabled; + + // Causes vertical scroll events (e.g. scrolling with the mousewheel) as + // horizontal events, to make scrolling in horizontal-only scroll situations + // easier for the user. + bool treat_all_scroll_events_as_horizontal_ = false; // In Harmony, the indicator is a focus ring. Pre-Harmony, the indicator is a // different border painter. @@ -298,7 +330,9 @@ VIEW_BUILDER_VIEW_TYPE_PROPERTY(View, Header) VIEW_BUILDER_PROPERTY(base::Optional<ui::NativeTheme::ColorId>, BackgroundThemeColorId) -VIEW_BUILDER_PROPERTY(bool, HideHorizontalScrollBar) +VIEW_BUILDER_PROPERTY(ScrollView::ScrollBarMode, HorizontalScrollBarMode) +VIEW_BUILDER_PROPERTY(ScrollView::ScrollBarMode, VerticalScrollBarMode) +VIEW_BUILDER_PROPERTY(bool, TreatAllScrollEventsAsHorizontal) VIEW_BUILDER_PROPERTY(bool, DrawOverflowIndicator) VIEW_BUILDER_PROPERTY(base::Optional<SkColor>, BackgroundColor) VIEW_BUILDER_VIEW_PROPERTY(ScrollBar, HorizontalScrollBar)
diff --git a/ui/views/controls/scroll_view_unittest.cc b/ui/views/controls/scroll_view_unittest.cc index 0bf6354..3eb0d52 100644 --- a/ui/views/controls/scroll_view_unittest.cc +++ b/ui/views/controls/scroll_view_unittest.cc
@@ -65,7 +65,9 @@ return gfx::Point() - gfx::ScrollOffsetToFlooredVector2d(CurrentOffset()); } - gfx::ScrollOffset CurrentOffset() { return scroll_view_->CurrentOffset(); } + gfx::ScrollOffset CurrentOffset() const { + return scroll_view_->CurrentOffset(); + } base::RetainingOneShotTimer* GetScrollBarHideTimer( ScrollBarOrientation orientation) { @@ -183,6 +185,21 @@ DISALLOW_COPY_AND_ASSIGN(VerticalResizingView); }; +// Same as VerticalResizingView, but horizontal instead. +class HorizontalResizingView : public View { + public: + HorizontalResizingView() = default; + ~HorizontalResizingView() override = default; + void Layout() override { + int height = 10000; + int width = parent()->width(); + SetBounds(x(), y(), width, height); + } + + private: + DISALLOW_COPY_AND_ASSIGN(HorizontalResizingView); +}; + class TestScrollBarThumb : public BaseScrollBarThumb { public: using BaseScrollBarThumb::BaseScrollBarThumb; @@ -469,6 +486,53 @@ EXPECT_TRUE(scroll_view_->horizontal_scroll_bar()->GetVisible()); } +// Same as above, but setting horizontal scroll bar to hidden. +TEST_F(ScrollViewTest, HorizontalScrollbarDoesNotAppearIfHidden) { + const gfx::Rect default_outer_bounds(0, 0, 100, 100); + scroll_view_->SetHorizontalScrollBarMode( + ScrollView::ScrollBarMode::kHiddenButEnabled); + scroll_view_->SetContents(std::make_unique<VerticalResizingView>()); + scroll_view_->SetBoundsRect(default_outer_bounds); + scroll_view_->Layout(); + EXPECT_FALSE(scroll_view_->vertical_scroll_bar()->GetVisible()); + EXPECT_FALSE(scroll_view_->horizontal_scroll_bar()->GetVisible()); +} + +// Same as above, but setting vertical scrollbar instead. +TEST_F(ScrollViewTest, VerticalScrollbarDoesNotAppearIfHidden) { + const gfx::Rect default_outer_bounds(0, 0, 100, 100); + scroll_view_->SetVerticalScrollBarMode( + ScrollView::ScrollBarMode::kHiddenButEnabled); + scroll_view_->SetContents(std::make_unique<HorizontalResizingView>()); + scroll_view_->SetBoundsRect(default_outer_bounds); + scroll_view_->Layout(); + EXPECT_FALSE(scroll_view_->vertical_scroll_bar()->GetVisible()); + EXPECT_FALSE(scroll_view_->horizontal_scroll_bar()->GetVisible()); +} + +// Same as above, but setting horizontal scroll bar to disabled. +TEST_F(ScrollViewTest, HorizontalScrollbarDoesNotAppearIfDisabled) { + const gfx::Rect default_outer_bounds(0, 0, 100, 100); + scroll_view_->SetHorizontalScrollBarMode( + ScrollView::ScrollBarMode::kDisabled); + scroll_view_->SetContents(std::make_unique<VerticalResizingView>()); + scroll_view_->SetBoundsRect(default_outer_bounds); + scroll_view_->Layout(); + EXPECT_FALSE(scroll_view_->vertical_scroll_bar()->GetVisible()); + EXPECT_FALSE(scroll_view_->horizontal_scroll_bar()->GetVisible()); +} + +// Same as above, but setting vertical scrollbar instead. +TEST_F(ScrollViewTest, VerticallScrollbarDoesNotAppearIfDisabled) { + const gfx::Rect default_outer_bounds(0, 0, 100, 100); + scroll_view_->SetVerticalScrollBarMode(ScrollView::ScrollBarMode::kDisabled); + scroll_view_->SetContents(std::make_unique<HorizontalResizingView>()); + scroll_view_->SetBoundsRect(default_outer_bounds); + scroll_view_->Layout(); + EXPECT_FALSE(scroll_view_->vertical_scroll_bar()->GetVisible()); + EXPECT_FALSE(scroll_view_->horizontal_scroll_bar()->GetVisible()); +} + // Verifies the scrollbars are added as necessary. // If on Mac, test the non-overlay scrollbars. TEST_F(ScrollViewTest, ScrollBars) { @@ -742,6 +806,46 @@ EXPECT_GT(scroll_bar->GetPosition(), 0); } +// Test that calling ScrollToPosition() also updates the position of the +// child view even when the horizontal scrollbar is hidden. +TEST_F(ScrollViewTest, ScrollToPositionUpdatesWithHiddenHorizontalScrollBar) { + scroll_view_->SetHorizontalScrollBarMode( + ScrollView::ScrollBarMode::kHiddenButEnabled); + ScrollViewTestApi test_api(scroll_view_.get()); + View* contents = InstallContents(); + + contents->SetBounds(0, 0, 400, 50); + scroll_view_->Layout(); + auto* scroll_bar = test_api.GetScrollBar(HORIZONTAL); + ASSERT_TRUE(scroll_bar); + EXPECT_FALSE(scroll_bar->GetVisible()); + // We can't rely on the scrollbar, which may not be updated as it's not + // visible, but we can check the scroll offset itself. + EXPECT_EQ(0, test_api.CurrentOffset().x()); + scroll_view_->ScrollToPosition(scroll_bar, 20); + EXPECT_GT(test_api.CurrentOffset().x(), 0); +} + +// Test that calling ScrollToPosition() also updates the position of the +// child view even when the horizontal scrollbar is hidden. +TEST_F(ScrollViewTest, ScrollToPositionUpdatesWithHiddenVerticalScrollBar) { + scroll_view_->SetVerticalScrollBarMode( + ScrollView::ScrollBarMode::kHiddenButEnabled); + ScrollViewTestApi test_api(scroll_view_.get()); + View* contents = InstallContents(); + + contents->SetBounds(0, 0, 50, 400); + scroll_view_->Layout(); + auto* scroll_bar = test_api.GetScrollBar(VERTICAL); + ASSERT_TRUE(scroll_bar); + EXPECT_FALSE(scroll_bar->GetVisible()); + // We can't rely on the scrollbar, which may not be updated as it's not + // visible, but we can check the scroll offset itself. + EXPECT_EQ(0, test_api.CurrentOffset().y()); + scroll_view_->ScrollToPosition(scroll_bar, 20); + EXPECT_GT(test_api.CurrentOffset().y(), 0); +} + // Verifies ScrollRectToVisible() on the child works. TEST_F(ScrollViewTest, ScrollRectToVisible) { ScrollViewTestApi test_api(scroll_view_.get()); @@ -769,6 +873,66 @@ EXPECT_EQ(415 - viewport_height, test_api.CurrentOffset().y()); } +// Verifies ScrollRectToVisible() scrolls the view horizontally even if the +// horizontal scrollbar is hidden (but not disabled). +TEST_F(ScrollViewTest, ScrollRectToVisibleWithHiddenHorizontalScrollbar) { + scroll_view_->SetHorizontalScrollBarMode( + ScrollView::ScrollBarMode::kHiddenButEnabled); + ScrollViewTestApi test_api(scroll_view_.get()); + auto contents = std::make_unique<CustomView>(); + contents->SetPreferredSize(gfx::Size(500, 1000)); + auto* contents_ptr = scroll_view_->SetContents(std::move(contents)); + + scroll_view_->SetBoundsRect(gfx::Rect(0, 0, 100, 100)); + scroll_view_->Layout(); + EXPECT_EQ("0,0", test_api.IntegralViewOffset().ToString()); + + // Scroll to x=305 width=10, this should make the x position of the content + // at (305 + 10) - viewport_width (scroll region right aligned). + contents_ptr->ScrollRectToVisible(gfx::Rect(305, 0, 10, 10)); + const int viewport_width = test_api.contents_viewport()->width(); + + // Expect there to be a vertical scrollbar, making the viewport shorter. + EXPECT_EQ(100 - scroll_view_->GetScrollBarLayoutWidth(), viewport_width); + + gfx::ScrollOffset offset = test_api.CurrentOffset(); + EXPECT_EQ(315 - viewport_width, offset.x()); + + // Scroll to the current x-location and 10x10; should do nothing. + contents_ptr->ScrollRectToVisible(gfx::Rect(offset.x(), 0, 10, 10)); + EXPECT_EQ(315 - viewport_width, test_api.CurrentOffset().x()); +} + +// Verifies ScrollRectToVisible() scrolls the view horizontally even if the +// horizontal scrollbar is hidden (but not disabled). +TEST_F(ScrollViewTest, ScrollRectToVisibleWithHiddenVerticalScrollbar) { + scroll_view_->SetVerticalScrollBarMode( + ScrollView::ScrollBarMode::kHiddenButEnabled); + ScrollViewTestApi test_api(scroll_view_.get()); + auto contents = std::make_unique<CustomView>(); + contents->SetPreferredSize(gfx::Size(1000, 500)); + auto* contents_ptr = scroll_view_->SetContents(std::move(contents)); + + scroll_view_->SetBoundsRect(gfx::Rect(0, 0, 100, 100)); + scroll_view_->Layout(); + EXPECT_EQ("0,0", test_api.IntegralViewOffset().ToString()); + + // Scroll to y=305 height=10, this should make the y position of the content + // at (305 + 10) - viewport_height (scroll region bottom aligned). + contents_ptr->ScrollRectToVisible(gfx::Rect(0, 305, 10, 10)); + const int viewport_height = test_api.contents_viewport()->height(); + + // Expect there to be a vertical scrollbar, making the viewport shorter. + EXPECT_EQ(100 - scroll_view_->GetScrollBarLayoutHeight(), viewport_height); + + gfx::ScrollOffset offset = test_api.CurrentOffset(); + EXPECT_EQ(315 - viewport_height, offset.y()); + + // Scroll to the current x-location and 10x10; should do nothing. + contents_ptr->ScrollRectToVisible(gfx::Rect(0, offset.y(), 10, 10)); + EXPECT_EQ(315 - viewport_height, test_api.CurrentOffset().y()); +} + // Verifies that child scrolls into view when it's focused. TEST_F(ScrollViewTest, ScrollChildToVisibleOnFocus) { ScrollViewTestApi test_api(scroll_view_.get()); @@ -1576,8 +1740,34 @@ EXPECT_FALSE(test_api.more_content_right()->GetVisible()); } -// Ensure ScrollView::Layout succeeds if a hidden scrollbar's overlap style +// Ensure ScrollView::Layout succeeds if a disabled scrollbar's overlap style // does not match the other scrollbar. +TEST_F(ScrollViewTest, IgnoreOverlapWithDisabledHorizontalScroll) { + ScrollViewTestApi test_api(scroll_view_.get()); + + constexpr int kThickness = 1; + // Assume horizontal scroll bar is the default and is overlapping. + scroll_view_->SetHorizontalScrollBar(std::make_unique<TestScrollBar>( + /* horizontal */ true, /* overlaps_content */ true, kThickness)); + // Assume vertical scroll bar is custom and it we want it to not overlap. + scroll_view_->SetVerticalScrollBar(std::make_unique<TestScrollBar>( + /* horizontal */ false, /* overlaps_content */ false, kThickness)); + + // Also, let's turn off horizontal scroll bar. + scroll_view_->SetHorizontalScrollBarMode( + ScrollView::ScrollBarMode::kDisabled); + + View* contents = InstallContents(); + contents->SetBoundsRect(gfx::Rect(0, 0, 300, 300)); + scroll_view_->Layout(); + + gfx::Size expected_size = scroll_view_->size(); + expected_size.Enlarge(-kThickness, 0); + EXPECT_EQ(expected_size, test_api.contents_viewport()->size()); +} + +// Ensure ScrollView::Layout succeeds if a hidden but enabled scrollbar's +// overlap style does not match the other scrollbar. TEST_F(ScrollViewTest, IgnoreOverlapWithHiddenHorizontalScroll) { ScrollViewTestApi test_api(scroll_view_.get()); @@ -1590,7 +1780,8 @@ /* horizontal */ false, /* overlaps_content */ false, kThickness)); // Also, let's turn off horizontal scroll bar. - scroll_view_->SetHideHorizontalScrollBar(true); + scroll_view_->SetHorizontalScrollBarMode( + ScrollView::ScrollBarMode::kHiddenButEnabled); View* contents = InstallContents(); contents->SetBoundsRect(gfx::Rect(0, 0, 300, 300)); @@ -1601,6 +1792,57 @@ EXPECT_EQ(expected_size, test_api.contents_viewport()->size()); } +// Ensure ScrollView::Layout succeeds if a disabled scrollbar's overlap style +// does not match the other scrollbar. +TEST_F(ScrollViewTest, IgnoreOverlapWithDisabledVerticalScroll) { + ScrollViewTestApi test_api(scroll_view_.get()); + + constexpr int kThickness = 1; + // Assume horizontal scroll bar is custom and it we want it to not overlap. + scroll_view_->SetHorizontalScrollBar(std::make_unique<TestScrollBar>( + /* horizontal */ true, /* overlaps_content */ false, kThickness)); + // Assume vertical scroll bar is the default and is overlapping. + scroll_view_->SetVerticalScrollBar(std::make_unique<TestScrollBar>( + /* horizontal */ false, /* overlaps_content */ true, kThickness)); + + // Also, let's turn off horizontal scroll bar. + scroll_view_->SetVerticalScrollBarMode(ScrollView::ScrollBarMode::kDisabled); + + View* contents = InstallContents(); + contents->SetBoundsRect(gfx::Rect(0, 0, 300, 300)); + scroll_view_->Layout(); + + gfx::Size expected_size = scroll_view_->size(); + expected_size.Enlarge(0, -kThickness); + EXPECT_EQ(expected_size, test_api.contents_viewport()->size()); +} + +// Ensure ScrollView::Layout succeeds if a hidden but enabled scrollbar's +// overlap style does not match the other scrollbar. +TEST_F(ScrollViewTest, IgnoreOverlapWithHiddenVerticalScroll) { + ScrollViewTestApi test_api(scroll_view_.get()); + + constexpr int kThickness = 1; + // Assume horizontal scroll bar is custom and it we want it to not overlap. + scroll_view_->SetHorizontalScrollBar(std::make_unique<TestScrollBar>( + /* horizontal */ true, /* overlaps_content */ false, kThickness)); + // Assume vertical scroll bar is the default and is overlapping. + scroll_view_->SetVerticalScrollBar(std::make_unique<TestScrollBar>( + /* horizontal */ false, /* overlaps_content */ true, kThickness)); + + // Also, let's turn off horizontal scroll bar. + scroll_view_->SetVerticalScrollBarMode( + ScrollView::ScrollBarMode::kHiddenButEnabled); + + View* contents = InstallContents(); + contents->SetBoundsRect(gfx::Rect(0, 0, 300, 300)); + scroll_view_->Layout(); + + gfx::Size expected_size = scroll_view_->size(); + expected_size.Enlarge(0, -kThickness); + EXPECT_EQ(expected_size, test_api.contents_viewport()->size()); +} + // Test scrolling behavior when clicking on the scroll track. TEST_F(WidgetScrollViewTest, ScrollTrackScrolling) { // Set up with a vertical scroller. @@ -1847,6 +2089,38 @@ EXPECT_EQ(gfx::ScrollOffset(offset.x(), offset.y()), impl_offset); } +namespace { + +// Applies |scroll_event| to |scroll_view| and verifies that the event is +// applied correctly whether or not compositor scrolling is enabled. +static void ApplyScrollEvent(const ScrollViewTestApi& test_api, + ScrollView* scroll_view, + ui::ScrollEvent& scroll_event) { + EXPECT_FALSE(scroll_event.handled()); + EXPECT_FALSE(scroll_event.stopped_propagation()); + scroll_view->OnScrollEvent(&scroll_event); + + // Check to see if the scroll event is handled by the scroll view. + if (base::FeatureList::IsEnabled(::features::kUiCompositorScrollWithLayers)) { + // If UiCompositorScrollWithLayers is enabled, the event is set handled + // and its propagation is stopped. + EXPECT_TRUE(scroll_event.handled()); + EXPECT_TRUE(scroll_event.stopped_propagation()); + } else { + // If UiCompositorScrollWithLayers is disabled, the event isn't handled. + // This informs Widget::OnScrollEvent() to convert to a MouseWheel event + // and dispatch again. Simulate that. + EXPECT_FALSE(scroll_event.handled()); + EXPECT_FALSE(scroll_event.stopped_propagation()); + EXPECT_EQ(gfx::ScrollOffset(), test_api.CurrentOffset()); + + ui::MouseWheelEvent wheel(scroll_event); + scroll_view->OnMouseEvent(&wheel); + } +} + +} // namespace + // Tests to see the scroll events are handled correctly in composited and // non-composited scrolling. TEST_F(WidgetScrollViewTest, CompositedScrollEvents) { @@ -1858,32 +2132,80 @@ // Create a fake scroll event and send it to the scroll view. ui::ScrollEvent scroll(ui::ET_SCROLL, gfx::Point(), base::TimeTicks::Now(), 0, 0, -10, 0, -10, 3); - EXPECT_FALSE(scroll.handled()); - EXPECT_FALSE(scroll.stopped_propagation()); - scroll_view->OnScrollEvent(&scroll); - - // Check to see if the scroll event is handled by the scroll view. - if (base::FeatureList::IsEnabled(::features::kUiCompositorScrollWithLayers)) { - // If UiCompositorScrollWithLayers is enabled, the event is set handled - // and its propagation is stopped. - EXPECT_TRUE(scroll.handled()); - EXPECT_TRUE(scroll.stopped_propagation()); - } else { - // If UiCompositorScrollWithLayers is disabled, the event isn't handled. - // This informs Widget::OnScrollEvent() to convert to a MouseWheel event - // and dispatch again. Simulate that. - EXPECT_FALSE(scroll.handled()); - EXPECT_FALSE(scroll.stopped_propagation()); - EXPECT_EQ(gfx::ScrollOffset(), test_api.CurrentOffset()); - - ui::MouseWheelEvent wheel(scroll); - scroll_view->OnMouseEvent(&wheel); - } + ApplyScrollEvent(test_api, scroll_view, scroll); // Check if the scroll view has been offset. EXPECT_EQ(gfx::ScrollOffset(0, 10), test_api.CurrentOffset()); } +// Tests to see that transposed (treat-as-horizontal) scroll events are handled +// correctly in composited and non-composited scrolling. +TEST_F(WidgetScrollViewTest, CompositedTransposedScrollEvents) { + // Set up with a vertical scroll bar. + ScrollView* scroll_view = + AddScrollViewWithContentSize(gfx::Size(kDefaultHeight * 5, 10)); + scroll_view->SetTreatAllScrollEventsAsHorizontal(true); + ScrollViewTestApi test_api(scroll_view); + + // Create a fake scroll event and send it to the scroll view. + // Note that this is still a VERTICAL scroll event, but we'll be looking for + // HORIZONTAL motion later because we're transposed. + ui::ScrollEvent scroll(ui::ET_SCROLL, gfx::Point(), base::TimeTicks::Now(), 0, + 0, -10, 0, -10, 3); + ApplyScrollEvent(test_api, scroll_view, scroll); + + // Check if the scroll view has been offset. + EXPECT_EQ(gfx::ScrollOffset(10, 0), test_api.CurrentOffset()); +} + +// Tests to see that transposed (treat-as-horizontal) scroll events are handled +// correctly in composited and non-composited scrolling when the scroll offset +// is somewhat ambiguous. This is the case where the horizontal component is +// larger than the vertical. +TEST_F(WidgetScrollViewTest, + CompositedTransposedScrollEventsHorizontalComponentIsLarger) { + // Set up with a vertical scroll bar. + ScrollView* scroll_view = + AddScrollViewWithContentSize(gfx::Size(kDefaultHeight * 5, 10)); + scroll_view->SetTreatAllScrollEventsAsHorizontal(true); + ScrollViewTestApi test_api(scroll_view); + + // Create a fake scroll event and send it to the scroll view. + // This will be a horizontal scroll event but there will be a conflicting + // vertical element. We should still scroll horizontally, since the horizontal + // component is greater. + ui::ScrollEvent scroll(ui::ET_SCROLL, gfx::Point(), base::TimeTicks::Now(), 0, + -10, 7, -10, 7, 3); + ApplyScrollEvent(test_api, scroll_view, scroll); + + // Check if the scroll view has been offset. + EXPECT_EQ(gfx::ScrollOffset(10, 0), test_api.CurrentOffset()); +} + +// Tests to see that transposed (treat-as-horizontal) scroll events are handled +// correctly in composited and non-composited scrolling when the scroll offset +// is somewhat ambiguous. This is the case where the vertical component is +// larger than the horizontal. +TEST_F(WidgetScrollViewTest, + CompositedTransposedScrollEventsVerticalComponentIsLarger) { + // Set up with a vertical scroll bar. + ScrollView* scroll_view = + AddScrollViewWithContentSize(gfx::Size(kDefaultHeight * 5, 10)); + scroll_view->SetTreatAllScrollEventsAsHorizontal(true); + ScrollViewTestApi test_api(scroll_view); + + // Create a fake scroll event and send it to the scroll view. + // This will be a vertical scroll event but there will be a conflicting + // horizontal element. We should still scroll horizontally, since the vertical + // component is greater. + ui::ScrollEvent scroll(ui::ET_SCROLL, gfx::Point(), base::TimeTicks::Now(), 0, + 7, -10, 7, -10, 3); + ApplyScrollEvent(test_api, scroll_view, scroll); + + // Check if the scroll view has been offset. + EXPECT_EQ(gfx::ScrollOffset(10, 0), test_api.CurrentOffset()); +} + INSTANTIATE_TEST_SUITE_P(All, WidgetScrollViewTestRTLAndLayers, ::testing::Values(UiConfig::kLtr,
diff --git a/ui/views/metadata/type_conversion.cc b/ui/views/metadata/type_conversion.cc index 579052a9..ac0cf76 100644 --- a/ui/views/metadata/type_conversion.cc +++ b/ui/views/metadata/type_conversion.cc
@@ -14,6 +14,7 @@ #include "ui/base/ime/text_input_type.h" #include "ui/gfx/geometry/rect.h" #include "ui/native_theme/native_theme.h" +#include "ui/views/controls/scroll_view.h" namespace views { namespace metadata { @@ -354,6 +355,14 @@ {ui::MenuSeparatorType::PADDED_SEPARATOR, base::ASCIIToUTF16("PADDED_SEPARATOR")}) +DEFINE_ENUM_CONVERTERS(views::ScrollView::ScrollBarMode, + {views::ScrollView::ScrollBarMode::kDisabled, + base::ASCIIToUTF16("kDisabled")}, + {views::ScrollView::ScrollBarMode::kHiddenButEnabled, + base::ASCIIToUTF16("kHiddenButEnabled")}, + {views::ScrollView::ScrollBarMode::kEnabled, + base::ASCIIToUTF16("kEnabled")}) + #define OP(enum_name) \ { ui::NativeTheme::enum_name, base::ASCIIToUTF16(#enum_name) } DEFINE_ENUM_CONVERTERS(ui::NativeTheme::ColorId, NATIVE_THEME_COLOR_IDS)
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/NewTabCallbackTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/NewTabCallbackTest.java index efb3a41..0c0e5cf 100644 --- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/NewTabCallbackTest.java +++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/NewTabCallbackTest.java
@@ -11,8 +11,10 @@ import org.junit.Test; import org.junit.runner.RunWith; +import org.chromium.base.test.util.CallbackHelper; import org.chromium.content_public.browser.test.util.CriteriaHelper; import org.chromium.content_public.browser.test.util.TestThreadUtils; +import org.chromium.weblayer.NewTabCallback; import org.chromium.weblayer.Tab; import org.chromium.weblayer.shell.InstrumentationActivity; @@ -51,6 +53,31 @@ @Test @SmallTest + public void testDestroyTabInOnNewTab() throws Throwable { + String url = mActivityTestRule.getTestDataURL("new_browser.html"); + mActivity = mActivityTestRule.launchShellWithUrl(url); + Assert.assertNotNull(mActivity); + CallbackHelper callbackHelper = new CallbackHelper(); + TestThreadUtils.runOnUiThreadBlocking(() -> { + Tab tab = mActivity.getBrowser().getActiveTab(); + tab.setNewTabCallback(new NewTabCallback() { + @Override + public void onNewTab(Tab newTab, int mode) { + newTab.getBrowser().destroyTab(newTab); + Assert.assertTrue(newTab.isDestroyed()); + Assert.assertEquals(1, mActivity.getBrowser().getTabs().size()); + Assert.assertFalse(mActivity.getBrowser().getActiveTab().isDestroyed()); + callbackHelper.notifyCalled(); + } + }); + }); + + EventUtils.simulateTouchCenterOfView(mActivity.getWindow().getDecorView()); + callbackHelper.waitForFirst(); + } + + @Test + @SmallTest public void testNewTabHasFocus() { String url = mActivityTestRule.getTestDataURL("new_browser.html"); mActivity = mActivityTestRule.launchShellWithUrl(url);
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/WebLayerVersionConstants.java b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/WebLayerVersionConstants.java index 3ef535d..a76b13c3 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/WebLayerVersionConstants.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/WebLayerVersionConstants.java
@@ -15,5 +15,5 @@ * * @see WebLayer#isAvailable() */ - int MAX_SKEW = 3; + int MAX_SKEW = 4; }
diff --git a/weblayer/browser/new_tab_delegate_browsertest.cc b/weblayer/browser/new_tab_delegate_browsertest.cc new file mode 100644 index 0000000..5c13568 --- /dev/null +++ b/weblayer/browser/new_tab_delegate_browsertest.cc
@@ -0,0 +1,58 @@ +// 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 "weblayer/public/new_tab_delegate.h" + +#include "base/strings/stringprintf.h" +#include "net/test/embedded_test_server/embedded_test_server.h" +#include "weblayer/browser/tab_impl.h" +#include "weblayer/public/browser.h" +#include "weblayer/public/new_tab_delegate.h" +#include "weblayer/public/tab.h" +#include "weblayer/shell/browser/shell.h" +#include "weblayer/test/weblayer_browser_test.h" +#include "weblayer/test/weblayer_browser_test_utils.h" + +namespace weblayer { + +namespace { + +class DestroyingNewTabDelegate : public NewTabDelegate { + public: + void WaitForOnNewTab() { run_loop_.Run(); } + + bool was_on_new_tab_called() const { return was_on_new_tab_called_; } + + // NewTabDelegate: + void OnNewTab(Tab* new_tab, NewTabType type) override { + was_on_new_tab_called_ = true; + new_tab->GetBrowser()->DestroyTab(new_tab); + run_loop_.Quit(); + } + + private: + base::RunLoop run_loop_; + bool was_on_new_tab_called_ = false; +}; + +} // namespace + +using NewTabDelegateTest = WebLayerBrowserTest; + +IN_PROC_BROWSER_TEST_F(NewTabDelegateTest, DestroyTabOnNewTab) { + ASSERT_TRUE(embedded_test_server()->Start()); + NavigateAndWaitForCompletion(embedded_test_server()->GetURL("/echo"), + shell()->tab()); + DestroyingNewTabDelegate new_tab_delegate; + shell()->tab()->SetNewTabDelegate(&new_tab_delegate); + GURL popup_url = embedded_test_server()->GetURL("/echo?popup"); + ExecuteScriptWithUserGesture( + shell()->tab(), + base::StringPrintf("window.open('%s')", popup_url.spec().c_str())); + new_tab_delegate.WaitForOnNewTab(); + EXPECT_TRUE(new_tab_delegate.was_on_new_tab_called()); + EXPECT_EQ(1u, shell()->tab()->GetBrowser()->GetTabs().size()); +} + +} // namespace weblayer
diff --git a/weblayer/browser/tab_impl.cc b/weblayer/browser/tab_impl.cc index 56cc817..bbb893b 100644 --- a/weblayer/browser/tab_impl.cc +++ b/weblayer/browser/tab_impl.cc
@@ -401,6 +401,10 @@ data_observers_.RemoveObserver(observer); } +Browser* TabImpl::GetBrowser() { + return browser_; +} + void TabImpl::SetErrorPageDelegate(ErrorPageDelegate* delegate) { error_page_delegate_ = delegate; }
diff --git a/weblayer/browser/tab_impl.h b/weblayer/browser/tab_impl.h index 14cb683b..e21928bc9 100644 --- a/weblayer/browser/tab_impl.h +++ b/weblayer/browser/tab_impl.h
@@ -214,6 +214,7 @@ } // Tab: + Browser* GetBrowser() override; void SetErrorPageDelegate(ErrorPageDelegate* delegate) override; void SetFullscreenDelegate(FullscreenDelegate* delegate) override; void SetNewTabDelegate(NewTabDelegate* delegate) override;
diff --git a/weblayer/public/tab.h b/weblayer/public/tab.h index 6d26eb6..2485fef0 100644 --- a/weblayer/public/tab.h +++ b/weblayer/public/tab.h
@@ -25,6 +25,7 @@ #endif namespace weblayer { +class Browser; class ErrorPageDelegate; class FaviconFetcher; class FaviconFetcherDelegate; @@ -40,6 +41,9 @@ public: virtual ~Tab() = default; + // Returns the Browser that owns this. + virtual Browser* GetBrowser() = 0; + // Sets the ErrorPageDelegate. If none is set, a default action will be taken // for any given interaction with an error page. virtual void SetErrorPageDelegate(ErrorPageDelegate* delegate) = 0;
diff --git a/weblayer/test/BUILD.gn b/weblayer/test/BUILD.gn index 60f7b96..34c37e65 100644 --- a/weblayer/test/BUILD.gn +++ b/weblayer/test/BUILD.gn
@@ -142,6 +142,7 @@ "../browser/js_communication/web_message_browsertest.cc", "../browser/navigation_browsertest.cc", "../browser/navigation_error_navigation_throttle_browsertest.cc", + "../browser/new_tab_delegate_browsertest.cc", "../browser/no_state_prefetch/no_state_prefetch_browsertest.cc", "../browser/page_load_metrics_browsertest.cc", "../browser/popup_blocker_browsertest.cc",