diff --git a/DEPS b/DEPS index 99967eb..6c03189 100644 --- a/DEPS +++ b/DEPS
@@ -295,7 +295,7 @@ # 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': '3744490336cf54f6a167643a8e40298cd6ce2756', + 'skia_revision': '877213bd9a41200b6f568df40cab71deec2d3bd8', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -303,7 +303,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '71ead7b41c8beb1c992f9395a616ea0f41b08b7b', + 'angle_revision': '541cdcbf094fd900f085d14cb896f11240393f0c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -346,7 +346,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling freetype # and whatever else without interference from each other. - 'freetype_revision': '1c44de209cb465d175279dc30cd95f9857f703dd', + 'freetype_revision': 'aca4ec5907e0bfb5bbeb01370257a121f3f47a0f', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling freetype # and whatever else without interference from each other. @@ -366,7 +366,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': 'ddb664396541c88dc09b7ea2a528b86efa8dc7c6', + 'catapult_revision': '07489847d9adb4d5fb5ab9348f1044acd96e523a', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -374,7 +374,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': 'aeb2dc95cce6b337892a9315f2304d8862dc3cf3', + 'devtools_frontend_revision': 'f27464fc7745b4c88ed955c79b80e59b5d7d472e', # 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. @@ -414,7 +414,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'quiche_revision': 'cfff7cf007ecb3dcfee2aceb04cdbf3f7f39272d', + 'quiche_revision': 'a9c7837f7085662870031f8134f7464e56f1bb01', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ios_webkit # and whatever else without interference from each other. @@ -434,7 +434,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling nearby # and whatever else without interference from each other. - 'nearby_revision': '8bd3d3458056c59801ecf2d86145844c4137070c', + 'nearby_revision': '00b1a1570ef5290394b7e865a67392ae4199f4c4', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling securemessage # and whatever else without interference from each other. @@ -782,12 +782,12 @@ 'src/clank': { 'url': 'https://chrome-internal.googlesource.com/clank/internal/apps.git' + '@' + - '23dad63168e72047bbb6aa121f53172cc156777d', + '773541ef7b875aad33ec4ffd613cfa4825d0932b', 'condition': 'checkout_android and checkout_src_internal', }, 'src/docs/website': { - 'url': Var('chromium_git') + '/website.git' + '@' + '9aff7766594d07d48603073fafa5d07b16e1d411', + 'url': Var('chromium_git') + '/website.git' + '@' + 'a951c376d10365faee64b904a050695506c4690a', }, 'src/ios/third_party/earl_grey2/src': { @@ -971,7 +971,7 @@ 'packages': [ { 'package': 'chromium/third_party/androidx', - 'version': 'czqUkXtlFi7ry_9Cp8R92jqD6Tk3QQFvQQERxS_8RGYC', + 'version': 'QIAEMIWLTUbZTxvdAvBOr-o7ggm0GYvw3xGm8KdoPqAC', }, ], 'condition': 'checkout_android', @@ -1204,7 +1204,7 @@ # For Linux and Chromium OS. 'src/third_party/cros_system_api': { - 'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + 'f2700e5aaeec4f4735e8a2cf2a13b3561c390448', + 'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + '2c7a87d4a4f5d9e55abfd6111843b2cd425c842f', 'condition': 'checkout_linux', }, @@ -1214,13 +1214,13 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '6fde0fbe9226ae3fc9f5c709adb93249924e5c49', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '73a26246e50c0718e1b604040937bd3e1af428d4', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), 'src/third_party/devtools-frontend-internal': { - 'url': 'https://chrome-internal.googlesource.com/devtools/devtools-internal.git' + '@' + '79130b882092b6ab79785ea4180de97a72ca7e15', + 'url': 'https://chrome-internal.googlesource.com/devtools/devtools-internal.git' + '@' + 'f196f5a4a0d40987024d0379e4a59a416a1fad44', 'condition': 'checkout_src_internal', }, @@ -1635,7 +1635,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '197b7113ead0b489c3a4a4366786d6733d0d7c35', + Var('android_git') + '/platform/external/perfetto.git' + '@' + 'c194bc190ded8849d9d6be943220c5f8f72cc022', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1817,10 +1817,10 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'd1b65aa5a88f6efd900604dfcda840154e9f16e2', 'src/third_party/webgpu-cts/src': - Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '95541299f6b73716cb632523c3e7cfb80eb714f3', + Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '82ec26d039e19c70f6fa979bbff03b82d4b6ff7f', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '46e2d103b4edc76b65a8e71a5de372c213cfb5c3', + Var('webrtc_git') + '/src.git' + '@' + '7216b27406d094834d8644a525370069a70d2f93', # Wuffs' canonical repository is at github.com/google/wuffs, but we use # Skia's mirror of Wuffs, the same as in upstream Skia's DEPS file.
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/services/JsSandboxServiceTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/services/JsSandboxServiceTest.java index 833f28f1..e57b7fb 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/services/JsSandboxServiceTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/services/JsSandboxServiceTest.java
@@ -13,6 +13,7 @@ import androidx.javascriptengine.IsolateTerminatedException; import androidx.javascriptengine.JavaScriptIsolate; import androidx.javascriptengine.JavaScriptSandbox; +import androidx.javascriptengine.MemoryLimitExceededException; import androidx.javascriptengine.SandboxDeadException; import androidx.test.filters.MediumTest; @@ -450,7 +451,7 @@ @Test @MediumTest - public void testEvaluationThrowsWhenSandboxDead() throws Throwable { + public void testEvaluationThrowsWhenSandboxClosed() throws Throwable { final String code = "while(true){}"; Context context = ContextUtils.getApplicationContext(); @@ -458,16 +459,37 @@ JavaScriptSandbox.createConnectedInstanceForTestingAsync(context); try (JavaScriptSandbox jsSandbox = jsSandboxFuture.get(5, TimeUnit.SECONDS); JavaScriptIsolate jsIsolate = jsSandbox.createIsolate()) { - ListenableFuture<String> resultFuture = jsIsolate.evaluateJavaScriptAsync(code); + ListenableFuture<String> resultFuture1 = jsIsolate.evaluateJavaScriptAsync(code); jsSandbox.close(); + // Check already running evaluation gets SandboxDeadException try { - resultFuture.get(5, TimeUnit.SECONDS); + resultFuture1.get(5, TimeUnit.SECONDS); Assert.fail("Should have thrown."); } catch (ExecutionException e) { - if (!(e.getCause() instanceof IsolateTerminatedException)) { + if (!(e.getCause() instanceof SandboxDeadException)) { throw e; } } + // Check post-close evaluation gets SandboxDeadException + ListenableFuture<String> resultFuture2 = jsIsolate.evaluateJavaScriptAsync(code); + try { + resultFuture2.get(5, TimeUnit.SECONDS); + Assert.fail("Should have thrown."); + } catch (ExecutionException e) { + if (!(e.getCause() instanceof SandboxDeadException)) { + throw e; + } + } + // Check that closing an isolate then causes the IllegalStateException to be + // thrown instead. + jsIsolate.close(); + try { + ListenableFuture<String> postCloseResultFuture = + jsIsolate.evaluateJavaScriptAsync(code); + Assert.fail("Should have thrown."); + } catch (IllegalStateException e) { + // Expected + } } } @@ -558,33 +580,152 @@ @MediumTest public void testHeapSizeEnforced() throws Throwable { final long maxHeapSize = REASONABLE_HEAP_SIZE; - // We need to beat the v8 optimizer to ensure it really allocates the required memory. - // Note that we're allocating an array of elements - not bytes. - final String code = "this.array = Array(" + maxHeapSize + ").fill(Math.random(), 0);" - + "var arrayLength = this.array.length;" - + "var sum = 0;" - + "for (var i = 0; i < arrayLength; i++) {" - + " sum+=this.array[i];" - + "}"; + // We need to beat the v8 optimizer to ensure it really allocates the required memory. Note + // that we're allocating an array of elements - not bytes. Filling will ensure that the + // array is not sparsely allocated. + final String oomingCode = "" + + "const array = Array(" + maxHeapSize + ").fill(Math.random(), 0);"; + final String stableCode = "'PASS'"; + final String stableExpected = "PASS"; + final String unresolvedCode = "new Promise((resolve, reject) => {/* never resolve */})"; Context context = ContextUtils.getApplicationContext(); - ListenableFuture<JavaScriptSandbox> jsSandboxFuture = + + ListenableFuture<JavaScriptSandbox> jsSandboxFuture1 = JavaScriptSandbox.createConnectedInstanceForTestingAsync(context); - try (JavaScriptSandbox jsSandbox = jsSandboxFuture.get(5, TimeUnit.SECONDS)) { + try (JavaScriptSandbox jsSandbox = jsSandboxFuture1.get(5, TimeUnit.SECONDS)) { Assume.assumeTrue(jsSandbox.isFeatureSupported( JavaScriptSandbox.JS_FEATURE_ISOLATE_MAX_HEAP_SIZE)); + Assume.assumeTrue( + jsSandbox.isFeatureSupported(JavaScriptSandbox.JS_FEATURE_PROMISE_RETURN)); IsolateStartupParameters isolateStartupParameters = new IsolateStartupParameters(); isolateStartupParameters.setMaxHeapSizeBytes(maxHeapSize); - try (JavaScriptIsolate jsIsolate = jsSandbox.createIsolate(isolateStartupParameters)) { - ListenableFuture<String> resultFuture = jsIsolate.evaluateJavaScriptAsync(code); + try (JavaScriptIsolate jsIsolate1 = jsSandbox.createIsolate(isolateStartupParameters); + JavaScriptIsolate jsIsolate2 = jsSandbox.createIsolate()) { + ListenableFuture<String> earlyUnresolvedResultFuture = + jsIsolate1.evaluateJavaScriptAsync(unresolvedCode); + ListenableFuture<String> earlyResultFuture = + jsIsolate1.evaluateJavaScriptAsync(stableCode); + ListenableFuture<String> oomResultFuture = + jsIsolate1.evaluateJavaScriptAsync(oomingCode); + + // Wait for jsIsolate2 to fully initialize before using jsIsolate1. + jsIsolate2.evaluateJavaScriptAsync(stableCode).get(5, TimeUnit.SECONDS); + + // Check that the heap limit is enforced and that it reports this was the evaluation + // that exceeded the limit. try { - resultFuture.get(10, TimeUnit.SECONDS); + oomResultFuture.get(5, TimeUnit.SECONDS); Assert.fail("Should have thrown."); } catch (ExecutionException e) { - if (!(e.getCause() instanceof SandboxDeadException)) { + if (!(e.getCause() instanceof MemoryLimitExceededException)) { throw e; } } + + // Check that the previously submitted (but unresolved) promise evaluation reports a + // crash + try { + earlyUnresolvedResultFuture.get(5, TimeUnit.SECONDS); + Assert.fail("Should have thrown."); + } catch (ExecutionException e) { + if (!(e.getCause() instanceof IsolateTerminatedException)) { + throw e; + } + } + + // Check that the previously submitted evaluation which completed before the memory + // limit was exceeded, but for which we haven't yet gotten the result, returns its + // result just fine. + String result = earlyResultFuture.get(5, TimeUnit.SECONDS); + Assert.assertEquals(stableExpected, result); + + // Check that a totally new evaluation reports a crash + ListenableFuture<String> lateResultFuture = + jsIsolate1.evaluateJavaScriptAsync(stableCode); + try { + lateResultFuture.get(5, TimeUnit.SECONDS); + Assert.fail("Should have thrown."); + } catch (ExecutionException e) { + if (!(e.getCause() instanceof IsolateTerminatedException)) { + throw e; + } + } + + // Check that other pre-existing isolates can still be used. + ListenableFuture<String> otherIsolateResultFuture = + jsIsolate2.evaluateJavaScriptAsync(stableCode); + String otherIsolateResult = otherIsolateResultFuture.get(5, TimeUnit.SECONDS); + Assert.assertEquals(stableExpected, otherIsolateResult); } } } + + @Test + @MediumTest + public void testIsolateCreationAfterCrash() throws Throwable { + final long maxHeapSize = REASONABLE_HEAP_SIZE; + // We need to beat the v8 optimizer to ensure it really allocates the required memory. Note + // that we're allocating an array of elements - not bytes. Filling will ensure that the + // array is not sparsely allocated. + final String oomingCode = "" + + "const array = Array(" + maxHeapSize + ").fill(Math.random(), 0);"; + final String stableCode = "'PASS'"; + final String stableExpected = "PASS"; + Context context = ContextUtils.getApplicationContext(); + + ListenableFuture<JavaScriptSandbox> jsSandboxFuture1 = + JavaScriptSandbox.createConnectedInstanceForTestingAsync(context); + try (JavaScriptSandbox jsSandbox = jsSandboxFuture1.get(5, TimeUnit.SECONDS)) { + Assume.assumeTrue(jsSandbox.isFeatureSupported( + JavaScriptSandbox.JS_FEATURE_ISOLATE_MAX_HEAP_SIZE)); + Assume.assumeTrue( + jsSandbox.isFeatureSupported(JavaScriptSandbox.JS_FEATURE_PROMISE_RETURN)); + IsolateStartupParameters isolateStartupParameters = new IsolateStartupParameters(); + isolateStartupParameters.setMaxHeapSizeBytes(maxHeapSize); + try (JavaScriptIsolate jsIsolate1 = jsSandbox.createIsolate(isolateStartupParameters)) { + ListenableFuture<String> oomResultFuture = + jsIsolate1.evaluateJavaScriptAsync(oomingCode); + + // Check that the heap limit is enforced and that it reports this was the evaluation + // that exceeded the limit. + try { + oomResultFuture.get(5, TimeUnit.SECONDS); + Assert.fail("Should have thrown."); + } catch (ExecutionException e) { + if (!(e.getCause() instanceof MemoryLimitExceededException)) { + throw e; + } + } + + // Check that other isolates can still be created and used (without closing + // jsIsolate1). + try (JavaScriptIsolate jsIsolate2 = + jsSandbox.createIsolate(isolateStartupParameters)) { + ListenableFuture<String> resultFuture = + jsIsolate2.evaluateJavaScriptAsync(stableCode); + String result = resultFuture.get(5, TimeUnit.SECONDS); + Assert.assertEquals(stableExpected, result); + } + } + + // Check that other isolates can still be created and used (after closing jsIsolate1). + try (JavaScriptIsolate jsIsolate = jsSandbox.createIsolate(isolateStartupParameters)) { + ListenableFuture<String> resultFuture = + jsIsolate.evaluateJavaScriptAsync(stableCode); + String result = resultFuture.get(5, TimeUnit.SECONDS); + Assert.assertEquals(stableExpected, result); + } + } + + // Check that the old sandbox with the "crashed" isolate can be torn down and that a new + // sandbox and isolate can be spun up. + ListenableFuture<JavaScriptSandbox> jsSandboxFuture2 = + JavaScriptSandbox.createConnectedInstanceForTestingAsync(context); + try (JavaScriptSandbox jsSandbox = jsSandboxFuture2.get(5, TimeUnit.SECONDS); + JavaScriptIsolate jsIsolate = jsSandbox.createIsolate()) { + ListenableFuture<String> resultFuture = jsIsolate.evaluateJavaScriptAsync(stableCode); + String result = resultFuture.get(5, TimeUnit.SECONDS); + Assert.assertEquals(stableExpected, result); + } + } }
diff --git a/android_webview/js_sandbox/BUILD.gn b/android_webview/js_sandbox/BUILD.gn index 0427827..7daad969 100644 --- a/android_webview/js_sandbox/BUILD.gn +++ b/android_webview/js_sandbox/BUILD.gn
@@ -5,7 +5,10 @@ import("//build/config/android/rules.gni") generate_jni("js_sandbox_jni_headers") { - sources = [ "java/src/org/chromium/android_webview/js_sandbox/service/JsSandboxIsolate.java" ] + sources = [ + "java/src/org/chromium/android_webview/js_sandbox/service/JsSandboxIsolate.java", + "java/src/org/chromium/android_webview/js_sandbox/service/JsSandboxIsolateCallback.java", + ] } android_aidl("js_sandbox_aidl") { @@ -24,6 +27,7 @@ android_library("js_sandbox_service_java") { sources = [ "java/src/org/chromium/android_webview/js_sandbox/service/JsSandboxIsolate.java", + "java/src/org/chromium/android_webview/js_sandbox/service/JsSandboxIsolateCallback.java", "java/src/org/chromium/android_webview/js_sandbox/service/JsSandboxService.java", "java/src/org/chromium/android_webview/js_sandbox/service/JsSandboxService0.java", ] @@ -50,6 +54,7 @@ "java/src/androidx/javascriptengine/JavaScriptException.java", "java/src/androidx/javascriptengine/JavaScriptIsolate.java", "java/src/androidx/javascriptengine/JavaScriptSandbox.java", + "java/src/androidx/javascriptengine/MemoryLimitExceededException.java", "java/src/androidx/javascriptengine/SandboxDeadException.java", "java/src/androidx/javascriptengine/SandboxUnsupportedException.java", ]
diff --git a/android_webview/js_sandbox/java/src/androidx/javascriptengine/IsolateTerminatedException.java b/android_webview/js_sandbox/java/src/androidx/javascriptengine/IsolateTerminatedException.java index b44d0146..ae5b752 100644 --- a/android_webview/js_sandbox/java/src/androidx/javascriptengine/IsolateTerminatedException.java +++ b/android_webview/js_sandbox/java/src/androidx/javascriptengine/IsolateTerminatedException.java
@@ -5,8 +5,23 @@ package androidx.javascriptengine; /** - * Exception thrown when evaluation is terminated due to {@link JavaScriptIsolate} being - * closed. This can occur when the {@link JavaScriptIsolate#close()} is called. + * Exception thrown when evaluation is terminated due to the {@link JavaScriptIsolate} being closed + * or crashing. + * + * Calling {@link JavaScriptIsolate#close()} will cause this exception to be thrown for all + * previously requested but pending evaluations. + * <p> + * If the individual isolate has crashed, for example, due to exceeding a memory limit, this + * exception will also be thrown for all pending and future evaluations (until + * {@link JavaScriptIsolate#close()} is called). + * <p> + * Note that if the sandbox as a whole has crashed or been closed, {@link SandboxDeadException} will + * be thrown instead. + * <p> + * Note that this exception will not be thrown if the isolate has been explicitly closed before a + * call to {@link JavaScriptIsolate#evaluateJavaScriptAsync(String)}, which will instead immediately + * throw an IllegalStateException (and not asynchronously via a future). This applies even if the + * isolate was closed following a crash. */ public final class IsolateTerminatedException extends JavaScriptException { public IsolateTerminatedException() {
diff --git a/android_webview/js_sandbox/java/src/androidx/javascriptengine/JavaScriptIsolate.java b/android_webview/js_sandbox/java/src/androidx/javascriptengine/JavaScriptIsolate.java index fcbf862..667b43aa 100644 --- a/android_webview/js_sandbox/java/src/androidx/javascriptengine/JavaScriptIsolate.java +++ b/android_webview/js_sandbox/java/src/androidx/javascriptengine/JavaScriptIsolate.java
@@ -23,7 +23,7 @@ import java.io.IOException; import java.io.OutputStream; import java.util.HashSet; -import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; @@ -49,10 +49,16 @@ public final class JavaScriptIsolate implements AutoCloseable { private static final String TAG = "JavaScriptIsolate"; private final Object mSetLock = new Object(); + /** + * Interface to underlying service-backed implementation. + * + * mJsIsolateStub should only be null when the Isolate has been explicitly closed - not when the + * isolate has crashed or simply had its pending and future evaluations cancelled. + */ @Nullable private IJsSandboxIsolate mJsIsolateStub; private CloseGuardHelper mGuard = CloseGuardHelper.create(); - private final Executor mThreadPoolTaskExecutor = + private final ExecutorService mThreadPoolTaskExecutor = Executors.newCachedThreadPool(new ThreadFactory() { private final AtomicInteger mCount = new AtomicInteger(1); @@ -67,6 +73,13 @@ @GuardedBy("mSetLock") private HashSet<CallbackToFutureAdapter.Completer<String>> mPendingCompleterSet = new HashSet<CallbackToFutureAdapter.Completer<String>>(); + /** + * If mPendingCompleterSet is null, new evaluations will throw this exception asynchronously. + * + * Note that if the isolate is closed, IllegalStateException is thrown synchronously instead. + */ + @Nullable + private Exception mExceptionForNewEvaluations; private class IJsSandboxIsolateCallbackStubWrapper extends IJsSandboxIsolateCallback.Stub { private CallbackToFutureAdapter.Completer<String> mCompleter; @@ -83,9 +96,25 @@ @Override public void reportError(@ExecutionErrorTypes int type, String error) { - assert type == IJsSandboxIsolateCallback.JS_EVALUATION_ERROR; - mCompleter.setException(new EvaluationFailedException(error)); + boolean crashing = false; + switch (type) { + case IJsSandboxIsolateCallback.JS_EVALUATION_ERROR: + mCompleter.setException(new EvaluationFailedException(error)); + break; + case IJsSandboxIsolateCallback.MEMORY_LIMIT_EXCEEDED: + mCompleter.setException(new MemoryLimitExceededException(error)); + crashing = true; + break; + default: + mCompleter.setException(new JavaScriptException( + "Crashing due to unknown JavaScriptException: " + error)); + // Assume the worst + crashing = true; + } removePending(mCompleter); + if (crashing) { + handleCrash(); + } } } @@ -126,8 +155,8 @@ * Promise of a String in case {@link JavaScriptSandbox#JS_FEATURE_PROMISE_RETURN} is * supported * - * @return Future that evaluates to the result String of the evaluation or exceptions({@link - * IsolateTerminatedException}, {@link SandboxDeadException}) if there is an error + * @return Future that evaluates to the result String of the evaluation or exceptions (see + * {@link JavaScriptException} and subclasses) if there is an error */ @SuppressWarnings("NullAway") @NonNull @@ -136,13 +165,12 @@ throw new IllegalStateException( "Calling evaluateJavascript() after closing the Isolate"); } - return CallbackToFutureAdapter.getFuture(completer -> { final String futureDebugMessage = "evaluateJavascript Future"; IJsSandboxIsolateCallbackStubWrapper callbackStub; synchronized (mSetLock) { if (mPendingCompleterSet == null) { - completer.setException(new IsolateTerminatedException()); + completer.setException(mExceptionForNewEvaluations); return futureDebugMessage; } mPendingCompleterSet.add(completer); @@ -176,6 +204,8 @@ */ @Override public void close() { + // IllegalStateException will be thrown synchronously instead for new evaluations. + mExceptionForNewEvaluations = null; if (mJsIsolateStub == null) { return; } @@ -232,7 +262,9 @@ * * @param name Identifier for the data that is passed, the same identifier should be used in the * JavaScript environment to refer to the data - * @param inputBytes Bytes to be passed into the JavaScript environment + * @param inputBytes Bytes to be passed into the JavaScript environment. This array must not be + * modified until the JavaScript promise returned by consumeNamedDataAsArrayBuffer has + * resolved (or rejected). * * @return {@code true} on success, {@code false} if the name has already been used before, * in which case the client should use an unused name @@ -253,12 +285,19 @@ ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe(); ParcelFileDescriptor readSide = pipe[0]; ParcelFileDescriptor writeSide = pipe[1]; - OutputStream outputStream = new ParcelFileDescriptor.AutoCloseOutputStream(writeSide); - mThreadPoolTaskExecutor.execute( - () -> { convertByteArrayToStream(inputBytes, outputStream); }); + try { + OutputStream outputStream = + new ParcelFileDescriptor.AutoCloseOutputStream(writeSide); + mThreadPoolTaskExecutor.execute( + () -> { convertByteArrayToStream(inputBytes, outputStream); }); - AssetFileDescriptor asd = new AssetFileDescriptor(readSide, offset, length); - return mJsIsolateStub.provideNamedData(name, asd); + AssetFileDescriptor asd = new AssetFileDescriptor(readSide, offset, length); + return mJsIsolateStub.provideNamedData(name, asd); + } finally { + // We pass the readSide to the separate sandbox process but we still need to close + // it on our end to avoid file descriptor leaks. + readSide.close(); + } } catch (RemoteException e) { Log.e(TAG, "RemoteException was thrown during provideNamedData()", e); } catch (IOException e) { @@ -278,16 +317,27 @@ } } + /** + * Cancel all pending and future evaluations with the given exception. + * + * Only the first call to this method has any effect. + */ void cancelAllPendingEvaluations(Exception e) { final HashSet<CallbackToFutureAdapter.Completer<String>> pendingSet; synchronized (mSetLock) { if (mPendingCompleterSet == null) return; pendingSet = mPendingCompleterSet; mPendingCompleterSet = null; + mExceptionForNewEvaluations = e; } for (CallbackToFutureAdapter.Completer<String> ele : pendingSet) { ele.setException(e); } + // This is the closest thing to a .close() method for ExecutorServices. This doesn't force + // the threads or their Runnables to immediately terminate, but will ensure that once the + // worker threads finish their current runnable (if any) that the thread pool terminates + // them, preventing a leak of threads. + mThreadPoolTaskExecutor.shutdownNow(); } void removePending(CallbackToFutureAdapter.Completer<String> completer) { @@ -298,6 +348,10 @@ } } + private void handleCrash() { + cancelAllPendingEvaluations(new IsolateTerminatedException()); + } + private static void closeQuietly(Closeable closeable) { if (closeable == null) return; try {
diff --git a/android_webview/js_sandbox/java/src/androidx/javascriptengine/JavaScriptSandbox.java b/android_webview/js_sandbox/java/src/androidx/javascriptengine/JavaScriptSandbox.java index c0f4febe..e3433150 100644 --- a/android_webview/js_sandbox/java/src/androidx/javascriptengine/JavaScriptSandbox.java +++ b/android_webview/js_sandbox/java/src/androidx/javascriptengine/JavaScriptSandbox.java
@@ -464,7 +464,7 @@ */ @Override public void close() { - doClose(new IsolateTerminatedException()); + doClose(new SandboxDeadException()); } void doClose(Exception cancelPendingWith) {
diff --git a/android_webview/js_sandbox/java/src/androidx/javascriptengine/MemoryLimitExceededException.java b/android_webview/js_sandbox/java/src/androidx/javascriptengine/MemoryLimitExceededException.java new file mode 100644 index 0000000..e188651 --- /dev/null +++ b/android_webview/js_sandbox/java/src/androidx/javascriptengine/MemoryLimitExceededException.java
@@ -0,0 +1,31 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package androidx.javascriptengine; + +import androidx.annotation.NonNull; + +/** + * Indicates that a JavaScriptIsolate's evaluation failed due to exceeding its heap size limit. + * + * This exception is thrown when exceeding the heap size limit configured for the isolate via + * {@link IsolateStartupParameters}, or the default limit. It is not guaranteed to be thrown if the + * Android system as a whole has run out of memory before the JavaScript environment has reached its + * configured heap limit. + * <p> + * The isolate may not continue to be used after this exception has been thrown, and other pending + * evalutions for the isolate will fail. The isolate may continue to hold onto resources (even if + * explicitly closed) until the sandbox has been shutdown. Therefore, it is recommended that the + * sandbox be restarted at the earliest opportunity in order to reclaim these resources. + * <p> + * Other isolates within the same sandbox may continue to be used, created, and closed as normal. + */ +public final class MemoryLimitExceededException extends JavaScriptException { + public MemoryLimitExceededException(@NonNull String error) { + super(error); + } + public MemoryLimitExceededException() { + super(); + } +}
diff --git a/android_webview/js_sandbox/java/src/androidx/javascriptengine/SandboxDeadException.java b/android_webview/js_sandbox/java/src/androidx/javascriptengine/SandboxDeadException.java index b51d545d..b06695bb 100644 --- a/android_webview/js_sandbox/java/src/androidx/javascriptengine/SandboxDeadException.java +++ b/android_webview/js_sandbox/java/src/androidx/javascriptengine/SandboxDeadException.java
@@ -11,6 +11,9 @@ * <p> * This is different from {@link IsolateTerminatedException} which occurs when the * {@link JavaScriptIsolate} within a {@link JavaScriptSandbox} is terminated. + * <p> + * This exception will continue to be thrown for all future evaluation requests on unclosed + * isolates. */ public final class SandboxDeadException extends JavaScriptException { public SandboxDeadException() {
diff --git a/android_webview/js_sandbox/java/src/org/chromium/android_webview/js_sandbox/common/IJsSandboxIsolateCallback.aidl b/android_webview/js_sandbox/java/src/org/chromium/android_webview/js_sandbox/common/IJsSandboxIsolateCallback.aidl index 85ca474..f56c5a56 100644 --- a/android_webview/js_sandbox/java/src/org/chromium/android_webview/js_sandbox/common/IJsSandboxIsolateCallback.aidl +++ b/android_webview/js_sandbox/java/src/org/chromium/android_webview/js_sandbox/common/IJsSandboxIsolateCallback.aidl
@@ -12,6 +12,8 @@ oneway interface IJsSandboxIsolateCallback { // An exception was thrown during the JS evaluation. const int JS_EVALUATION_ERROR = 0; + // The evaluation failed and the isolate crashed due to running out of heap memory. + const int MEMORY_LIMIT_EXCEEDED = 1; void reportResult(String result) = 0;
diff --git a/android_webview/js_sandbox/java/src/org/chromium/android_webview/js_sandbox/service/JsSandboxIsolate.java b/android_webview/js_sandbox/java/src/org/chromium/android_webview/js_sandbox/service/JsSandboxIsolate.java index 691e626..54c91dc8 100644 --- a/android_webview/js_sandbox/java/src/org/chromium/android_webview/js_sandbox/service/JsSandboxIsolate.java +++ b/android_webview/js_sandbox/java/src/org/chromium/android_webview/js_sandbox/service/JsSandboxIsolate.java
@@ -9,7 +9,6 @@ import org.chromium.android_webview.js_sandbox.common.IJsSandboxIsolate; import org.chromium.android_webview.js_sandbox.common.IJsSandboxIsolateCallback; -import org.chromium.base.Callback; import org.chromium.base.Log; import org.chromium.base.annotations.JNINamespace; import org.chromium.base.annotations.NativeMethods; @@ -39,23 +38,24 @@ if (mJsSandboxIsolate == 0) { throw new IllegalStateException("evaluateJavascript() called after close()"); } - JsSandboxIsolateJni.get().evaluateJavascript(mJsSandboxIsolate, this, code, - (result) - -> { - try { - callback.reportResult(result); - } catch (RemoteException e) { - Log.e(TAG, "reporting result failed", e); + JsSandboxIsolateJni.get().evaluateJavascript( + mJsSandboxIsolate, this, code, new JsSandboxIsolateCallback() { + @Override + public void onResult(String result) { + try { + callback.reportResult(result); + } catch (RemoteException e) { + Log.e(TAG, "reporting result failed", e); + } } - }, - (error) -> { - try { - // Currently we only support - // IJsSandboxIsolateCallback.JS_EVALUATION_ERROR - callback.reportError( - IJsSandboxIsolateCallback.JS_EVALUATION_ERROR, error); - } catch (RemoteException e) { - Log.e(TAG, "reporting error failed", e); + + @Override + public void onError(int errorType, String error) { + try { + callback.reportError(errorType, error); + } catch (RemoteException e) { + Log.e(TAG, "reporting error failed", e); + } } }); } @@ -111,7 +111,7 @@ void destroyNative(long nativeJsSandboxIsolate, JsSandboxIsolate caller); boolean evaluateJavascript(long nativeJsSandboxIsolate, JsSandboxIsolate caller, - String script, Callback<String> successCallback, Callback<String> failureCallback); + String script, JsSandboxIsolateCallback callback); boolean provideNamedData(long nativeJsSandboxIsolate, JsSandboxIsolate caller, String name, int fd, int length);
diff --git a/android_webview/js_sandbox/java/src/org/chromium/android_webview/js_sandbox/service/JsSandboxIsolateCallback.java b/android_webview/js_sandbox/java/src/org/chromium/android_webview/js_sandbox/service/JsSandboxIsolateCallback.java new file mode 100644 index 0000000..9aac3f3 --- /dev/null +++ b/android_webview/js_sandbox/java/src/org/chromium/android_webview/js_sandbox/service/JsSandboxIsolateCallback.java
@@ -0,0 +1,32 @@ +// Copyright 2022 The Chromium Authors +// 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.js_sandbox.service; + +import org.chromium.base.annotations.CalledByNative; +import org.chromium.base.annotations.JNINamespace; + +/** + * Callback interface for the native code to report a JavaScript evaluation outcome. + */ +@JNINamespace("android_webview") +public interface JsSandboxIsolateCallback { + /** + * Called when an evaluation succeeds immediately or after its promise resolves. + * + * @param result The string result of the evaluation or resolved evaluation promise. + */ + @CalledByNative + void onResult(String result); + /** + * Called in the event of an error. + * + * @param errorType See + * {@link org.chromium.android_webview.js_sandbox.common.IJsSandboxIsolateCallback} for + * error types. + * @param error String description of the error. + */ + @CalledByNative + void onError(int errorType, String error); +}
diff --git a/android_webview/js_sandbox/javatests/src/androidx/javascriptengine/WebViewJavaScriptSandboxTest.java b/android_webview/js_sandbox/javatests/src/androidx/javascriptengine/WebViewJavaScriptSandboxTest.java index 5972fd7..d0ab5ac 100644 --- a/android_webview/js_sandbox/javatests/src/androidx/javascriptengine/WebViewJavaScriptSandboxTest.java +++ b/android_webview/js_sandbox/javatests/src/androidx/javascriptengine/WebViewJavaScriptSandboxTest.java
@@ -28,7 +28,8 @@ public class WebViewJavaScriptSandboxTest { // This value is somewhat arbitrary. It might need bumping if V8 snapshots become significantly // larger in future. However, we don't want it too large as that will make the tests slower and - // require more memory. + // require more memory. Although this is a long, it must not be greater than Integer.MAX_VALUE + // and should be much smaller (for the purposes of testing). private static final long REASONABLE_HEAP_SIZE = 100 * 1024 * 1024; @Before @@ -426,7 +427,7 @@ @Test @MediumTest - public void testEvaluationThrowsWhenSandboxDead() throws Throwable { + public void testEvaluationThrowsWhenSandboxClosed() throws Throwable { final String code = "while(true){}"; Context context = ApplicationProvider.getApplicationContext(); @@ -434,16 +435,37 @@ JavaScriptSandbox.createConnectedInstanceAsync(context); try (JavaScriptSandbox jsSandbox = jsSandboxFuture.get(5, TimeUnit.SECONDS); JavaScriptIsolate jsIsolate = jsSandbox.createIsolate()) { - ListenableFuture<String> resultFuture = jsIsolate.evaluateJavaScriptAsync(code); + ListenableFuture<String> resultFuture1 = jsIsolate.evaluateJavaScriptAsync(code); jsSandbox.close(); + // Check already running evaluation gets SandboxDeadException try { - resultFuture.get(5, TimeUnit.SECONDS); + resultFuture1.get(5, TimeUnit.SECONDS); Assert.fail("Should have thrown."); } catch (ExecutionException e) { - if (!(e.getCause() instanceof IsolateTerminatedException)) { + if (!(e.getCause() instanceof SandboxDeadException)) { throw e; } } + // Check post-close evaluation gets SandboxDeadException + ListenableFuture<String> resultFuture2 = jsIsolate.evaluateJavaScriptAsync(code); + try { + resultFuture2.get(5, TimeUnit.SECONDS); + Assert.fail("Should have thrown."); + } catch (ExecutionException e) { + if (!(e.getCause() instanceof SandboxDeadException)) { + throw e; + } + } + // Check that closing an isolate then causes the IllegalStateException to be + // thrown instead. + jsIsolate.close(); + try { + ListenableFuture<String> postCloseResultFuture = + jsIsolate.evaluateJavaScriptAsync(code); + Assert.fail("Should have thrown."); + } catch (IllegalStateException e) { + // Expected + } } } @@ -534,33 +556,152 @@ @MediumTest public void testHeapSizeEnforced() throws Throwable { final long maxHeapSize = REASONABLE_HEAP_SIZE; - // We need to beat the v8 optimizer to ensure it really allocates the required memory. - // Note that we're allocating an array of elements - not bytes. - final String code = "this.array = Array(" + maxHeapSize + ").fill(Math.random(), 0);" - + "var arrayLength = this.array.length;" - + "var sum = 0;" - + "for (var i = 0; i < arrayLength; i++) {" - + " sum+=this.array[i];" - + "}"; + // We need to beat the v8 optimizer to ensure it really allocates the required memory. Note + // that we're allocating an array of elements - not bytes. Filling will ensure that the + // array is not sparsely allocated. + final String oomingCode = "" + + "const array = Array(" + maxHeapSize + ").fill(Math.random(), 0);"; + final String stableCode = "'PASS'"; + final String stableExpected = "PASS"; + final String unresolvedCode = "new Promise((resolve, reject) => {/* never resolve */})"; Context context = ApplicationProvider.getApplicationContext(); - ListenableFuture<JavaScriptSandbox> jsSandboxFuture = + + ListenableFuture<JavaScriptSandbox> jsSandboxFuture1 = JavaScriptSandbox.createConnectedInstanceAsync(context); - try (JavaScriptSandbox jsSandbox = jsSandboxFuture.get(5, TimeUnit.SECONDS)) { + try (JavaScriptSandbox jsSandbox = jsSandboxFuture1.get(5, TimeUnit.SECONDS)) { Assume.assumeTrue(jsSandbox.isFeatureSupported( JavaScriptSandbox.JS_FEATURE_ISOLATE_MAX_HEAP_SIZE)); + Assume.assumeTrue( + jsSandbox.isFeatureSupported(JavaScriptSandbox.JS_FEATURE_PROMISE_RETURN)); IsolateStartupParameters isolateStartupParameters = new IsolateStartupParameters(); isolateStartupParameters.setMaxHeapSizeBytes(maxHeapSize); - try (JavaScriptIsolate jsIsolate = jsSandbox.createIsolate(isolateStartupParameters)) { - ListenableFuture<String> resultFuture = jsIsolate.evaluateJavaScriptAsync(code); + try (JavaScriptIsolate jsIsolate1 = jsSandbox.createIsolate(isolateStartupParameters); + JavaScriptIsolate jsIsolate2 = jsSandbox.createIsolate()) { + ListenableFuture<String> earlyUnresolvedResultFuture = + jsIsolate1.evaluateJavaScriptAsync(unresolvedCode); + ListenableFuture<String> earlyResultFuture = + jsIsolate1.evaluateJavaScriptAsync(stableCode); + ListenableFuture<String> oomResultFuture = + jsIsolate1.evaluateJavaScriptAsync(oomingCode); + + // Wait for jsIsolate2 to fully initialize before using jsIsolate1. + jsIsolate2.evaluateJavaScriptAsync(stableCode).get(5, TimeUnit.SECONDS); + + // Check that the heap limit is enforced and that it reports this was the evaluation + // that exceeded the limit. try { - resultFuture.get(10, TimeUnit.SECONDS); + oomResultFuture.get(5, TimeUnit.SECONDS); Assert.fail("Should have thrown."); } catch (ExecutionException e) { - if (!(e.getCause() instanceof SandboxDeadException)) { + if (!(e.getCause() instanceof MemoryLimitExceededException)) { throw e; } } + + // Check that the previously submitted (but unresolved) promise evaluation reports a + // crash + try { + earlyUnresolvedResultFuture.get(5, TimeUnit.SECONDS); + Assert.fail("Should have thrown."); + } catch (ExecutionException e) { + if (!(e.getCause() instanceof IsolateTerminatedException)) { + throw e; + } + } + + // Check that the previously submitted evaluation which completed before the memory + // limit was exceeded, but for which we haven't yet gotten the result, returns its + // result just fine. + String result = earlyResultFuture.get(5, TimeUnit.SECONDS); + Assert.assertEquals(stableExpected, result); + + // Check that a totally new evaluation reports a crash + ListenableFuture<String> lateResultFuture = + jsIsolate1.evaluateJavaScriptAsync(stableCode); + try { + lateResultFuture.get(5, TimeUnit.SECONDS); + Assert.fail("Should have thrown."); + } catch (ExecutionException e) { + if (!(e.getCause() instanceof IsolateTerminatedException)) { + throw e; + } + } + + // Check that other pre-existing isolates can still be used. + ListenableFuture<String> otherIsolateResultFuture = + jsIsolate2.evaluateJavaScriptAsync(stableCode); + String otherIsolateResult = otherIsolateResultFuture.get(5, TimeUnit.SECONDS); + Assert.assertEquals(stableExpected, otherIsolateResult); } } } + + @Test + @MediumTest + public void testIsolateCreationAfterCrash() throws Throwable { + final long maxHeapSize = REASONABLE_HEAP_SIZE; + // We need to beat the v8 optimizer to ensure it really allocates the required memory. Note + // that we're allocating an array of elements - not bytes. Filling will ensure that the + // array is not sparsely allocated. + final String oomingCode = "" + + "const array = Array(" + maxHeapSize + ").fill(Math.random(), 0);"; + final String stableCode = "'PASS'"; + final String stableExpected = "PASS"; + Context context = ApplicationProvider.getApplicationContext(); + + ListenableFuture<JavaScriptSandbox> jsSandboxFuture1 = + JavaScriptSandbox.createConnectedInstanceAsync(context); + try (JavaScriptSandbox jsSandbox = jsSandboxFuture1.get(5, TimeUnit.SECONDS)) { + Assume.assumeTrue(jsSandbox.isFeatureSupported( + JavaScriptSandbox.JS_FEATURE_ISOLATE_MAX_HEAP_SIZE)); + Assume.assumeTrue( + jsSandbox.isFeatureSupported(JavaScriptSandbox.JS_FEATURE_PROMISE_RETURN)); + IsolateStartupParameters isolateStartupParameters = new IsolateStartupParameters(); + isolateStartupParameters.setMaxHeapSizeBytes(maxHeapSize); + try (JavaScriptIsolate jsIsolate1 = jsSandbox.createIsolate(isolateStartupParameters)) { + ListenableFuture<String> oomResultFuture = + jsIsolate1.evaluateJavaScriptAsync(oomingCode); + + // Check that the heap limit is enforced and that it reports this was the evaluation + // that exceeded the limit. + try { + oomResultFuture.get(5, TimeUnit.SECONDS); + Assert.fail("Should have thrown."); + } catch (ExecutionException e) { + if (!(e.getCause() instanceof MemoryLimitExceededException)) { + throw e; + } + } + + // Check that other isolates can still be created and used (without closing + // jsIsolate1). + try (JavaScriptIsolate jsIsolate2 = + jsSandbox.createIsolate(isolateStartupParameters)) { + ListenableFuture<String> resultFuture = + jsIsolate2.evaluateJavaScriptAsync(stableCode); + String result = resultFuture.get(5, TimeUnit.SECONDS); + Assert.assertEquals(stableExpected, result); + } + } + + // Check that other isolates can still be created and used (after closing jsIsolate1). + try (JavaScriptIsolate jsIsolate = jsSandbox.createIsolate(isolateStartupParameters)) { + ListenableFuture<String> resultFuture = + jsIsolate.evaluateJavaScriptAsync(stableCode); + String result = resultFuture.get(5, TimeUnit.SECONDS); + Assert.assertEquals(stableExpected, result); + } + } + + // Check that the old sandbox with the "crashed" isolate can be torn down and that a new + // sandbox and isolate can be spun up. + ListenableFuture<JavaScriptSandbox> jsSandboxFuture2 = + JavaScriptSandbox.createConnectedInstanceAsync(context); + try (JavaScriptSandbox jsSandbox = jsSandboxFuture2.get(5, TimeUnit.SECONDS); + JavaScriptIsolate jsIsolate = jsSandbox.createIsolate()) { + ListenableFuture<String> resultFuture = jsIsolate.evaluateJavaScriptAsync(stableCode); + String result = resultFuture.get(5, TimeUnit.SECONDS); + Assert.assertEquals(stableExpected, result); + } + } }
diff --git a/android_webview/js_sandbox/service/BUILD.gn b/android_webview/js_sandbox/service/BUILD.gn index a4c0555..29f1f41 100644 --- a/android_webview/js_sandbox/service/BUILD.gn +++ b/android_webview/js_sandbox/service/BUILD.gn
@@ -6,6 +6,8 @@ sources = [ "js_sandbox_isolate.cc", "js_sandbox_isolate.h", + "js_sandbox_isolate_callback.cc", + "js_sandbox_isolate_callback.h", ] deps = [
diff --git a/android_webview/js_sandbox/service/js_sandbox_isolate.cc b/android_webview/js_sandbox/service/js_sandbox_isolate.cc index afc8031..59354ee 100644 --- a/android_webview/js_sandbox/service/js_sandbox_isolate.cc +++ b/android_webview/js_sandbox/service/js_sandbox_isolate.cc
@@ -10,14 +10,18 @@ #include <string> #include "android_webview/js_sandbox/js_sandbox_jni_headers/JsSandboxIsolate_jni.h" +#include "android_webview/js_sandbox/service/js_sandbox_isolate_callback.h" #include "base/android/callback_android.h" #include "base/android/jni_android.h" #include "base/android/jni_string.h" +#include "base/auto_reset.h" #include "base/bind.h" #include "base/files/file_util.h" +#include "base/immediate_crash.h" #include "base/logging.h" #include "base/memory/raw_ptr.h" #include "base/strings/string_piece.h" +#include "base/synchronization/waitable_event.h" #include "base/system/sys_info.h" #include "base/task/cancelable_task_tracker.h" #include "base/task/single_thread_task_runner.h" @@ -34,6 +38,7 @@ #include "js_sandbox_isolate.h" #include "v8/include/v8-function.h" #include "v8/include/v8-microtask-queue.h" +#include "v8/include/v8-statistics.h" #include "v8/include/v8-template.h" using base::android::ConvertJavaStringToUTF8; @@ -113,6 +118,7 @@ CHECK(resolver->Reject(context, compilation_result).FromJust()); } } + } // namespace namespace android_webview { @@ -133,8 +139,9 @@ length = len; } -JsSandboxIsolate::JsSandboxIsolate(jlong max_heap_size_bytes) { - isolate_max_heap_size_bytes_ = max_heap_size_bytes; +JsSandboxIsolate::JsSandboxIsolate(jlong max_heap_size_bytes) + : isolate_max_heap_size_bytes_(max_heap_size_bytes) { + CHECK_GE(isolate_max_heap_size_bytes_, 0); control_task_runner_ = base::ThreadPool::CreateSequencedTaskRunner({}); isolate_task_runner_ = base::ThreadPool::CreateSingleThreadTaskRunner( {base::TaskPriority::USER_BLOCKING, @@ -163,19 +170,16 @@ JNIEnv* env, const base::android::JavaParamRef<jobject>& obj, const base::android::JavaParamRef<jstring>& jcode, - const base::android::JavaParamRef<jobject>& j_success_callback, - const base::android::JavaParamRef<jobject>& j_failure_callback) { + const base::android::JavaParamRef<jobject>& j_callback) { std::string code = ConvertJavaStringToUTF8(env, jcode); + std::unique_ptr<JsSandboxIsolateCallback> callback = + std::make_unique<JsSandboxIsolateCallback>( + base::android::ScopedJavaGlobalRef(j_callback)); control_task_runner_->PostTask( FROM_HERE, base::BindOnce(&JsSandboxIsolate::PostEvaluationToIsolateThread, base::Unretained(this), std::move(code), - base::BindOnce(&base::android::RunStringCallbackAndroid, - base::android::ScopedJavaGlobalRef<jobject>( - j_success_callback)), - base::BindOnce(&base::android::RunStringCallbackAndroid, - base::android::ScopedJavaGlobalRef<jobject>( - j_failure_callback)))); + std::move(callback))); return true; } @@ -205,13 +209,12 @@ // Called from control sequence. void JsSandboxIsolate::PostEvaluationToIsolateThread( const std::string code, - FinishedCallback success_callback, - FinishedCallback error_callback) { + std::unique_ptr<JsSandboxIsolateCallback> callback) { cancelable_task_tracker_->PostTask( isolate_task_runner_.get(), FROM_HERE, base::BindOnce(&JsSandboxIsolate::EvaluateJavascriptOnThread, base::Unretained(this), std::move(code), - std::move(success_callback), std::move(error_callback))); + std::move(callback))); } // Called from control sequence. @@ -317,6 +320,9 @@ } // Called from isolate thread. +// +// Note that this will never be called if the isolate has "crashed" due to OOM +// and frozen its isolate thread. void JsSandboxIsolate::DeleteSelf() { delete this; } @@ -337,6 +343,9 @@ v8::Isolate::Scope isolate_scope(isolate); isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kAuto); isolate->SetWasmAsyncResolvePromiseCallback(WasmAsyncResolvePromiseCallback); + + isolate->AddNearHeapLimitCallback(&JsSandboxIsolate::NearHeapLimitCallback, + this); v8::HandleScope handle_scope(isolate); v8::Local<v8::ObjectTemplate> android_template = @@ -355,8 +364,10 @@ // Called from isolate thread. void JsSandboxIsolate::EvaluateJavascriptOnThread( const std::string code, - FinishedCallback success_callback, - FinishedCallback error_callback) { + std::unique_ptr<JsSandboxIsolateCallback> callback) { + base::AutoReset<JsSandboxIsolateCallback*> callback_autoreset( + ¤t_callback_, callback.get()); + v8::Isolate::Scope isolate_scope(isolate_holder_->isolate()); v8::HandleScope handle_scope(isolate_holder_->isolate()); v8::Context::Scope scope(context_holder_->context()); @@ -374,7 +385,7 @@ } v8::Local<v8::Script> script; if (!maybe_script.ToLocal(&script)) { - std::move(error_callback).Run(compile_error); + std::move(callback)->ReportJsEvaluationError(compile_error); return; } @@ -397,26 +408,27 @@ // directly. if (promise->State() == v8::Promise::PromiseState::kFulfilled) { std::string result = gin::V8ToString(v8_isolate, promise->Result()); - std::move(success_callback).Run(result); + std::move(callback)->ReportResult(result); return; } if (promise->State() == v8::Promise::PromiseState::kRejected) { v8::Local<v8::Message> message = v8::Exception::CreateMessage( isolate_holder_->isolate(), promise->Result()); std::string error_message = GetStackTrace(message, v8_isolate); - std::move(error_callback).Run(error_message); + std::move(callback)->ReportJsEvaluationError(error_message); return; } v8::Local<v8::Function> fulfill_fun = gin::CreateFunctionTemplate( v8_isolate, base::BindRepeating( - [](FinishedCallback success_callback, gin::Arguments* args) { + [](std::unique_ptr<JsSandboxIsolateCallback> callback, + gin::Arguments* args) { std::string output; args->GetNext(&output); - std::move(success_callback).Run(output); + std::move(callback)->ReportResult(output); }, - base::Passed(std::move(success_callback)))) + base::Passed(std::move(callback)))) ->GetFunction(context_holder_->context()) .ToLocalChecked(); v8::Local<v8::Function> reject_fun = @@ -424,7 +436,7 @@ v8_isolate, base::BindRepeating(&JsSandboxIsolate::PromiseRejectCallback, base::Unretained(this), - base::Passed(std::move(error_callback)))) + base::Passed(std::move(callback)))) ->GetFunction(context_holder_->context()) .ToLocalChecked(); @@ -432,22 +444,23 @@ .ToLocalChecked(); } else { std::string result = gin::V8ToString(v8_isolate, value); - std::move(success_callback).Run(result); + std::move(callback)->ReportResult(result); } } else { - std::move(error_callback).Run(run_error); + std::move(callback)->ReportJsEvaluationError(run_error); } } -void JsSandboxIsolate::PromiseRejectCallback(FinishedCallback error_callback, - gin::Arguments* args) { +void JsSandboxIsolate::PromiseRejectCallback( + std::unique_ptr<JsSandboxIsolateCallback> callback, + gin::Arguments* args) { v8::Local<v8::Value> value; args->GetNext(&value); v8::Local<v8::Message> message = v8::Exception::CreateMessage(isolate_holder_->isolate(), value); std::string error_message = GetStackTrace(message, isolate_holder_->isolate()); - std::move(error_callback).Run(error_message); + std::move(callback)->ReportJsEvaluationError(error_message); } // Called from isolate thread. @@ -529,6 +542,50 @@ args->Return(promise); } +// Called from isolate thread. +[[noreturn]] size_t JsSandboxIsolate::NearHeapLimitCallback( + void* data, + size_t /*current_heap_limit*/, + size_t /*initial_heap_limit*/) { + android_webview::JsSandboxIsolate* js_sandbox_isolate = + static_cast<android_webview::JsSandboxIsolate*>(data); + js_sandbox_isolate->MemoryLimitExceeded(); +} + +// Called from isolate thread. +[[noreturn]] void JsSandboxIsolate::MemoryLimitExceeded() { + LOG(ERROR) << "Isolate has OOMed"; + // TODO(ashleynewson): An isolate could run out of memory outside of an + // evaluation when processing asynchronous code. We should add a crash + // signalling mechanism which doesn't rely on us having a callback for a + // currently running evaluation. + CHECK(current_callback_) + << "Isolate ran out of memory outside of an evaluation."; + uint64_t memory_limit = static_cast<uint64_t>(isolate_max_heap_size_bytes_); + v8::HeapStatistics heap_statistics; + isolate_holder_->isolate()->GetHeapStatistics(&heap_statistics); + uint64_t heap_usage = heap_statistics.used_heap_size(); + current_callback_->ReportMemoryLimitExceededError(memory_limit, heap_usage); + FreezeThread(); +} + +// Halt thread until process dies. +[[noreturn]] void JsSandboxIsolate::FreezeThread() { + // There is no well-defined way to fully terminate a thread prematurely, so we + // idle the thread forever. + // + // TODO(ashleynewson): In future, we may want to look into ways to cleanup or + // even properly terminate the thread if language or V8 features allow for it, + // as we currently hold onto (essentially leaking) all resources this isolate + // has accumulated up to this point. C++20's <stop_token> (not permitted in + // Chromium at time of writing) may contribute to such a future solution. + + base::ScopedAllowBaseSyncPrimitives allow_base_sync_primitives; + base::WaitableEvent().Wait(); + // Unreachable. Make sure the compiler understands that. + base::ImmediateCrash(); +} + static void JNI_JsSandboxIsolate_InitializeEnvironment(JNIEnv* env) { base::ThreadPoolInstance::CreateAndStartWithDefaultParams("JsSandboxIsolate"); #ifdef V8_USE_EXTERNAL_STARTUP_DATA
diff --git a/android_webview/js_sandbox/service/js_sandbox_isolate.h b/android_webview/js_sandbox/service/js_sandbox_isolate.h index a0322e8..2ccd409b 100644 --- a/android_webview/js_sandbox/service/js_sandbox_isolate.h +++ b/android_webview/js_sandbox/service/js_sandbox_isolate.h
@@ -38,20 +38,18 @@ namespace android_webview { class FdWithLength; +class JsSandboxIsolateCallback; class JsSandboxIsolate { public: explicit JsSandboxIsolate(jlong max_heap_size_bytes = 0); ~JsSandboxIsolate(); - using FinishedCallback = base::OnceCallback<void(const std::string&)>; - jboolean EvaluateJavascript( JNIEnv* env, const base::android::JavaParamRef<jobject>& obj, const base::android::JavaParamRef<jstring>& jcode, - const base::android::JavaParamRef<jobject>& j_success_callback, - const base::android::JavaParamRef<jobject>& j_failure_callback); + const base::android::JavaParamRef<jobject>& j_callback); void DestroyNative(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj); jboolean ProvideNamedData(JNIEnv* env, @@ -63,19 +61,19 @@ private: void DeleteSelf(); void InitializeIsolateOnThread(); - void EvaluateJavascriptOnThread(const std::string code, - FinishedCallback success_callback, - FinishedCallback failure_callback); - void PromiseRejectCallback(FinishedCallback error_callback, + void EvaluateJavascriptOnThread( + const std::string code, + std::unique_ptr<JsSandboxIsolateCallback> callback); + void PromiseRejectCallback(std::unique_ptr<JsSandboxIsolateCallback> callback, gin::Arguments* args); void TerminateAndDestroy(); void DestroyWhenPossible(); void NotifyInitComplete(); void CreateCancelableTaskTracker(); - void PostEvaluationToIsolateThread(const std::string code, - FinishedCallback success_callback, - FinishedCallback error_callback); + void PostEvaluationToIsolateThread( + const std::string code, + std::unique_ptr<JsSandboxIsolateCallback> callback); void ConvertPromiseToArrayBufferInThreadPool(base::ScopedFD fd, ssize_t length, std::string name); @@ -94,6 +92,14 @@ v8::Local<v8::ObjectTemplate> CreateAndroidNamespaceTemplate( v8::Isolate* isolate); + // Must only be used from isolate thread + [[noreturn]] static size_t NearHeapLimitCallback(void* data, + size_t current_heap_limit, + size_t initial_heap_limit); + // Must only be used from isolate thread + [[noreturn]] void MemoryLimitExceeded(); + [[noreturn]] void FreezeThread(); + // Used as a control sequence to add ordering to binder threadpool requests. scoped_refptr<base::SequencedTaskRunner> control_task_runner_; // Should be used from control_task_runner_. @@ -116,7 +122,19 @@ base::Lock named_fd_lock_; std::unordered_map<std::string, FdWithLength> named_fd_ GUARDED_BY(named_fd_lock_); - jlong isolate_max_heap_size_bytes_; + // V8 heap size limit. Must be non-negative. + // + // 0 indicates no explicit limit (but use the default V8 limits). + const jlong isolate_max_heap_size_bytes_; + + // The callback associated with the current evaluation, if any. Used for + // signaling errors from V8 callbacks. + // + // This can be nullptr outside of active evaluation, including when the result + // of an evaluation is a JS promise which is pending resolution/rejection. + // + // This pointer must only be accessed from the isolate thread. + JsSandboxIsolateCallback* current_callback_; }; } // namespace android_webview
diff --git a/android_webview/js_sandbox/service/js_sandbox_isolate_callback.cc b/android_webview/js_sandbox/service/js_sandbox_isolate_callback.cc new file mode 100644 index 0000000..d703f11 --- /dev/null +++ b/android_webview/js_sandbox/service/js_sandbox_isolate_callback.cc
@@ -0,0 +1,58 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "android_webview/js_sandbox/service/js_sandbox_isolate_callback.h" + +#include <jni.h> +#include <sstream> + +#include "android_webview/js_sandbox/js_sandbox_jni_headers/JsSandboxIsolateCallback_jni.h" +#include "base/android/jni_android.h" +#include "base/android/jni_string.h" +#include "base/android/scoped_java_ref.h" + +namespace android_webview { + +JsSandboxIsolateCallback::JsSandboxIsolateCallback( + base::android::ScopedJavaGlobalRef<jobject>&& callback) + : callback_(std::move(callback)) {} + +JsSandboxIsolateCallback::~JsSandboxIsolateCallback() = default; + +void JsSandboxIsolateCallback::ReportResult(const std::string& result) { + JNIEnv* env = base::android::AttachCurrentThread(); + base::android::ScopedJavaLocalRef<jstring> java_string_result = + base::android::ConvertUTF8ToJavaString(env, result); + Java_JsSandboxIsolateCallback_onResult(env, callback_, java_string_result); +} + +void JsSandboxIsolateCallback::ReportJsEvaluationError( + const std::string& error) { + ReportError(ErrorType::kJsEvaluationError, error); +} + +void JsSandboxIsolateCallback::ReportMemoryLimitExceededError( + const uint64_t memory_limit, + const uint64_t heap_usage) { + std::ostringstream details; + details << "Memory limit exceeded.\n"; + if (memory_limit > 0) { + details << "Memory limit: " << memory_limit << " bytes\n"; + } else { + details << "Memory limit not explicitly configured\n"; + } + details << "Heap usage: " << heap_usage << " bytes\n"; + ReportError(ErrorType::kMemoryLimitExceeded, details.str()); +} + +void JsSandboxIsolateCallback::ReportError(const ErrorType error_type, + const std::string& error) { + JNIEnv* env = base::android::AttachCurrentThread(); + base::android::ScopedJavaLocalRef<jstring> java_string_error = + base::android::ConvertUTF8ToJavaString(env, error); + Java_JsSandboxIsolateCallback_onError( + env, callback_, static_cast<jint>(error_type), java_string_error); +} + +} // namespace android_webview
diff --git a/android_webview/js_sandbox/service/js_sandbox_isolate_callback.h b/android_webview/js_sandbox/service/js_sandbox_isolate_callback.h new file mode 100644 index 0000000..ea563bb --- /dev/null +++ b/android_webview/js_sandbox/service/js_sandbox_isolate_callback.h
@@ -0,0 +1,45 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ANDROID_WEBVIEW_JS_SANDBOX_SERVICE_JS_SANDBOX_ISOLATE_CALLBACK_H_ +#define ANDROID_WEBVIEW_JS_SANDBOX_SERVICE_JS_SANDBOX_ISOLATE_CALLBACK_H_ + +#include <jni.h> + +#include "base/android/scoped_java_ref.h" + +namespace android_webview { + +class JsSandboxIsolateCallback final { + public: + enum class ErrorType { + kJsEvaluationError = 0, + kMemoryLimitExceeded = 1, + }; + + explicit JsSandboxIsolateCallback( + base::android::ScopedJavaGlobalRef<jobject>&& callback); + JsSandboxIsolateCallback(const JsSandboxIsolateCallback&) = delete; + JsSandboxIsolateCallback& operator=(const JsSandboxIsolateCallback&) = delete; + ~JsSandboxIsolateCallback(); + + void ReportResult(const std::string& result); + void ReportJsEvaluationError(const std::string& error); + // Report that the isolate has exceeded its memory limit, with various stats. + // + // memory_limit == 0 indicates that no explicit limit was configured. + // + // heap_usage describes memory usage before the failed allocation. + void ReportMemoryLimitExceededError(uint64_t memory_limit, + uint64_t heap_usage); + + private: + void ReportError(ErrorType error_type, const std::string& error); + + base::android::ScopedJavaGlobalRef<jobject> callback_; +}; + +} // namespace android_webview + +#endif // ANDROID_WEBVIEW_JS_SANDBOX_SERVICE_JS_SANDBOX_ISOLATE_CALLBACK_H_
diff --git a/ash/app_list/app_list_presenter_unittest.cc b/ash/app_list/app_list_presenter_unittest.cc index c25dc0a..e5b46ed 100644 --- a/ash/app_list/app_list_presenter_unittest.cc +++ b/ash/app_list/app_list_presenter_unittest.cc
@@ -3132,13 +3132,13 @@ test_result->set_display_type(SearchResultDisplayType::kList); search_model->results()->Add(std::move(test_result)); - auto test_tile_result = std::make_unique<TestSearchResult>(); - test_tile_result->set_result_id("test_tile"); + auto test_list_result = std::make_unique<TestSearchResult>(); + test_list_result->set_result_id("test_list"); // Give this item a name so that the accessibility paint checks pass. // (Focusable items should have accessible names.) - test_tile_result->SetAccessibleName(u"test_tile"); - test_tile_result->set_display_type(SearchResultDisplayType::kTile); - search_model->results()->Add(std::move(test_tile_result)); + test_list_result->SetAccessibleName(u"test_list"); + test_list_result->set_display_type(SearchResultDisplayType::kList); + search_model->results()->Add(std::move(test_list_result)); // The results are updated asynchronously. Wait until the update is finished. base::RunLoop().RunUntilIdle(); @@ -3173,13 +3173,13 @@ test_result_override->set_display_type(SearchResultDisplayType::kList); search_model_override->results()->Add(std::move(test_result_override)); - auto test_tile_result_override = std::make_unique<TestSearchResult>(); - test_tile_result_override->set_result_id("test_tile_override"); + auto test_list_result_override = std::make_unique<TestSearchResult>(); + test_list_result_override->set_result_id("test_list_override"); // Give this item a name so that the accessibility paint checks pass. // (Focusable items should have accessible names.) - test_tile_result_override->SetAccessibleName(u"test_tile_override"); - test_tile_result_override->set_display_type(SearchResultDisplayType::kTile); - search_model_override->results()->Add(std::move(test_tile_result_override)); + test_list_result_override->SetAccessibleName(u"test_list_override"); + test_list_result_override->set_display_type(SearchResultDisplayType::kList); + search_model_override->results()->Add(std::move(test_list_result_override)); // The results are updated asynchronously. Wait until the update is finished. base::RunLoop().RunUntilIdle();
diff --git a/ash/app_list/views/search_result_list_view_unittest.cc b/ash/app_list/views/search_result_list_view_unittest.cc index f2c6458f6..0661cfb 100644 --- a/ash/app_list/views/search_result_list_view_unittest.cc +++ b/ash/app_list/views/search_result_list_view_unittest.cc
@@ -421,31 +421,5 @@ ExpectConsistent(); } -TEST_P(SearchResultListViewTest, HidesAssistantResultWhenTilesVisible) { - SetUpSearchResults(); - - // No assistant results available. - EXPECT_TRUE(GetAssistantResultViews().empty()); - - AddAssistantSearchResult(); - - // Assistant result should be set and visible. - for (const auto* view : GetAssistantResultViews()) { - EXPECT_TRUE(view->GetVisible()); - EXPECT_EQ(view->result()->title(), u"assistant result"); - } - - // Add a tile result - std::unique_ptr<TestSearchResult> tile_result = - std::make_unique<TestSearchResult>(); - tile_result->set_display_type(ash::SearchResultDisplayType::kTile); - GetResults()->Add(std::move(tile_result)); - - RunPendingMessages(); - - // Assistant result should be gone. - EXPECT_TRUE(GetAssistantResultViews().empty()); -} - } // namespace test } // namespace ash
diff --git a/ash/app_list/views/search_result_page_view.cc b/ash/app_list/views/search_result_page_view.cc index 41455061..c24cff78 100644 --- a/ash/app_list/views/search_result_page_view.cc +++ b/ash/app_list/views/search_result_page_view.cc
@@ -219,15 +219,6 @@ result_container_ptr->set_delegate(this); } -bool SearchResultPageView::IsFirstResultTile() const { - // In the event that the result does not exist, it is not a tile. - if (!first_result_view_ || !first_result_view_->result()) - return false; - - return first_result_view_->result()->display_type() == - SearchResultDisplayType::kTile; -} - bool SearchResultPageView::IsFirstResultHighlighted() const { DCHECK(first_result_view_); return first_result_view_->selected();
diff --git a/ash/app_list/views/search_result_page_view.h b/ash/app_list/views/search_result_page_view.h index 3f2dde31..406cb60 100644 --- a/ash/app_list/views/search_result_page_view.h +++ b/ash/app_list/views/search_result_page_view.h
@@ -50,7 +50,6 @@ return result_container_views_; } - bool IsFirstResultTile() const; bool IsFirstResultHighlighted() const; // Overridden from views::View:
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd index 3e2c5a36..a4585be 100644 --- a/ash/ash_strings.grd +++ b/ash/ash_strings.grd
@@ -884,10 +884,10 @@ Keyboard backlight is on </message> <message name="IDS_ASH_STATUS_AREA_TOAST_MIC_OFF" desc="The text in the toast that shows up when the mic is muted using a physical key or shortcut."> - Microphone is off + Device microphone access is off </message> <message name="IDS_ASH_STATUS_AREA_TOAST_MIC_ON" desc="The text in the toast that shows up when the mic is unmuted using a physical key or shortcut."> - Microphone is on + Device microphone access is on </message> <message name="IDS_ASH_STATUS_TRAY_VOLUME" desc="The accessible text for the toggle volume muted button in the tray."> Toggle Volume. <ph name="STATE_TEXT">$1<ex>Volume is muted</ex></ph>
diff --git a/ash/ash_strings_grd/IDS_ASH_STATUS_AREA_TOAST_MIC_OFF.png.sha1 b/ash/ash_strings_grd/IDS_ASH_STATUS_AREA_TOAST_MIC_OFF.png.sha1 index 5e221a2..a90a97e 100644 --- a/ash/ash_strings_grd/IDS_ASH_STATUS_AREA_TOAST_MIC_OFF.png.sha1 +++ b/ash/ash_strings_grd/IDS_ASH_STATUS_AREA_TOAST_MIC_OFF.png.sha1
@@ -1 +1 @@ -2eec248082c775e6293ba3bad6a7ff88b2b7f287 \ No newline at end of file +f38e527e9408214d6938eb86a6267c74361e212f \ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_STATUS_AREA_TOAST_MIC_ON.png.sha1 b/ash/ash_strings_grd/IDS_ASH_STATUS_AREA_TOAST_MIC_ON.png.sha1 index 173e4d83..4e13c45 100644 --- a/ash/ash_strings_grd/IDS_ASH_STATUS_AREA_TOAST_MIC_ON.png.sha1 +++ b/ash/ash_strings_grd/IDS_ASH_STATUS_AREA_TOAST_MIC_ON.png.sha1
@@ -1 +1 @@ -d5affacf158cd422891415d0d6491d61232a73c7 \ No newline at end of file +3fbc7839d4130768848a1b4424ced74b0c75d7d9 \ No newline at end of file
diff --git a/ash/public/cpp/app_list/app_list_config.cc b/ash/public/cpp/app_list/app_list_config.cc index a20479b..e37acc5c 100644 --- a/ash/public/cpp/app_list/app_list_config.cc +++ b/ash/public/cpp/app_list/app_list_config.cc
@@ -146,10 +146,6 @@ switch (display_type) { case SearchResultDisplayType::kList: return search_list_icon_dimension_; - case SearchResultDisplayType::kTile: - return search_tile_icon_dimension_; - case SearchResultDisplayType::kChip: - return suggestion_chip_icon_dimension_; case SearchResultDisplayType::kContinue: return suggestion_chip_icon_dimension_; case SearchResultDisplayType::kNone:
diff --git a/ash/public/cpp/app_list/app_list_types.h b/ash/public/cpp/app_list/app_list_types.h index 782a856..c11485b 100644 --- a/ash/public/cpp/app_list/app_list_types.h +++ b/ash/public/cpp/app_list/app_list_types.h
@@ -18,7 +18,6 @@ #include "ui/base/models/image_model.h" #include "ui/gfx/image/image_skia.h" #include "ui/gfx/range/range.h" -#include "url/gurl.h" namespace ash { @@ -412,16 +411,13 @@ // Which UI container(s) the result should be displayed in. // Do not change the order of these as they are used for metrics. -// -// TODO(https://crbug.com/1258415): kChip can be deprecated once -// ProductivityLauncher is launched. enum class SearchResultDisplayType { kNone = 0, kList = 1, // Displays in search list - kTile = 2, // Displays in search tiles + // kTile = 2, // No longer used, Displays in search tiles // kRecommendation = 3 // No longer used, split between kTile and kChip kAnswerCard = 4, // Displays in answer cards - kChip = 5, // Displays in suggestion chips + // kChip = 5, // No longer used, Displays in suggestion chips kContinue = 6, // Displays in the Continue section kRecentApps = 7, // Displays in recent apps row // Add new values here
diff --git a/ash/webui/camera_app_ui/OWNERS b/ash/webui/camera_app_ui/OWNERS index 9fe3d698..3d66d748 100644 --- a/ash/webui/camera_app_ui/OWNERS +++ b/ash/webui/camera_app_ui/OWNERS
@@ -1,5 +1,6 @@ chuhsuan@chromium.org jcliang@chromium.org +kamchonlathorn@chromium.org pihsun@chromium.org shik@chromium.org wtlee@chromium.org
diff --git a/ash/webui/common/resources/office_fallback/office_fallback_dialog.ts b/ash/webui/common/resources/office_fallback/office_fallback_dialog.ts index 0f8a7475..ab40117 100644 --- a/ash/webui/common/resources/office_fallback/office_fallback_dialog.ts +++ b/ash/webui/common/resources/office_fallback/office_fallback_dialog.ts
@@ -164,4 +164,10 @@ } } +declare global { + interface HTMLElementTagNameMap { + 'office-fallback': OfficeFallbackElement; + } +} + customElements.define('office-fallback', OfficeFallbackElement); \ No newline at end of file
diff --git a/ash/webui/files_internals/files_internals_page_handler.cc b/ash/webui/files_internals/files_internals_page_handler.cc index 1911dd2..264b0c0 100644 --- a/ash/webui/files_internals/files_internals_page_handler.cc +++ b/ash/webui/files_internals/files_internals_page_handler.cc
@@ -36,4 +36,14 @@ files_internals_ui_->delegate()->SetOfficeSetupComplete(complete); } +void FilesInternalsPageHandler::GetAlwaysMoveOfficeFiles( + GetAlwaysMoveOfficeFilesCallback callback) { + std::move(callback).Run( + files_internals_ui_->delegate()->GetAlwaysMoveOfficeFiles()); +} + +void FilesInternalsPageHandler::SetAlwaysMoveOfficeFiles(bool always_move) { + files_internals_ui_->delegate()->SetAlwaysMoveOfficeFiles(always_move); +} + } // namespace ash
diff --git a/ash/webui/files_internals/files_internals_page_handler.h b/ash/webui/files_internals/files_internals_page_handler.h index a07517db..ab8b1e5 100644 --- a/ash/webui/files_internals/files_internals_page_handler.h +++ b/ash/webui/files_internals/files_internals_page_handler.h
@@ -31,6 +31,9 @@ void SetSmbfsEnableVerboseLogging(bool enabled) override; void GetOfficeSetupComplete(GetOfficeSetupCompleteCallback callback) override; void SetOfficeSetupComplete(bool complete) override; + void GetAlwaysMoveOfficeFiles( + GetAlwaysMoveOfficeFilesCallback callback) override; + void SetAlwaysMoveOfficeFiles(bool always_move) override; private: raw_ptr<FilesInternalsUI> files_internals_ui_; // Owns |this|.
diff --git a/ash/webui/files_internals/files_internals_ui_delegate.h b/ash/webui/files_internals/files_internals_ui_delegate.h index 686fcba7..04d366f5 100644 --- a/ash/webui/files_internals/files_internals_ui_delegate.h +++ b/ash/webui/files_internals/files_internals_ui_delegate.h
@@ -21,6 +21,9 @@ virtual bool GetOfficeSetupComplete() const = 0; virtual void SetOfficeSetupComplete(bool complete) = 0; + + virtual bool GetAlwaysMoveOfficeFiles() const = 0; + virtual void SetAlwaysMoveOfficeFiles(bool always_move) = 0; }; } // namespace ash
diff --git a/ash/webui/files_internals/mojom/files_internals.mojom b/ash/webui/files_internals/mojom/files_internals.mojom index 7df45c8a..82a6bcb 100644 --- a/ash/webui/files_internals/mojom/files_internals.mojom +++ b/ash/webui/files_internals/mojom/files_internals.mojom
@@ -15,4 +15,9 @@ GetOfficeSetupComplete() => (bool complete); // Sets the filebrowser.office.setup_complete pref. SetOfficeSetupComplete(bool complete); + + // Gets the filebrowser.office.setup_complete pref. + GetAlwaysMoveOfficeFiles() => (bool always_move); + // Sets the filebrowser.office.setup_complete pref. + SetAlwaysMoveOfficeFiles(bool always_move); };
diff --git a/ash/webui/files_internals/resources/index.html b/ash/webui/files_internals/resources/index.html index e1f192167..865b78c4 100644 --- a/ash/webui/files_internals/resources/index.html +++ b/ash/webui/files_internals/resources/index.html
@@ -35,6 +35,8 @@ <h2>Office file handlers</h2> <p>Office setup complete?: <span id="office-setup-complete-status"></span></p> <button id="clear-office-setup-complete">Clear Office setup complete</button> +<p>Always move files?: <span id="office-always-move-status"></span></p> +<button id="clear-office-always-move">Always ask before moving</button> </body> </html>
diff --git a/ash/webui/files_internals/resources/index.js b/ash/webui/files_internals/resources/index.js index 29ec146..abf334a 100644 --- a/ash/webui/files_internals/resources/index.js +++ b/ash/webui/files_internals/resources/index.js
@@ -26,4 +26,15 @@ const officeSetupComplete = (await pageHandler.getOfficeSetupComplete()).complete; officeSetupStatus.innerText = officeSetupComplete ? 'Yes' : 'No'; + + const clearAlwaysMoveButton = + document.getElementById('clear-office-always-move'); + clearAlwaysMoveButton.addEventListener('click', () => { + pageHandler.setAlwaysMoveOfficeFiles(false); + }); + const officeAlwaysMoveStatus = + document.getElementById('office-always-move-status'); + const officeAlwaysMove = + (await pageHandler.getAlwaysMoveOfficeFiles()).alwaysMove; + officeAlwaysMoveStatus.innerText = officeAlwaysMove ? 'Yes' : 'No'; });
diff --git a/base/BUILD.gn b/base/BUILD.gn index 1484cc6..58bed8e 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -1744,13 +1744,18 @@ sources += [ "profiler/chrome_unwind_info_android.cc", "profiler/chrome_unwind_info_android.h", - "profiler/chrome_unwinder_android.cc", - "profiler/chrome_unwinder_android.h", "profiler/chrome_unwinder_android_v2.cc", "profiler/chrome_unwinder_android_v2.h", ] } + if (current_cpu == "arm64") { + sources += [ + "profiler/frame_pointer_unwinder.cc", + "profiler/frame_pointer_unwinder.h", + ] + } + if (current_cpu != "arm" && current_cpu != "arm64") { # The reached code profiler is only supported on Android arm arch. sources -= [ "android/reached_code_profiler.cc" ] @@ -2640,7 +2645,6 @@ flags = [ "ENABLE_ARM_CFI_TABLE=$enable_arm_cfi_table", "IOS_STACK_PROFILER_ENABLED=$ios_stack_profiler_enabled", - "USE_ANDROID_UNWINDER_V2=$use_android_unwinder_v2", ] } @@ -3636,10 +3640,12 @@ if (current_cpu == "arm") { sources += [ "profiler/chrome_unwind_info_android_unittest.cc", - "profiler/chrome_unwinder_android_unittest.cc", "profiler/chrome_unwinder_android_v2_unittest.cc", ] } + if (current_cpu == "arm64") { + sources += [ "profiler/frame_pointer_unwinder_unittest.cc" ] + } if (!exclude_unwind_tables && (current_cpu == "arm" || current_cpu == "arm64")) { sources += [
diff --git a/base/android/jni_array.cc b/base/android/jni_array.cc index 679bf7b..2de7862b 100644 --- a/base/android/jni_array.cc +++ b/base/android/jni_array.cc
@@ -4,29 +4,12 @@ #include "base/android/jni_array.h" -#include <ostream> - #include "base/android/jni_android.h" #include "base/android/jni_string.h" #include "base/check_op.h" #include "base/numerics/safe_conversions.h" -namespace base { -namespace android { -namespace { - -// As |GetArrayLength| makes no guarantees about the returned value (e.g., it -// may be -1 if |array| is not a valid Java array), provide a safe wrapper -// that always returns a valid, non-negative size. -template <typename JavaArrayType> -size_t SafeGetArrayLength(JNIEnv* env, const JavaRef<JavaArrayType>& jarray) { - DCHECK(jarray); - jsize length = env->GetArrayLength(jarray.obj()); - DCHECK_GE(length, 0) << "Invalid array length: " << length; - return static_cast<size_t>(std::max(0, length)); -} - -} // namespace +namespace base::android { ScopedJavaLocalRef<jbyteArray> ToJavaByteArray(JNIEnv* env, const uint8_t* bytes, @@ -374,6 +357,19 @@ AppendJavaByteArrayToByteVector(env, byte_array, out); } +size_t JavaByteArrayToByteSpan(JNIEnv* env, + const JavaRef<jbyteArray>& byte_array, + base::span<uint8_t> dest) { + CHECK(byte_array); + size_t len = SafeGetArrayLength(env, byte_array); + size_t span_len = dest.size_bytes(); + CHECK_GE(span_len, len) << "Target span is too small, java array size: " + << len << ", span size: " << span_len; + env->GetByteArrayRegion(byte_array.obj(), 0, static_cast<jsize>(len), + reinterpret_cast<int8_t*>(dest.data())); + return len; +} + void JavaByteArrayToString(JNIEnv* env, const JavaRef<jbyteArray>& byte_array, std::string* out) { @@ -540,5 +536,4 @@ } } -} // namespace android -} // namespace base +} // namespace base::android
diff --git a/base/android/jni_array.h b/base/android/jni_array.h index d9d6ceb..ee3bbb5 100644 --- a/base/android/jni_array.h +++ b/base/android/jni_array.h
@@ -8,14 +8,28 @@ #include <jni.h> #include <stddef.h> #include <stdint.h> +#include <ostream> #include <string> #include <vector> #include "base/android/scoped_java_ref.h" +#include "base/check_op.h" #include "base/containers/span.h" -namespace base { -namespace android { +namespace base::android { + +// As |GetArrayLength| makes no guarantees about the returned value (e.g., it +// may be -1 if |array| is not a valid Java array), provide a safe wrapper +// that always returns a valid, non-negative size. +// Returns the length of Java array. +template <typename JavaArrayType> +BASE_EXPORT size_t SafeGetArrayLength(JNIEnv* env, + const JavaRef<JavaArrayType>& jarray) { + DCHECK(jarray); + jsize length = env->GetArrayLength(jarray.obj()); + DCHECK_GE(length, 0) << "Invalid array length: " << length; + return static_cast<size_t>(std::max(0, length)); +} // Returns a new Java byte array converted from the given bytes array. BASE_EXPORT ScopedJavaLocalRef<jbyteArray> ToJavaByteArray(JNIEnv* env, @@ -141,6 +155,14 @@ const JavaRef<jbyteArray>& byte_array, std::vector<uint8_t>* out); +// Copy the contents of java |byte_array| into |dest|. The span must be larger +// than or equal to the array. +// Returns the number of bytes copied. +BASE_EXPORT size_t +JavaByteArrayToByteSpan(JNIEnv* env, + const JavaRef<jbyteArray>& byte_array, + base::span<uint8_t> dest); + // Replaces the content of |out| with the Java bytes in |byte_array|. No UTF-8 // conversion is performed. BASE_EXPORT void JavaByteArrayToString(JNIEnv* env, @@ -220,7 +242,6 @@ const JavaRef<jobjectArray>& array, std::vector<std::vector<int>>* out); -} // namespace android -} // namespace base +} // namespace base::android #endif // BASE_ANDROID_JNI_ARRAY_H_
diff --git a/base/android/jni_array_unittest.cc b/base/android/jni_array_unittest.cc index 61ed0ebc..0bf72281 100644 --- a/base/android/jni_array_unittest.cc +++ b/base/android/jni_array_unittest.cc
@@ -13,12 +13,26 @@ #include "base/android/jni_android.h" #include "base/android/jni_string.h" #include "base/android/scoped_java_ref.h" +#include "base/containers/span.h" #include "base/strings/utf_string_conversions.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -namespace base { -namespace android { +namespace base::android { + +TEST(JniArray, GetLength) { + const uint8_t bytes[] = {0, 1, 2, 3}; + const size_t len = std::size(bytes); + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jbyteArray> j_bytes = ToJavaByteArray(env, bytes, len); + ASSERT_TRUE(j_bytes); + ASSERT_EQ(4U, SafeGetArrayLength(env, j_bytes)); + + ScopedJavaLocalRef<jbyteArray> j_empty_bytes = + ToJavaByteArray(env, base::span<uint8_t>()); + ASSERT_TRUE(j_empty_bytes); + ASSERT_EQ(0U, SafeGetArrayLength(env, j_empty_bytes)); +} TEST(JniArray, BasicConversions) { const uint8_t kBytes[] = {0, 1, 2, 3}; @@ -42,6 +56,10 @@ EXPECT_EQ(expected_vec, vectorFromBytes); EXPECT_EQ(expected_vec, vectorFromVector); + std::vector<uint8_t> vector_for_span_test(expected_vec.size()); + JavaByteArrayToByteSpan(env, bytes, base::make_span(vector_for_span_test)); + EXPECT_EQ(expected_vec, vector_for_span_test); + AppendJavaByteArrayToByteVector(env, bytes, &vectorFromBytes); EXPECT_EQ(8U, vectorFromBytes.size()); expected_vec.insert(expected_vec.end(), kBytes, kBytes + kLen); @@ -605,5 +623,4 @@ env, static_cast<jstring>(env->GetObjectArrayElement( j_array.obj(), 2))))); } -} // namespace android -} // namespace base +} // namespace base::android
diff --git a/base/memory/README.md b/base/memory/README.md index 5d92cd1..915f32e 100644 --- a/base/memory/README.md +++ b/base/memory/README.md
@@ -12,16 +12,30 @@ [here](https://docs.google.com/document/d/1VRevv8JhlP4I8fIlvf87IrW2IRjE0PbkSfIcI6-UbJo/edit?usp=sharing). ## `raw_ptr<T>` -Use for class fields/members that would otherwise be a native pointer. +Use for class fields/members that would otherwise be a `T*`. -This is a weakly refcounted wrapper for a native pointer (also called a raw +This is a weakly refcounted wrapper for a `T*` (also called a raw pointer). When the object is deleted, the allocator will "poison" the memory that object occupied and keep the memory around so it’s not reused. This reduces the risk and impact of a use-after-free bug. Depending on the use case, it's possible a smart pointer with additional features would be more appropriate, but if none of those are applicable or -necesssary, `raw_ptr<T>` is much safer than a native pointer. +necessary, `raw_ptr<T>` is preferred over a `T*`. + +For more information, see [`raw_ptr.md`](./raw_ptr.md); for guidance on +usage, see +[the style guide](../../styleguide/c++/c++.md#non_owning-pointers-in-class-fields). + +## `raw_ref<T>` +Use for class fields/members that would otherwise be a `T&`. + +This shares much in common with `raw_ptr<T>`, but asserts that the +`raw_ref<T>` is not nullable. + +For more information, see [`raw_ptr.md`](./raw_ptr.md); for guidance on +usage, see +[the style guide](../../styleguide/c++/c++.md#non_owning-pointers-in-class-fields). ## `base::WeakPtr<T>` Use when a reference to an object might outlive the object itself.
diff --git a/base/message_loop/message_pump_mac.mm b/base/message_loop/message_pump_mac.mm index 1beda5f..25ee6539 100644 --- a/base/message_loop/message_pump_mac.mm +++ b/base/message_loop/message_pump_mac.mm
@@ -43,7 +43,7 @@ // - Cancel an already scheduled timer wake up if there is no delayed work. BASE_FEATURE(kMessagePumpMacDelayedWorkOptimizations, "MessagePumpMacDelayedWorkOptimizations", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); // Caches the state of the "MessagePumpMacDelayedWorkOptimizations" // feature for efficiency.
diff --git a/base/profiler/chrome_unwinder_android.cc b/base/profiler/chrome_unwinder_android.cc deleted file mode 100644 index 3322b92..0000000 --- a/base/profiler/chrome_unwinder_android.cc +++ /dev/null
@@ -1,104 +0,0 @@ -// Copyright 2019 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/profiler/chrome_unwinder_android.h" - -#include "base/numerics/checked_math.h" -#include "base/profiler/module_cache.h" -#include "build/build_config.h" - -namespace base { - -ChromeUnwinderAndroid::ChromeUnwinderAndroid( - const ArmCFITable* cfi_table, - uintptr_t chrome_module_base_address) - : cfi_table_(cfi_table), - chrome_module_base_address_(chrome_module_base_address) { - DCHECK(cfi_table_); -} - -ChromeUnwinderAndroid::~ChromeUnwinderAndroid() = default; - -bool ChromeUnwinderAndroid::CanUnwindFrom(const Frame& current_frame) const { - return current_frame.module && - current_frame.module->GetBaseAddress() == chrome_module_base_address_; -} - -UnwindResult ChromeUnwinderAndroid::TryUnwind(RegisterContext* thread_context, - uintptr_t stack_top, - std::vector<Frame>* stack) { - DCHECK(CanUnwindFrom(stack->back())); - do { - const ModuleCache::Module* module = stack->back().module; - uintptr_t pc = RegisterContextInstructionPointer(thread_context); - DCHECK_GE(pc, module->GetBaseAddress()); - uintptr_t func_addr = pc - module->GetBaseAddress(); - - auto entry = cfi_table_->FindEntryForAddress(func_addr); - if (entry) { - if (!Step(thread_context, stack_top, *entry)) - return UnwindResult::kAborted; - } else if (stack->size() == 1) { - // Try unwinding by sourcing the return address from the lr register. - if (!StepUsingLrRegister(thread_context, stack_top)) - return UnwindResult::kAborted; - } else { - return UnwindResult::kAborted; - } - stack->emplace_back(RegisterContextInstructionPointer(thread_context), - module_cache()->GetModuleForAddress( - RegisterContextInstructionPointer(thread_context))); - } while (CanUnwindFrom(stack->back())); - return UnwindResult::kUnrecognizedFrame; -} - -// static -bool ChromeUnwinderAndroid::Step(RegisterContext* thread_context, - uintptr_t stack_top, - const ArmCFITable::FrameEntry& entry) { - CHECK_NE(RegisterContextStackPointer(thread_context), 0U); - CHECK_LE(RegisterContextStackPointer(thread_context), stack_top); - if (entry.cfa_offset == 0) - return StepUsingLrRegister(thread_context, stack_top); - - // The rules for unwinding using the CFI information are: - // SP_prev = SP_cur + cfa_offset and - // PC_prev = * (SP_prev - ra_offset). - auto new_sp = - CheckedNumeric<uintptr_t>(RegisterContextStackPointer(thread_context)) + - CheckedNumeric<uint16_t>(entry.cfa_offset); - if (!new_sp.AssignIfValid(&RegisterContextStackPointer(thread_context)) || - RegisterContextStackPointer(thread_context) >= stack_top) { - return false; - } - - if (entry.ra_offset > entry.cfa_offset) - return false; - - // Underflow is prevented because |ra_offset| <= |cfa_offset|. - uintptr_t ip_address = (new_sp - CheckedNumeric<uint16_t>(entry.ra_offset)) - .ValueOrDie<uintptr_t>(); - RegisterContextInstructionPointer(thread_context) = - *reinterpret_cast<uintptr_t*>(ip_address); - return true; -} - -// static -bool ChromeUnwinderAndroid::StepUsingLrRegister(RegisterContext* thread_context, - uintptr_t stack_top) { - CHECK_NE(RegisterContextStackPointer(thread_context), 0U); - CHECK_LE(RegisterContextStackPointer(thread_context), stack_top); - - uintptr_t pc = RegisterContextInstructionPointer(thread_context); - uintptr_t return_address = static_cast<uintptr_t>(thread_context->arm_lr); - - // The step failed if the pc doesn't change. - if (pc == return_address) - return false; - - RegisterContextInstructionPointer(thread_context) = return_address; - return true; -} - -} // namespace base
diff --git a/base/profiler/chrome_unwinder_android.h b/base/profiler/chrome_unwinder_android.h deleted file mode 100644 index 46728d3d..0000000 --- a/base/profiler/chrome_unwinder_android.h +++ /dev/null
@@ -1,55 +0,0 @@ -// Copyright 2019 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_PROFILER_CHROME_UNWINDER_ANDROID_H_ -#define BASE_PROFILER_CHROME_UNWINDER_ANDROID_H_ - -#include <vector> - -#include "base/memory/raw_ptr.h" -#include "base/profiler/unwinder.h" - -#include "base/base_export.h" -#include "base/profiler/arm_cfi_table.h" -#include "base/profiler/module_cache.h" -#include "base/profiler/register_context.h" - -namespace base { - -// Chrome unwinder implementation for Android, using ArmCfiTable. -class BASE_EXPORT ChromeUnwinderAndroid : public Unwinder { - public: - ChromeUnwinderAndroid(const ArmCFITable* cfi_table, - uintptr_t chrome_module_base_address); - ~ChromeUnwinderAndroid() override; - ChromeUnwinderAndroid(const ChromeUnwinderAndroid&) = delete; - ChromeUnwinderAndroid& operator=(const ChromeUnwinderAndroid&) = delete; - - // Unwinder: - bool CanUnwindFrom(const Frame& current_frame) const override; - UnwindResult TryUnwind(RegisterContext* thread_context, - uintptr_t stack_top, - std::vector<Frame>* stack) override; - - static bool StepForTesting(RegisterContext* thread_context, - uintptr_t stack_top, - const ArmCFITable::FrameEntry& entry) { - return Step(thread_context, stack_top, entry); - } - - private: - static bool Step(RegisterContext* thread_context, - uintptr_t stack_top, - const ArmCFITable::FrameEntry& entry); - // Fallback setp that attempts to use lr as return address. - static bool StepUsingLrRegister(RegisterContext* thread_context, - uintptr_t stack_top); - - raw_ptr<const ArmCFITable> cfi_table_; - const uintptr_t chrome_module_base_address_; -}; - -} // namespace base - -#endif // BASE_PROFILER_CHROME_UNWINDER_ANDROID_H_
diff --git a/base/profiler/chrome_unwinder_android_unittest.cc b/base/profiler/chrome_unwinder_android_unittest.cc deleted file mode 100644 index 10ae0ea..0000000 --- a/base/profiler/chrome_unwinder_android_unittest.cc +++ /dev/null
@@ -1,309 +0,0 @@ -// Copyright 2019 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/profiler/chrome_unwinder_android.h" - -#include "base/android/library_loader/anchor_functions.h" -#include "base/files/file_util.h" -#include "base/profiler/profile_builder.h" -#include "base/profiler/stack_buffer.h" -#include "base/profiler/stack_copier_signal.h" -#include "base/profiler/stack_sampling_profiler_test_util.h" -#include "base/profiler/thread_delegate_posix.h" -#include "base/test/gtest_util.h" -#include "build/build_config.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace base { - -namespace { - -// Input is generated from the CFI file: -// STACK CFI INIT 100 100 -// STACK CFI 1010 .cfa: sp 8 + .ra: .cfa -4 + ^ -const uint16_t cfi_data[] = { - // UNW_INDEX size - 0x02, - 0x0, - // UNW_INDEX function_addresses (4 byte rows). - 0x100, - 0x0, - 0x200, - 0x0, - // UNW_INDEX entry_data_indices (2 byte rows). - 0x0, - 0xffff, - // UNW_DATA table. - 0x1, - 0x10, - 0x9, -}; - -// Utility function to add a single native module during test setup. Returns -// a pointer to the provided module. -const ModuleCache::Module* AddNativeModule( - ModuleCache* cache, - std::unique_ptr<const ModuleCache::Module> module) { - const ModuleCache::Module* module_ptr = module.get(); - cache->AddCustomNativeModule(std::move(module)); - return module_ptr; -} - -ArmCFITable::FrameEntry MakeFrameEntry(uint16_t cfa_offset, - uint16_t ra_offset) { - return ArmCFITable::FrameEntry{ - static_cast<uint16_t>(cfa_offset * sizeof(uintptr_t)), - static_cast<uint16_t>(ra_offset * sizeof(uintptr_t))}; -} - -} // namespace - -// Tests unwind step under normal operation. -TEST(ChromeUnwinderAndroidTest, Step) { - const std::vector<uintptr_t> stack_buffer = { - 0xFFFF, 0xFFFF, 0xFFFF, 0x1111, 0xFFFF, 0x2222, - }; - const uintptr_t stack_top = - reinterpret_cast<uintptr_t>(stack_buffer.data() + stack_buffer.size()); - RegisterContext context; - RegisterContextInstructionPointer(&context) = 0xBEEF; - RegisterContextStackPointer(&context) = - reinterpret_cast<uintptr_t>(stack_buffer.data()); - - EXPECT_TRUE(ChromeUnwinderAndroid::StepForTesting(&context, stack_top, - MakeFrameEntry(4, 1))); - EXPECT_EQ(RegisterContextInstructionPointer(&context), 0x1111U); - EXPECT_EQ(RegisterContextStackPointer(&context), - reinterpret_cast<uintptr_t>(stack_buffer.data() + 4)); - - EXPECT_TRUE(ChromeUnwinderAndroid::StepForTesting(&context, stack_top, - MakeFrameEntry(1, 0))); - EXPECT_EQ(RegisterContextInstructionPointer(&context), 0x2222U); - EXPECT_EQ(RegisterContextStackPointer(&context), - reinterpret_cast<uintptr_t>(stack_buffer.data() + 5)); -} - -// Tests unwind step using immediate return address. -TEST(ChromeUnwinderAndroidTest, StepImmediate) { - const std::vector<uintptr_t> stack_buffer = {0xFFFF, 0xFFFF}; - const uintptr_t stack_top = - reinterpret_cast<uintptr_t>(stack_buffer.data() + stack_buffer.size()); - RegisterContext context; - RegisterContextInstructionPointer(&context) = 0xBEEF; - RegisterContextStackPointer(&context) = - reinterpret_cast<uintptr_t>(stack_buffer.data()); - context.arm_lr = 0x4444; - - EXPECT_TRUE(ChromeUnwinderAndroid::StepForTesting(&context, stack_top, - MakeFrameEntry(0, 0))); - EXPECT_EQ(RegisterContextInstructionPointer(&context), 0x4444U); - EXPECT_EQ(RegisterContextStackPointer(&context), - reinterpret_cast<uintptr_t>(stack_buffer.data())); -} - -// Tests that unwinding fails if immediate return address is the current -// instruction. -TEST(ChromeUnwinderAndroidTest, StepImmediateFail) { - const std::vector<uintptr_t> stack_buffer = {0xFFFF, 0xFFFF}; - const uintptr_t stack_top = - reinterpret_cast<uintptr_t>(stack_buffer.data() + stack_buffer.size()); - - RegisterContext context; - RegisterContextInstructionPointer(&context) = 0x1111; - RegisterContextStackPointer(&context) = - reinterpret_cast<uintptr_t>(stack_buffer.data()); - context.arm_lr = 0x1111; - - EXPECT_FALSE(ChromeUnwinderAndroid::StepForTesting(&context, stack_top, - MakeFrameEntry(0, 0))); -} - -// Tests that unwinding fails if stack is invalid. -TEST(ChromeUnwinderAndroidTest, StepInvalidStack) { - const std::vector<uintptr_t> stack_buffer = {0xFFFF}; - - const uintptr_t stack_top = - reinterpret_cast<uintptr_t>(stack_buffer.data() + stack_buffer.size()); - - RegisterContext context; - EXPECT_CHECK_DEATH({ - RegisterContextStackPointer(&context) = 0; - - ChromeUnwinderAndroid::StepForTesting(&context, stack_top, - MakeFrameEntry(1, 0)); - }); - - EXPECT_CHECK_DEATH({ - RegisterContextStackPointer(&context) = reinterpret_cast<uintptr_t>( - stack_buffer.data() + stack_buffer.size() + 1); - - ChromeUnwinderAndroid::StepForTesting(&context, stack_top, - MakeFrameEntry(1, 0)); - }); -} - -// Tests that unwinding fails if the frame entry is out of bounds. -TEST(ChromeUnwinderAndroidTest, StepOutOfBounds) { - RegisterContext context; - RegisterContextInstructionPointer(&context) = 0xBEEF; - constexpr uintptr_t kOverflowOffset = 8; - constexpr size_t kStackSize = 4; - // It's fine to use a fake stack pointer since the stack won't be - // dereferenced. Purposely underflow so that sp + |kOverflowOffset| overflows. - RegisterContextStackPointer(&context) = 0 - kOverflowOffset; - const uintptr_t stack_top = - RegisterContextStackPointer(&context) + kStackSize; - - // ra_offset exceeds cfa_offset. - EXPECT_FALSE(ChromeUnwinderAndroid::StepForTesting(&context, stack_top, - MakeFrameEntry(1, 2))); - EXPECT_FALSE(ChromeUnwinderAndroid::StepForTesting( - &context, stack_top, MakeFrameEntry(1, kOverflowOffset))); - - // cfa_offset exceeds |stack_top|. - EXPECT_FALSE(ChromeUnwinderAndroid::StepForTesting( - &context, stack_top, MakeFrameEntry(kStackSize, 0))); - - // sp + cfa_offset overflows. - EXPECT_FALSE(ChromeUnwinderAndroid::StepForTesting( - &context, stack_top, MakeFrameEntry(kOverflowOffset, 0))); -} - -TEST(ChromeUnwinderAndroidTest, StepUnderflows) { - RegisterContext context; - RegisterContextInstructionPointer(&context) = 0xBEEF; - // It's fine to use a fake stack pointer since the stack won't be - // dereferenced. - RegisterContextStackPointer(&context) = 2; - const uintptr_t stack_top = RegisterContextStackPointer(&context) + 4; - - // sp + cfa_offset - ra_offset underflows. - EXPECT_FALSE(ChromeUnwinderAndroid::StepForTesting(&context, stack_top, - MakeFrameEntry(1, 4))); -} - -TEST(ChromeUnwinderAndroidTest, CanUnwindFrom) { - auto cfi_table = ArmCFITable::Parse( - {reinterpret_cast<const uint8_t*>(cfi_data), sizeof(cfi_data)}); - - auto chrome_module = std::make_unique<TestModule>(0x1000, 0x500); - auto non_chrome_module = std::make_unique<TestModule>(0x2000, 0x500); - - ModuleCache module_cache; - ChromeUnwinderAndroid unwinder(cfi_table.get(), - chrome_module->GetBaseAddress()); - unwinder.Initialize(&module_cache); - - EXPECT_TRUE(unwinder.CanUnwindFrom({0x1100, chrome_module.get()})); - EXPECT_FALSE(unwinder.CanUnwindFrom({0x2100, non_chrome_module.get()})); -} - -TEST(ChromeUnwinderAndroidTest, TryUnwind) { - auto cfi_table = ArmCFITable::Parse( - {reinterpret_cast<const uint8_t*>(cfi_data), sizeof(cfi_data)}); - - ModuleCache module_cache; - const ModuleCache::Module* chrome_module = AddNativeModule( - &module_cache, std::make_unique<TestModule>(0x1000, 0x500)); - - ChromeUnwinderAndroid unwinder(cfi_table.get(), - chrome_module->GetBaseAddress()); - unwinder.Initialize(&module_cache); - - std::vector<uintptr_t> stack_buffer = { - 0xFFFF, - // .cfa: sp 8 + .ra: .cfa -4 + ^ - 0x2000, - 0xFFFF, - }; - uintptr_t stack_top = - reinterpret_cast<uintptr_t>(stack_buffer.data() + stack_buffer.size()); - - std::vector<Frame> stack; - stack.emplace_back(0x1100, chrome_module); - - RegisterContext context; - RegisterContextInstructionPointer(&context) = 0x1100; - RegisterContextStackPointer(&context) = - reinterpret_cast<uintptr_t>(stack_buffer.data()); - context.arm_lr = 0x11AA; - - EXPECT_EQ(UnwindResult::kUnrecognizedFrame, - unwinder.TryUnwind(&context, stack_top, &stack)); - EXPECT_EQ(std::vector<Frame>({{0x1100, chrome_module}, - {0x11AA, chrome_module}, - {0x2000, nullptr}}), - stack); -} - -TEST(ChromeUnwinderAndroidTest, TryUnwindAbort) { - auto cfi_table = ArmCFITable::Parse( - {reinterpret_cast<const uint8_t*>(cfi_data), sizeof(cfi_data)}); - ASSERT_TRUE(cfi_table); - - ModuleCache module_cache; - const ModuleCache::Module* chrome_module = AddNativeModule( - &module_cache, std::make_unique<TestModule>(0x1000, 0x500)); - - ChromeUnwinderAndroid unwinder(cfi_table.get(), - chrome_module->GetBaseAddress()); - unwinder.Initialize(&module_cache); - - std::vector<uintptr_t> stack_buffer = { - 0xFFFF, - }; - uintptr_t stack_top = - reinterpret_cast<uintptr_t>(stack_buffer.data() + stack_buffer.size()); - - std::vector<Frame> stack; - stack.emplace_back(0x1100, chrome_module); - - RegisterContext context; - RegisterContextInstructionPointer(&context) = 0x1100; - RegisterContextStackPointer(&context) = - reinterpret_cast<uintptr_t>(stack_buffer.data()); - context.arm_lr = 0x1100; - - // Aborted because ra == pc. - EXPECT_EQ(UnwindResult::kAborted, - unwinder.TryUnwind(&context, stack_top, &stack)); - EXPECT_EQ(std::vector<Frame>({{0x1100, chrome_module}}), stack); -} - -TEST(ChromeUnwinderAndroidTest, TryUnwindNoData) { - auto cfi_table = ArmCFITable::Parse( - {reinterpret_cast<const uint8_t*>(cfi_data), sizeof(cfi_data)}); - - ModuleCache module_cache; - const ModuleCache::Module* chrome_module = AddNativeModule( - &module_cache, std::make_unique<TestModule>(0x1000, 0x500)); - - ChromeUnwinderAndroid unwinder(cfi_table.get(), - chrome_module->GetBaseAddress()); - unwinder.Initialize(&module_cache); - - std::vector<uintptr_t> stack_buffer = {0xFFFF}; - - uintptr_t stack_top = - reinterpret_cast<uintptr_t>(stack_buffer.data() + stack_buffer.size()); - - std::vector<Frame> stack; - stack.emplace_back(0x1200, chrome_module); - - RegisterContext context; - RegisterContextInstructionPointer(&context) = 0xBEEF; - RegisterContextStackPointer(&context) = - reinterpret_cast<uintptr_t>(stack_buffer.data()); - context.arm_lr = 0x12AA; - - // Unwinding will first use arm_lr as fallback because there's no unwind info - // for the instruction pointer, and then abort. - EXPECT_EQ(UnwindResult::kAborted, - unwinder.TryUnwind(&context, stack_top, &stack)); - EXPECT_EQ( - std::vector<Frame>({{0x1200, chrome_module}, {0x12AA, chrome_module}}), - stack); -} - -} // namespace base
diff --git a/base/profiler/stack_sampling_profiler_test_util.cc b/base/profiler/stack_sampling_profiler_test_util.cc index 2c70d585..d703d97c 100644 --- a/base/profiler/stack_sampling_profiler_test_util.cc +++ b/base/profiler/stack_sampling_profiler_test_util.cc
@@ -22,16 +22,10 @@ #if BUILDFLAG(IS_ANDROID) && BUILDFLAG(ENABLE_ARM_CFI_TABLE) #include "base/android/apk_assets.h" -#include "base/files/memory_mapped_file.h" -#include "base/profiler/native_unwinder_android.h" - -#if BUILDFLAG(USE_ANDROID_UNWINDER_V2) #include "base/android/library_loader/anchor_functions.h" +#include "base/files/memory_mapped_file.h" #include "base/profiler/chrome_unwinder_android_v2.h" -#else -#include "base/profiler/chrome_unwinder_android.h" -#endif - +#include "base/profiler/native_unwinder_android.h" #endif #if BUILDFLAG(IS_WIN) @@ -127,7 +121,6 @@ std::move(maps), std::move(memory), exclude_module_with_base_address); } -#if BUILDFLAG(USE_ANDROID_UNWINDER_V2) std::unique_ptr<Unwinder> CreateChromeUnwinderAndroidForTesting( uintptr_t chrome_module_base_address) { static constexpr char kCfiFileName[] = "assets/unwind_cfi_32_v2"; @@ -163,41 +156,6 @@ chrome_module_base_address, /* text_section_start_address= */ base::android::kStartOfText); } -#else -std::unique_ptr<Unwinder> CreateChromeUnwinderAndroidForTesting( - uintptr_t chrome_module_base_address) { - static constexpr char kCfiFileName[] = "assets/unwind_cfi_32"; - - // The wrapper class ensures that `MemoryMappedFile` has the same lifetime - // as the unwinder. - class ChromeUnwinderAndroidForTesting : public ChromeUnwinderAndroid { - public: - ChromeUnwinderAndroidForTesting(std::unique_ptr<MemoryMappedFile> cfi_file, - std::unique_ptr<ArmCFITable> cfi_table, - uintptr_t chrome_module_base_address) - : ChromeUnwinderAndroid(cfi_table.get(), chrome_module_base_address), - cfi_file_(std::move(cfi_file)), - cfi_table_(std::move(cfi_table)) {} - ~ChromeUnwinderAndroidForTesting() override = default; - - private: - std::unique_ptr<MemoryMappedFile> cfi_file_; - std::unique_ptr<ArmCFITable> cfi_table_; - }; - - MemoryMappedFile::Region cfi_region; - int fd = base::android::OpenApkAsset(kCfiFileName, &cfi_region); - DCHECK_GT(fd, 0); - auto cfi_file = std::make_unique<MemoryMappedFile>(); - bool ok = cfi_file->Initialize(base::File(fd), cfi_region); - DCHECK(ok); - std::unique_ptr<ArmCFITable> cfi_table = - ArmCFITable::Parse({cfi_file->data(), cfi_file->length()}); - DCHECK(cfi_table); - return std::make_unique<ChromeUnwinderAndroidForTesting>( - std::move(cfi_file), std::move(cfi_table), chrome_module_base_address); -} -#endif // #if BUILDFLAG(USE_ANDROID_UNWINDER_V2) #endif // #if BUILDFLAG(IS_ANDROID) && BUILDFLAG(ENABLE_ARM_CFI_TABLE) } // namespace
diff --git a/base/task/thread_pool/delayed_task_manager.h b/base/task/thread_pool/delayed_task_manager.h index 4196143..59fbef0 100644 --- a/base/task/thread_pool/delayed_task_manager.h +++ b/base/task/thread_pool/delayed_task_manager.h
@@ -121,7 +121,7 @@ // it is never modified. It is therefore safe to access // |service_thread_task_runner_| without synchronization once it is observed // that it is non-null. - mutable CheckedLock queue_lock_; + mutable CheckedLock queue_lock_{UniversalSuccessor()}; scoped_refptr<SequencedTaskRunner> service_thread_task_runner_;
diff --git a/base/threading/thread_restrictions.h b/base/threading/thread_restrictions.h index 24498ec6..e1b4f49 100644 --- a/base/threading/thread_restrictions.h +++ b/base/threading/thread_restrictions.h
@@ -132,6 +132,7 @@ namespace android_webview { class AwFormDatabaseService; class CookieManager; +class JsSandboxIsolate; class ScopedAllowInitGLBindings; class VizCompositorThreadRunnerWebView; } // namespace android_webview @@ -683,6 +684,7 @@ // Allowed usage: friend class ::ChromeNSSCryptoModuleDelegate; + friend class android_webview::JsSandboxIsolate; friend class base::internal::GetAppOutputScopedAllowBaseSyncPrimitives; friend class base::SimpleThread; friend class blink::CategorizedWorkerPoolImpl;
diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn index 958f33a..efba847 100644 --- a/build/config/BUILDCONFIG.gn +++ b/build/config/BUILDCONFIG.gn
@@ -615,8 +615,13 @@ # # As remote execution requires inputs to be made more explicit than is normally # expected with gn, you may find that setting allow_remote to true will result -# in many missing file errors. This should be resolved by explicitly declaring -# these inputs/sources. +# in many missing file errors. In most cases, this should be resolved by +# explicitly declaring these inputs/sources. +# +# However, it may be impractical to determine these inputs in gn. For such +# cases, the invoker can specify a custom input processor, which are currently +# defined and implemented in //build/util/action_remote.py. The appropriate +# value should be set using the custom_processor arg. # Variables needed by rbe.gni aren't available at the top of this file. import("//build/toolchain/rbe.gni")
diff --git a/build/config/compiler/compiler.gni b/build/config/compiler/compiler.gni index fa665e3f..e0d44ee 100644 --- a/build/config/compiler/compiler.gni +++ b/build/config/compiler/compiler.gni
@@ -151,8 +151,8 @@ # Use offsets rather than pointers in vtables in order to reduce the number of # relocations. This is safe to enable only when all C++ code is built with the # flag set to the same value. - use_relative_vtables_abi = - is_android && use_custom_libcxx && !is_component_build + use_relative_vtables_abi = is_android && current_cpu == "arm64" && + use_custom_libcxx && !is_component_build } assert(!is_cfi || use_thin_lto, "CFI requires ThinLTO")
diff --git a/build/fuchsia/linux_internal.sdk.sha1 b/build/fuchsia/linux_internal.sdk.sha1 index fc3b270..ef17b542 100644 --- a/build/fuchsia/linux_internal.sdk.sha1 +++ b/build/fuchsia/linux_internal.sdk.sha1
@@ -1 +1 @@ -10.20221123.1.1 +10.20221123.2.1
diff --git a/build/util/action_remote.py b/build/util/action_remote.py index 021c871..1e9517d 100755 --- a/build/util/action_remote.py +++ b/build/util/action_remote.py
@@ -2,16 +2,129 @@ # Copyright 2022 The Chromium Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Wrapper script to run action remotely through rewrapper with gn.""" +"""Wrapper script to run action remotely through rewrapper with gn. +Also includes Chromium-specific input processors which don't make sense to +be reclient inbuilt input processors.""" + +import argparse +import json +import os import subprocess import sys +from enum import Enum + + +class CustomProcessor(Enum): + mojom_parser = 'mojom_parser' + + def __str__(self): + return self.value + + +def _process_build_metadata_json(bm_file, exec_root, working_dir, output_root, + re_outputs, processed_inputs): + """Recursively find mojom_parser inputs from a build_metadata file.""" + if bm_file in processed_inputs: + return + + processed_inputs.add(bm_file) + + bm_dir = os.path.dirname(bm_file) + wd_rel = os.path.relpath(working_dir, exec_root) + + with open(bm_file) as f: + bm = json.load(f) + + # All sources and corresponding module files are inputs. + for s in bm["sources"]: + src = os.path.normpath(os.path.join(bm_dir, s)) + if src not in processed_inputs and os.path.exists(src): + processed_inputs.add(src) + src_module = os.path.normpath( + os.path.join(output_root, os.path.join(wd_rel, src + "-module"))) + if src_module in re_outputs: + continue + if src_module not in processed_inputs and os.path.exists(src_module): + processed_inputs.add(src_module) + + # Recurse into build_metadata deps. + for d in bm["deps"]: + dep = os.path.normpath(os.path.join(bm_dir, d)) + _process_build_metadata_json(dep, exec_root, working_dir, output_root, + re_outputs, processed_inputs) + + +def _get_mojom_parser_inputs(exec_root, output_files, extra_args): + """Get mojom inputs by walking generated build_metadata files. + + This is less complexity and disk I/O compared to parsing mojom files for + imports and finding all imports. + + Start from the root build_metadata file passed to mojom_parser's + --check-imports flag. + """ + argparser = argparse.ArgumentParser() + argparser.add_argument('--check-imports', dest='check_imports', required=True) + argparser.add_argument('--output-root', dest='output_root', required=True) + mojom_parser_args, _ = argparser.parse_known_args(args=extra_args) + + processed_inputs = set() + _process_build_metadata_json(mojom_parser_args.check_imports, exec_root, + os.getcwd(), mojom_parser_args.output_root, + output_files, processed_inputs) + + # Rebase paths onto rewrapper exec root. + return map(lambda dep: os.path.normpath(os.path.relpath(dep, exec_root)), + processed_inputs) def main(): - # Pass through all args. Use check=True to ensure failure is raised. - args = sys.argv[1:] - proc = subprocess.run(args, check=True) + # Set up argparser with some rewrapper flags. + argparser = argparse.ArgumentParser(description='rewrapper executor for gn', + allow_abbrev=False) + argparser.add_argument('--custom_processor', + type=CustomProcessor, + choices=list(CustomProcessor)) + argparser.add_argument('rewrapper_path') + argparser.add_argument('--input_list_paths') + argparser.add_argument('--output_list_paths') + argparser.add_argument('--exec_root') + parsed_args, extra_args = argparser.parse_known_args() + + # This script expects to be calling rewrapper. + args = [parsed_args.rewrapper_path] + + # Get the output files list. + output_files = set() + with open(parsed_args.output_list_paths, 'r') as file: + for line in file: + output_files.add(line.rstrip('\n')) + + # Scan for and add explicit inputs for rewrapper if necessary. + # These should be in a new input list paths file, as using --inputs can fail + # if the list is extremely large. + if parsed_args.custom_processor == CustomProcessor.mojom_parser: + root, ext = os.path.splitext(parsed_args.input_list_paths) + extra_inputs = _get_mojom_parser_inputs(parsed_args.exec_root, output_files, + extra_args) + extra_input_list_path = '%s__extra%s' % (root, ext) + with open(extra_input_list_path, 'w') as file: + with open(parsed_args.input_list_paths, 'r') as inputs: + file.write(inputs.read()) + file.write("\n".join(extra_inputs)) + args += ["--input_list_paths=%s" % extra_input_list_path] + else: + args += ["--input_list_paths=%s" % parsed_args.input_list_paths] + + # Filter out --custom_processor= which is a flag for this script, + # and filter out --input_list_paths= because we replace it above. + # Pass on the rest of the args to rewrapper. + args_rest = filter(lambda arg: '--custom_processor=' not in arg, sys.argv[2:]) + args += filter(lambda arg: '--input_list_paths=' not in arg, args_rest) + + # Run rewrapper. + proc = subprocess.run(args) return proc.returncode
diff --git a/chrome/VERSION b/chrome/VERSION index 2c61ee02..35dc66a 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=110 MINOR=0 -BUILD=5437 +BUILD=5439 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 66f3610..d84f0d55 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -1089,6 +1089,7 @@ "//chrome/browser/tabmodel/internal:java", "//chrome/browser/tabpersistence:junit", "//chrome/browser/thumbnail:java", + "//chrome/browser/touch_to_fill/payments/android/internal:junit", "//chrome/browser/ui/android/appmenu:java", "//chrome/browser/ui/android/appmenu/internal:junit", "//chrome/browser/ui/android/autofill/internal:junit", @@ -3242,6 +3243,7 @@ "//chrome/browser/password_check/android:test_java", "//chrome/browser/subresource_filter:subresource_filter_javatests", "//chrome/browser/touch_to_fill/android:test_java", + "//chrome/browser/touch_to_fill/payments/android/internal:javatests", "//chrome/browser/ui/android/fast_checkout/internal:javatests", "//chrome/browser/ui/android/omnibox:javatests", "//chrome/browser/ui/android/webid/internal:javatests",
diff --git a/chrome/android/java/res/values/styles.xml b/chrome/android/java/res/values/styles.xml index 9101e45..3eac01b9 100644 --- a/chrome/android/java/res/values/styles.xml +++ b/chrome/android/java/res/values/styles.xml
@@ -439,10 +439,6 @@ <!-- TODO(https://crbug.com/1216642): Move color attributes here. --> </style> - <style name="ThemeOverlay.DisableOverscroll" parent=""> - <item name="android:overScrollMode">never</item> - </style> - <!-- Dialog for notification blocked message. --> <style name="NotificationBlockedDialogContent" parent="AlertDialogContent"> <item name="android:paddingBottom">12dp</item>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeBaseAppCompatActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeBaseAppCompatActivity.java index beeefaef..76becf7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeBaseAppCompatActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeBaseAppCompatActivity.java
@@ -31,7 +31,6 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.base.ServiceTracingProxyProvider; import org.chromium.chrome.browser.base.SplitChromeApplication; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.language.GlobalAppLocaleController; import org.chromium.chrome.browser.metrics.UmaSessionStats; import org.chromium.chrome.browser.night_mode.GlobalNightModeStateProviderHolder; @@ -243,17 +242,6 @@ UmaSessionStats.registerSyntheticFieldTrial( "IsDynamicColorAvailable", isDynamicColorAvailable ? "Enabled" : "Disabled"); }); - - // Try to enable browser overscroll when content overscroll is enabled for consistency. This - // needs to be in a cached feature because activity startup happens before native is - // initialized. Unfortunately content overscroll is read in renderer threads, and these two - // are not synchronized. Typically the first time overscroll is enabled, the following will - // use the old value and then content will pick up the enabled value, causing one execution - // of inconsistency. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S - && !ChromeFeatureList.sElasticOverscroll.isEnabled()) { - setTheme(R.style.ThemeOverlay_DisableOverscroll); - } } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java b/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java index c7580d9..56f1431 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java
@@ -101,7 +101,6 @@ add(ChromeFeatureList.sDiscardOccludedBitmaps); add(ChromeFeatureList.sDownloadsAutoResumptionNative); add(ChromeFeatureList.sEarlyLibraryLoad); - add(ChromeFeatureList.sElasticOverscroll); add(ChromeFeatureList.sFeedLoadingPlaceholder); add(ChromeFeatureList.sFoldableJankFix); add(ChromeFeatureList.sGridTabSwitcherForTablets);
diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc index e602cbe4..49d999f1 100644 --- a/chrome/app/chrome_main_delegate.cc +++ b/chrome/app/chrome_main_delegate.cc
@@ -758,6 +758,27 @@ chromeos::LacrosInitializeDBus(); #endif +#if BUILDFLAG(IS_CHROMEOS_LACROS) + // Set Lacros's default paths. + // + // NOTE: When launching Lacros at login screen, this is the first access + // to post-login parameters. In other words, this is as far as Lacros + // initialization will go at login screen. The browser process will block + // here. + // + // IMPORTANT NOTE: If your code requires access to post-login parameters + // (which are only known after login), please place them *after* this call. + chrome::SetLacrosDefaultPathsFromInitParams( + chromeos::BrowserParamsProxy::Get()->DefaultPaths().get()); + + // NOTE: When launching Lacros at login screen, after this point, + // the user should have logged in. The cryptohome is now accessible. + + // Redirect logs from system directory to cryptohome. + if (chromeos::IsLaunchedWithPostLoginParams()) + RedirectLacrosLogging(); +#endif // BUILDFLAG(IS_CHROMEOS_LACROS) + // The DBus initialization above is needed for FeatureList creation here; // features are needed for Mojo initialization; and Mojo initialization is // needed for LacrosService initialization below. @@ -769,21 +790,6 @@ content::InitializeMojoCore(); #if BUILDFLAG(IS_CHROMEOS_LACROS) - // Set Lacros's default paths. - // NOTE: When launching Lacros at login screen, this is the first access - // to post-login parameters. In other words, this is as far as Lacros - // initialization will go at login screen. - // The browser process will block here. - chrome::SetLacrosDefaultPathsFromInitParams( - chromeos::BrowserParamsProxy::Get()->DefaultPaths().get()); - - // NOTE: When launching Lacros at login screen, after this point, - // the user should have logged in. The cryptohome is now accessible. - - // Redirect logs from system directory to cryptohome. - if (chromeos::IsLaunchedWithPostLoginParams()) - RedirectLacrosLogging(); - // LacrosService instance needs the sequence of the main thread, // and needs to be created earlier than incoming Mojo invitation handling. // This also needs ThreadPool sequences to post some tasks internally.
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index b311fc3..cc4f9a50 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -2044,11 +2044,16 @@ </message> <message name="IDS_SETTINGS_SAFETY_CHECK_REVIEW_NOTIFICATION_PERMISSIONS_PRIMARY_LABEL" desc="'Review Notification Permissions' shows the websites that send a lot of notifications. This label is the header of the module in the site settings notification page. The number represents the number of notification permissions to be reviewed."> {NUM_SITES, plural, - =1 {Review 1 site that recently sent a lot of notifications} - other {Review {NUM_SITES} sites that recently sent a lot of notifications}} + =1 {Review 1 site that sent a lot of notifications} + other {Review {NUM_SITES} sites that sent a lot of notifications}} + </message> + <message name="IDS_SETTINGS_SAFETY_CHECK_NOTIFICATION_PERMISSIONS_REVIEW_BUTTON_ARIA_LABEL" desc="'Review Notification Permissions' shows the websites that send a lot of notifications. This label is used for the ARIA label of the button of the module in the site settings notification page."> + Review notification permissions </message> <message name="IDS_SETTINGS_SAFETY_CHECK_REVIEW_NOTIFICATION_PERMISSIONS_SECONDARY_LABEL" desc="'Review Notification Permissions' shows the websites that send a lot of notifications. This label is the description of the module in site settings notification page."> - These sites sent a lot of notifications recently. You can stop them from sending future notifications. + {NUM_SITES, plural, + =1 {This site sent a lot of notifications recently. You can stop it from sending future notifications.} + other {These sites sent a lot of notifications recently. You can stop them from sending future notifications.}} </message> <message name="IDS_SETTINGS_SAFETY_CHECK_NOTIFICATION_PERMISSION_REVIEW_IGNORED_TOAST_LABEL" desc="'Review Notification Permissions' shows the websites that send a lot of notifications. This label is to indicate for which site the user has explicitly allowed permissions."> Notifications allowed for <ph name="SITE">$1<ex>www.example.com</ex></ph> @@ -2236,7 +2241,7 @@ <message name="IDS_SETTINGS_PERMISSIONS" desc="Name of the settings page which allows users to manage permissions and site content settings"> Permissions and content settings </message> - <message name="IDS_SETTINGS_PERMISSIONS_DESCRIPTION" desc="Description of the controls available on the permisisons and site content settings page"> + <message name="IDS_SETTINGS_PERMISSIONS_DESCRIPTION" desc="Description of the controls available on the permissions and site content settings page"> Controls what information sites can use and show (location, camera, pop-ups, and more) </message> <message name="IDS_SETTINGS_SECURITY" desc="Name of the settings page which allows
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SAFETY_CHECK_NOTIFICATION_PERMISSIONS_REVIEW_BUTTON_ARIA_LABEL.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SAFETY_CHECK_NOTIFICATION_PERMISSIONS_REVIEW_BUTTON_ARIA_LABEL.png.sha1 new file mode 100644 index 0000000..c482a97 --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SAFETY_CHECK_NOTIFICATION_PERMISSIONS_REVIEW_BUTTON_ARIA_LABEL.png.sha1
@@ -0,0 +1 @@ +bf146724fac63bd8d116d4095bcab10b5d66e998 \ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SAFETY_CHECK_REVIEW_NOTIFICATION_PERMISSIONS_PRIMARY_LABEL.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SAFETY_CHECK_REVIEW_NOTIFICATION_PERMISSIONS_PRIMARY_LABEL.png.sha1 index 8e2742d..07877ba9 100644 --- a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SAFETY_CHECK_REVIEW_NOTIFICATION_PERMISSIONS_PRIMARY_LABEL.png.sha1 +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SAFETY_CHECK_REVIEW_NOTIFICATION_PERMISSIONS_PRIMARY_LABEL.png.sha1
@@ -1 +1 @@ -2046a724d4a713393a02bf4fd77dc28d90fec4ae \ No newline at end of file +8b5b7c8d959bea2a8bf7d31243aba0d0466da239 \ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SAFETY_CHECK_REVIEW_NOTIFICATION_PERMISSIONS_SECONDARY_LABEL.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SAFETY_CHECK_REVIEW_NOTIFICATION_PERMISSIONS_SECONDARY_LABEL.png.sha1 index cc8a5ce..0a1f8f8 100644 --- a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SAFETY_CHECK_REVIEW_NOTIFICATION_PERMISSIONS_SECONDARY_LABEL.png.sha1 +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SAFETY_CHECK_REVIEW_NOTIFICATION_PERMISSIONS_SECONDARY_LABEL.png.sha1
@@ -1 +1 @@ -0bcca247ab3656ade7ed536b7a41c7fa2a986be3 \ No newline at end of file +31d9b8d63ca573006b132cf2992dc31ba0ddc376 \ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 9331b71..b6fd4f39 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -95,6 +95,7 @@ buildflag_header("buildflags") { header = "buildflags.h" flags = [ + "ENABLE_UPDATER=$enable_updater", "ENABLE_UPDATE_NOTIFICATIONS=$enable_update_notifications", "USE_MINIKIN_HYPHENATION=$use_minikin_hyphenation", "USE_THIN_LTO=$use_thin_lto", @@ -6975,6 +6976,13 @@ } } + if (enable_bound_session_credentials) { + sources += [ + "signin/bound_session_credentials/bound_session_cookie_fetcher.cc", + "signin/bound_session_credentials/bound_session_cookie_fetcher.h", + ] + } + if (enable_media_remoting) { sources += [ "media/cast_remoting_connector.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 3def3cc..f7008576 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -2727,22 +2727,6 @@ nullptr}}; #if BUILDFLAG(IS_ANDROID) -// The variations of --touch-to-fill-password-submission. -const FeatureEntry::FeatureParam - kTouchToFillPasswordSubmissionWithConservativeHeuristics[] = { - {password_manager::features:: - kTouchToFillPasswordSubmissionWithConservativeHeuristics, - "true"}}; - -const FeatureEntry::FeatureVariation - kTouchToFillPasswordSubmissionVariations[] = { - {"Use conservative heuristics", - kTouchToFillPasswordSubmissionWithConservativeHeuristics, - std::size(kTouchToFillPasswordSubmissionWithConservativeHeuristics), - nullptr}}; -#endif // BUILDFLAG(IS_ANDROID) - -#if BUILDFLAG(IS_ANDROID) // The variations of --metrics-settings-android. const FeatureEntry::FeatureParam kMetricsSettingsAndroidAlternativeOne[] = { {"fre", "1"}}; @@ -8201,13 +8185,6 @@ flag_descriptions::kBiometricReauthForPasswordFillingDescription, kOsAndroid, FEATURE_VALUE_TYPE(password_manager::features::kBiometricTouchToFill)}, - {"touch-to-fill-password-submission", - flag_descriptions::kTouchToFillPasswordSubmissionName, - flag_descriptions::kTouchToFillPasswordSubmissionDescription, kOsAndroid, - FEATURE_WITH_PARAMS_VALUE_TYPE( - password_manager::features::kTouchToFillPasswordSubmission, - kTouchToFillPasswordSubmissionVariations, - "TouchToFillPasswordSubmission")}, {"fast-checkout", flag_descriptions::kFastCheckoutName, flag_descriptions::kFastCheckoutDescription, kOsAndroid, FEATURE_VALUE_TYPE(features::kFastCheckout)},
diff --git a/chrome/browser/apps/app_service/app_icon/app_icon_factory.cc b/chrome/browser/apps/app_service/app_icon/app_icon_factory.cc index 47e07a3..afe5ff10 100644 --- a/chrome/browser/apps/app_service/app_icon/app_icon_factory.cc +++ b/chrome/browser/apps/app_service/app_icon/app_icon_factory.cc
@@ -489,6 +489,30 @@ web_app_provider->icon_manager(), Profile::FromBrowserContext(context)); } +#if BUILDFLAG(IS_CHROMEOS_ASH) +void GetWebAppCompressedIconData(content::BrowserContext* context, + const std::string& web_app_id, + IconEffects icon_effects, + IconType icon_type, + int size_in_dip, + ui::ResourceScaleFactor scale_factor, + LoadIconCallback callback) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + DCHECK(context); + web_app::WebAppProvider* web_app_provider = + web_app::WebAppProvider::GetForLocalAppsUnchecked( + Profile::FromBrowserContext(context)); + + DCHECK(web_app_provider); + scoped_refptr<AppIconLoader> icon_loader = + base::MakeRefCounted<AppIconLoader>( + icon_type, size_in_dip, /*is_placeholder_icon=*/false, icon_effects, + kInvalidIconResource, std::move(callback)); + icon_loader->GetWebAppCompressedIconData(web_app_id, scale_factor, + web_app_provider->icon_manager()); +} +#endif // BUILDFLAG(IS_CHROMEOS_ASH) + void LoadIconFromFileWithFallback( IconType icon_type, int size_hint_in_dip,
diff --git a/chrome/browser/apps/app_service/app_icon/app_icon_factory.h b/chrome/browser/apps/app_service/app_icon/app_icon_factory.h index 76a48e2..495f690 100644 --- a/chrome/browser/apps/app_service/app_icon/app_icon_factory.h +++ b/chrome/browser/apps/app_service/app_icon/app_icon_factory.h
@@ -20,6 +20,7 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) #include "ash/components/arc/mojom/app.mojom.h" #include "ash/components/arc/mojom/intent_helper.mojom.h" +#include "ui/base/resource/resource_scale_factor.h" #endif // BUILDFLAG(IS_CHROMEOS_ASH) namespace content { @@ -105,6 +106,17 @@ IconEffects icon_effects, LoadIconCallback callback); +#if BUILDFLAG(IS_CHROMEOS_ASH) +// Requests a compressed icon data for an web app identified by `app_id`. +void GetWebAppCompressedIconData(content::BrowserContext* context, + const std::string& web_app_id, + IconEffects icon_effects, + IconType icon_type, + int size_in_dip, + ui::ResourceScaleFactor scale_factor, + LoadIconCallback callback); +#endif // BUILDFLAG(IS_CHROMEOS_ASH) + // Loads an icon from a FilePath. If that fails, it calls the fallback. // // The file named by |path| might be empty, not found or otherwise unreadable.
diff --git a/chrome/browser/apps/app_service/app_icon/app_icon_loader.cc b/chrome/browser/apps/app_service/app_icon/app_icon_loader.cc index f7db986..9a53363 100644 --- a/chrome/browser/apps/app_service/app_icon/app_icon_loader.cc +++ b/chrome/browser/apps/app_service/app_icon/app_icon_loader.cc
@@ -649,6 +649,69 @@ } } +void AppIconLoader::GetWebAppCompressedIconData( + const std::string& web_app_id, + ui::ResourceScaleFactor scale_factor, + web_app::WebAppIconManager& icon_manager) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + absl::optional<IconPurpose> icon_purpose_to_read = + GetIconPurpose(web_app_id, icon_manager, size_hint_in_dip_); + + if (!icon_purpose_to_read.has_value()) { + MaybeLoadFallbackOrCompleteEmpty(); + return; + } + + icon_scale_ = ui::GetScaleForResourceScaleFactor(scale_factor); + icon_size_in_px_ = + apps_util::ConvertDipToPxForScale(size_hint_in_dip_, icon_scale_); + + auto size_and_purpose = icon_manager.FindIconMatchBigger( + web_app_id, {*icon_purpose_to_read}, icon_size_in_px_); + DCHECK(size_and_purpose.has_value()); + + switch (icon_type_) { + case IconType::kCompressed: + // Only read IconPurpose::ANY icons compressed as other purposes would + // need to find the icon size to match the icon purpose. + // + // If the icon px size returned from FindIconMatchBigger doesn't match + // icon_size_in_px_, the returned compressed icon should be resized, so + // ReadSmallestCompressedIconAny can't be used. + // + // If `icon_effects_` is not none, the icon needs to be converted to the + // uncompressed icon to apply the icon effects. So ReadIcons is used to + // get the icon to match the size in px and icon purpose to keep the + // consistent implementation with LoadWebAppIcon. + if (icon_effects_ == apps::IconEffects::kNone && + *icon_purpose_to_read == IconPurpose::ANY && + icon_size_in_px_ == size_and_purpose->size_px) { + icon_manager.ReadSmallestCompressedIconAny( + web_app_id, icon_size_in_px_, + base::BindOnce(&AppIconLoader::CompleteWithCompressed, + base::WrapRefCounted(this))); + return; + } + [[fallthrough]]; + case IconType::kUncompressed: + [[fallthrough]]; + case IconType::kStandard: { + std::vector<int> icon_pixel_sizes; + icon_pixel_sizes.emplace_back(size_and_purpose->size_px); + icon_manager.ReadIcons( + web_app_id, *icon_purpose_to_read, icon_pixel_sizes, + base::BindOnce(&AppIconLoader::OnReadWebAppForCompressedIconData, + base::WrapRefCounted(this))); + return; + } + case IconType::kUnknown: + MaybeLoadFallbackOrCompleteEmpty(); + return; + } + NOTREACHED(); +} + std::unique_ptr<arc::IconDecodeRequest> AppIconLoader::CreateArcIconDecodeRequest( base::OnceCallback<void(const gfx::ImageSkia& icon)> callback, @@ -735,7 +798,6 @@ } void AppIconLoader::CompleteWithCompressed(std::vector<uint8_t> data) { - DCHECK_EQ(icon_type_, IconType::kCompressed); if (data.empty()) { MaybeLoadFallbackOrCompleteEmpty(); return; @@ -822,6 +884,30 @@ MaybeApplyEffectsAndComplete(image_skia); } +void AppIconLoader::OnReadWebAppForCompressedIconData( + std::map<int, SkBitmap> icon_bitmaps) { + if (icon_bitmaps.empty()) { + MaybeLoadFallbackOrCompleteEmpty(); + return; + } + + SkBitmap bitmap = icon_bitmaps.begin()->second; + + // Resize |bitmap| to match |icon_scale|. + bitmap = skia::ImageOperations::Resize(bitmap, + skia::ImageOperations::RESIZE_LANCZOS3, + icon_size_in_px_, icon_size_in_px_); + + gfx::ImageSkia image_skia; + image_skia.AddRepresentation(gfx::ImageSkiaRep(bitmap, icon_scale_)); + image_skia.MakeThreadSafe(); + base::ThreadPool::PostTaskAndReplyWithResult( + FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE}, + base::BindOnce(&apps::EncodeImageToPngBytes, image_skia, icon_scale_), + base::BindOnce(&AppIconLoader::CompleteWithCompressed, + base::WrapRefCounted(this))); +} + void AppIconLoader::MaybeLoadFallbackOrCompleteEmpty() { if (fallback_favicon_url_.is_valid() && icon_size_in_px_ == kFaviconFallbackImagePx) {
diff --git a/chrome/browser/apps/app_service/app_icon/app_icon_loader.h b/chrome/browser/apps/app_service/app_icon/app_icon_loader.h index a39475f..5491fe1 100644 --- a/chrome/browser/apps/app_service/app_icon/app_icon_loader.h +++ b/chrome/browser/apps/app_service/app_icon/app_icon_loader.h
@@ -22,6 +22,7 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) #include "ash/components/arc/mojom/intent_helper.mojom.h" +#include "ui/base/resource/resource_scale_factor.h" #endif // BUILDFLAG(IS_CHROMEOS_ASH) namespace arc { @@ -111,6 +112,12 @@ // Loads icons for ARC activities. void LoadArcActivityIcons( const std::vector<arc::mojom::ActivityIconPtr>& icons); + + // Requests a compressed icon data with `scale_factor` for an web app + // identified by `app_id`. + void GetWebAppCompressedIconData(const std::string& web_app_id, + ui::ResourceScaleFactor scale_factor, + web_app::WebAppIconManager& icon_manager); #endif // BUILDFLAG(IS_CHROMEOS_ASH) private: @@ -142,15 +149,17 @@ void OnReadWebAppIcon(std::map<int, SkBitmap> icon_bitmaps); + void OnReadWebAppForCompressedIconData(std::map<int, SkBitmap> icon_bitmaps); + void MaybeLoadFallbackOrCompleteEmpty(); const IconType icon_type_ = IconType::kUnknown; const int size_hint_in_dip_ = 0; - const int icon_size_in_px_ = 0; + int icon_size_in_px_ = 0; // The scale factor the icon is intended for. See gfx::ImageSkiaRep::scale // comments. - const float icon_scale_ = 0.0f; + float icon_scale_ = 0.0f; // A scale factor to take as input for the IconType::kCompressed response. See // gfx::ImageSkia::GetRepresentation() comments. float icon_scale_for_compressed_response_ = 1.0f;
diff --git a/chrome/browser/apps/app_service/app_icon/web_app_icon_unittest.cc b/chrome/browser/apps/app_service/app_icon/web_app_icon_unittest.cc index 741b01c1..dfe2d65 100644 --- a/chrome/browser/apps/app_service/app_icon/web_app_icon_unittest.cc +++ b/chrome/browser/apps/app_service/app_icon/web_app_icon_unittest.cc
@@ -54,6 +54,7 @@ #include "chrome/browser/ui/app_list/md_icon_normalizer.h" #include "chrome/common/chrome_features.h" #include "chrome/grit/chrome_unscaled_resources.h" +#include "ui/base/resource/resource_scale_factor.h" #endif namespace apps { @@ -126,7 +127,8 @@ IconPurpose purpose, const std::vector<int>& sizes_px, apps::ScaleToSize scale_to_size_in_px, - gfx::ImageSkia& output_image_skia) { + gfx::ImageSkia& output_image_skia, + bool skip_icon_effects = false) { base::RunLoop run_loop; icon_manager().ReadIcons( app_id, purpose, sizes_px, @@ -156,20 +158,22 @@ run_loop.QuitClosure())); run_loop.Run(); - extensions::ChromeAppIcon::ResizeFunction resize_function; + if (!skip_icon_effects) { + extensions::ChromeAppIcon::ResizeFunction resize_function; #if BUILDFLAG(IS_CHROMEOS_ASH) - if (purpose == IconPurpose::ANY) { - output_image_skia = apps::CreateStandardIconImage(output_image_skia); - } - if (purpose == IconPurpose::MASKABLE) { - output_image_skia = apps::ApplyBackgroundAndMask(output_image_skia); - } + if (purpose == IconPurpose::ANY) { + output_image_skia = apps::CreateStandardIconImage(output_image_skia); + } + if (purpose == IconPurpose::MASKABLE) { + output_image_skia = apps::ApplyBackgroundAndMask(output_image_skia); + } #endif - extensions::ChromeAppIcon::ApplyEffects( - kSizeInDip, resize_function, true /* app_launchable */, - true /* from_bookmark */, extensions::ChromeAppIcon::Badge::kNone, - &output_image_skia); + extensions::ChromeAppIcon::ApplyEffects( + kSizeInDip, resize_function, true /* app_launchable */, + true /* from_bookmark */, extensions::ChromeAppIcon::Badge::kNone, + &output_image_skia); + } EnsureRepresentationsLoaded(output_image_skia); } @@ -194,6 +198,26 @@ &result)); } + void GenerateWebAppCompressedIcon(const std::string& app_id, + IconPurpose purpose, + const std::vector<int>& sizes_px, + apps::ScaleToSize scale_to_size_in_px, + float scale, + std::vector<uint8_t>& result) { + gfx::ImageSkia image_skia; + GenerateWebAppIcon(app_id, purpose, sizes_px, scale_to_size_in_px, + image_skia, /*skip_icon_effects=*/true); + + const gfx::ImageSkiaRep& image_skia_rep = + image_skia.GetRepresentation(scale); + ASSERT_EQ(image_skia_rep.scale(), scale); + + const SkBitmap& bitmap = image_skia_rep.GetBitmap(); + const bool discard_transparency = false; + ASSERT_TRUE(gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, discard_transparency, + &result)); + } + std::vector<uint8_t> GenerateWebAppNonEffectCompressedIcon( const std::string& app_id, const SquareSizePx icon_size_in_px) { @@ -242,6 +266,20 @@ return icon_value; } +#if BUILDFLAG(IS_CHROMEOS_ASH) + apps::IconValuePtr GetWebAppCompressedIconData( + const std::string& app_id, + IconEffects icon_effects, + IconType icon_type, + ui::ResourceScaleFactor scale_factor) { + base::test::TestFuture<apps::IconValuePtr> result; + apps::GetWebAppCompressedIconData(profile(), app_id, icon_effects, + icon_type, kSizeInDip, scale_factor, + result.GetCallback()); + return result.Take(); + } +#endif // BUILDFLAG(IS_CHROMEOS_ASH) + web_app::WebAppIconManager& icon_manager() { return *icon_manager_; } web_app::WebAppProvider& web_app_provider() { return *web_app_provider_; } @@ -709,6 +747,263 @@ DCHECK(image.isNull()); } +TEST_F(WebAppIconFactoryTest, GetNonMaskableCompressedIconData) { + auto web_app = web_app::test::CreateWebApp(); + const std::string app_id = web_app->app_id(); + + const float scale1 = 1.0; + const float scale2 = 2.0; + const int kIconSize1 = kSizeInDip * scale1; + const int kIconSize2 = kSizeInDip * scale2; + const std::vector<int> sizes_px{kIconSize1, kIconSize2}; + const std::vector<SkColor> colors{SK_ColorGREEN, SK_ColorYELLOW}; + WriteIcons(app_id, {IconPurpose::ANY}, sizes_px, colors); + + web_app->SetDownloadedIconSizes(IconPurpose::ANY, sizes_px); + RegisterApp(std::move(web_app)); + + ASSERT_TRUE(icon_manager().HasIcons(app_id, IconPurpose::ANY, sizes_px)); + + std::vector<uint8_t> src_data1; + std::vector<uint8_t> src_data2; + apps::ScaleToSize scale_to_size_in_px = {{1.0, kIconSize1}, + {2.0, kIconSize2}}; + GenerateWebAppCompressedIcon(app_id, IconPurpose::ANY, sizes_px, + scale_to_size_in_px, scale1, src_data1); + GenerateWebAppCompressedIcon(app_id, IconPurpose::ANY, sizes_px, + scale_to_size_in_px, scale2, src_data2); + + // Verift getting the compressed icon data for the compressed icon with icon + // effects. + auto icon1 = GetWebAppCompressedIconData( + app_id, apps::IconEffects::kRoundCorners, apps::IconType::kCompressed, + ui::ResourceScaleFactor::k100Percent); + auto icon2 = GetWebAppCompressedIconData( + app_id, apps::IconEffects::kRoundCorners, apps::IconType::kCompressed, + ui::ResourceScaleFactor::k200Percent); + + VerifyCompressedIcon(src_data1, *icon1); + VerifyCompressedIcon(src_data2, *icon2); +} + +TEST_F(WebAppIconFactoryTest, + GetNonMaskableCompressedIconDataWithDifferentSizeIcon) { + auto web_app = web_app::test::CreateWebApp(); + const std::string app_id = web_app->app_id(); + + const float scale1 = 1.0; + const float scale2 = 2.0; + const int kIconSize1 = 96; + const int kIconSize2 = 256; + const std::vector<int> sizes_px{kIconSize1, kIconSize2}; + const std::vector<SkColor> colors{SK_ColorGREEN, SK_ColorYELLOW}; + WriteIcons(app_id, {IconPurpose::ANY}, sizes_px, colors); + + web_app->SetDownloadedIconSizes(IconPurpose::ANY, sizes_px); + RegisterApp(std::move(web_app)); + + ASSERT_TRUE(icon_manager().HasIcons(app_id, IconPurpose::ANY, sizes_px)); + + std::vector<uint8_t> src_data1; + std::vector<uint8_t> src_data2; + apps::ScaleToSize scale_to_size_in_px = {{1.0, kIconSize1}, + {2.0, kIconSize2}}; + GenerateWebAppCompressedIcon(app_id, IconPurpose::ANY, sizes_px, + scale_to_size_in_px, scale1, src_data1); + GenerateWebAppCompressedIcon(app_id, IconPurpose::ANY, sizes_px, + scale_to_size_in_px, scale2, src_data2); + + // Verift getting the compressed icon data for the compressed icon with icon + // effects. + auto icon1 = GetWebAppCompressedIconData( + app_id, apps::IconEffects::kRoundCorners, apps::IconType::kCompressed, + ui::ResourceScaleFactor::k100Percent); + auto icon2 = GetWebAppCompressedIconData( + app_id, apps::IconEffects::kRoundCorners, apps::IconType::kCompressed, + ui::ResourceScaleFactor::k200Percent); + + VerifyCompressedIcon(src_data1, *icon1); + VerifyCompressedIcon(src_data2, *icon2); + + // Verift getting the compressed icon data for the uncompressed icon. + auto icon3 = GetWebAppCompressedIconData( + app_id, apps::IconEffects::kNone, apps::IconType::kUncompressed, + ui::ResourceScaleFactor::k100Percent); + auto icon4 = GetWebAppCompressedIconData( + app_id, apps::IconEffects::kNone, apps::IconType::kUncompressed, + ui::ResourceScaleFactor::k200Percent); + + VerifyCompressedIcon(src_data1, *icon3); + VerifyCompressedIcon(src_data2, *icon4); + + // Verift getting the compressed icon data for the standard icon. + auto icon5 = GetWebAppCompressedIconData( + app_id, apps::IconEffects::kNone, apps::IconType::kStandard, + ui::ResourceScaleFactor::k100Percent); + auto icon6 = GetWebAppCompressedIconData( + app_id, apps::IconEffects::kNone, apps::IconType::kStandard, + ui::ResourceScaleFactor::k200Percent); + + VerifyCompressedIcon(src_data1, *icon5); + VerifyCompressedIcon(src_data2, *icon6); +} + +TEST_F(WebAppIconFactoryTest, GetNonMaskableNonEffectCompressedIcon) { + auto web_app = web_app::test::CreateWebApp(); + const std::string app_id = web_app->app_id(); + + const float scale1 = 1.0; + const float scale2 = 2.0; + const int kIconSize1 = kSizeInDip * scale1; + const int kIconSize2 = kSizeInDip * scale2; + const std::vector<int> sizes_px{kIconSize1, kIconSize2}; + const std::vector<SkColor> colors{SK_ColorGREEN, SK_ColorYELLOW}; + WriteIcons(app_id, {IconPurpose::ANY}, sizes_px, colors); + + web_app->SetDownloadedIconSizes(IconPurpose::ANY, sizes_px); + RegisterApp(std::move(web_app)); + + ASSERT_TRUE(icon_manager().HasIcons(app_id, IconPurpose::ANY, sizes_px)); + + std::vector<uint8_t> src_data1; + std::vector<uint8_t> src_data2; + src_data1 = GenerateWebAppNonEffectCompressedIcon(app_id, kIconSize1); + src_data2 = GenerateWebAppNonEffectCompressedIcon(app_id, kIconSize2); + + auto icon1 = GetWebAppCompressedIconData( + app_id, apps::IconEffects::kNone, apps::IconType::kCompressed, + ui::ResourceScaleFactor::k100Percent); + auto icon2 = GetWebAppCompressedIconData( + app_id, apps::IconEffects::kNone, apps::IconType::kCompressed, + ui::ResourceScaleFactor::k200Percent); + + VerifyCompressedIcon(src_data1, *icon1); + VerifyCompressedIcon(src_data2, *icon2); +} + +TEST_F(WebAppIconFactoryTest, + GetNonMaskableNonEffectCompressedIconWithDifferentSizeIcon) { + auto web_app = web_app::test::CreateWebApp(); + const std::string app_id = web_app->app_id(); + + const float scale1 = 1.0; + const float scale2 = 2.0; + const int kIconSize1 = 96; + const int kIconSize2 = 256; + const std::vector<int> sizes_px{kIconSize1, kIconSize2}; + const std::vector<SkColor> colors{SK_ColorGREEN, SK_ColorYELLOW}; + WriteIcons(app_id, {IconPurpose::ANY}, sizes_px, colors); + + web_app->SetDownloadedIconSizes(IconPurpose::ANY, sizes_px); + RegisterApp(std::move(web_app)); + + ASSERT_TRUE(icon_manager().HasIcons(app_id, IconPurpose::ANY, sizes_px)); + + std::vector<uint8_t> src_data1; + std::vector<uint8_t> src_data2; + apps::ScaleToSize scale_to_size_in_px = {{1.0, kIconSize1}, + {2.0, kIconSize2}}; + GenerateWebAppCompressedIcon(app_id, IconPurpose::ANY, sizes_px, + scale_to_size_in_px, scale1, src_data1); + GenerateWebAppCompressedIcon(app_id, IconPurpose::ANY, sizes_px, + scale_to_size_in_px, scale2, src_data2); + + // Verift getting the compressed icon data for the compressed icon. + auto icon1 = GetWebAppCompressedIconData( + app_id, apps::IconEffects::kNone, apps::IconType::kCompressed, + ui::ResourceScaleFactor::k100Percent); + auto icon2 = GetWebAppCompressedIconData( + app_id, apps::IconEffects::kNone, apps::IconType::kCompressed, + ui::ResourceScaleFactor::k200Percent); + + VerifyCompressedIcon(src_data1, *icon1); + VerifyCompressedIcon(src_data2, *icon2); + + // Verift getting the compressed icon data for the uncompressed icon. + auto icon3 = GetWebAppCompressedIconData( + app_id, apps::IconEffects::kNone, apps::IconType::kUncompressed, + ui::ResourceScaleFactor::k100Percent); + auto icon4 = GetWebAppCompressedIconData( + app_id, apps::IconEffects::kNone, apps::IconType::kUncompressed, + ui::ResourceScaleFactor::k200Percent); + + VerifyCompressedIcon(src_data1, *icon3); + VerifyCompressedIcon(src_data2, *icon4); + + // Verift getting the compressed icon data for the standard icon. + auto icon5 = GetWebAppCompressedIconData( + app_id, apps::IconEffects::kNone, apps::IconType::kStandard, + ui::ResourceScaleFactor::k100Percent); + auto icon6 = GetWebAppCompressedIconData( + app_id, apps::IconEffects::kNone, apps::IconType::kStandard, + ui::ResourceScaleFactor::k200Percent); + + VerifyCompressedIcon(src_data1, *icon5); + VerifyCompressedIcon(src_data2, *icon6); +} + +TEST_F(WebAppIconFactoryTest, GetMaskableCompressedIcon) { + auto web_app = web_app::test::CreateWebApp(); + const std::string app_id = web_app->app_id(); + + const float scale1 = 1.0; + const float scale2 = 2.0; + const int kIconSize1 = 128; + const int kIconSize2 = 256; + const std::vector<int> sizes_px{kIconSize1, kIconSize2}; + const std::vector<SkColor> colors{SK_ColorGREEN, SK_ColorYELLOW}; + WriteIcons(app_id, {IconPurpose::ANY, IconPurpose::MASKABLE}, sizes_px, + colors); + + web_app->SetDownloadedIconSizes(IconPurpose::ANY, {kIconSize1}); + web_app->SetDownloadedIconSizes(IconPurpose::MASKABLE, {kIconSize2}); + + RegisterApp(std::move(web_app)); + + std::vector<uint8_t> src_data1; + std::vector<uint8_t> src_data2; + apps::ScaleToSize scale_to_size_in_px = {{1.0, kIconSize2}, + {2.0, kIconSize2}}; + GenerateWebAppCompressedIcon(app_id, IconPurpose::MASKABLE, {kIconSize2}, + scale_to_size_in_px, scale1, src_data1); + GenerateWebAppCompressedIcon(app_id, IconPurpose::MASKABLE, {kIconSize2}, + scale_to_size_in_px, scale2, src_data2); + + apps::IconValuePtr icon; + + // Verift getting the compressed icon data for the compressed icon. + auto icon1 = GetWebAppCompressedIconData( + app_id, apps::IconEffects::kNone, apps::IconType::kCompressed, + ui::ResourceScaleFactor::k100Percent); + auto icon2 = GetWebAppCompressedIconData( + app_id, apps::IconEffects::kNone, apps::IconType::kCompressed, + ui::ResourceScaleFactor::k200Percent); + + VerifyCompressedIcon(src_data1, *icon1); + VerifyCompressedIcon(src_data2, *icon2); + + // Verift getting the compressed icon data for the uncompressed icon. + auto icon3 = GetWebAppCompressedIconData( + app_id, apps::IconEffects::kNone, apps::IconType::kUncompressed, + ui::ResourceScaleFactor::k100Percent); + auto icon4 = GetWebAppCompressedIconData( + app_id, apps::IconEffects::kNone, apps::IconType::kUncompressed, + ui::ResourceScaleFactor::k200Percent); + + VerifyCompressedIcon(src_data1, *icon3); + VerifyCompressedIcon(src_data2, *icon4); + + // Verift getting the compressed icon data for the standard icon. + auto icon5 = GetWebAppCompressedIconData( + app_id, apps::IconEffects::kNone, apps::IconType::kStandard, + ui::ResourceScaleFactor::k100Percent); + auto icon6 = GetWebAppCompressedIconData( + app_id, apps::IconEffects::kNone, apps::IconType::kStandard, + ui::ResourceScaleFactor::k200Percent); + + VerifyCompressedIcon(src_data1, *icon5); + VerifyCompressedIcon(src_data2, *icon6); +} #endif // BUILDFLAG(IS_CHROMEOS_ASH) } // namespace apps
diff --git a/chrome/browser/ash/accessibility/spoken_feedback_app_list_browsertest.cc b/chrome/browser/ash/accessibility/spoken_feedback_app_list_browsertest.cc index 0b4c203..0d8ba842 100644 --- a/chrome/browser/ash/accessibility/spoken_feedback_app_list_browsertest.cc +++ b/chrome/browser/ash/accessibility/spoken_feedback_app_list_browsertest.cc
@@ -133,7 +133,7 @@ TestSearchProvider** web_provider_ptr) { std::unique_ptr<TestSearchProvider> apps_provider = std::make_unique<TestSearchProvider>( - "app", ChromeSearchResult::DisplayType::kTile, + "app", ChromeSearchResult::DisplayType::kList, ChromeSearchResult::Category::kApps, ChromeSearchResult::ResultType::kInstalledApp); *apps_provider_ptr = apps_provider.get(); @@ -235,19 +235,6 @@ return test_item_index; } - std::vector<std::string> GetPublishedSuggestionChips() { - std::vector<std::string> chips; - std::vector<ChromeSearchResult*> published_results = - AppListClientImpl::GetInstance() - ->GetModelUpdaterForTest() - ->GetPublishedSearchResultsForTest(); - for (auto* result : published_results) { - if (result->display_type() == SearchResultDisplayType::kChip) - chips.push_back(base::UTF16ToUTF8(result->title())); - } - return chips; - } - AppListItem* FindItemByName(const std::string& name, int* index) { AppListModel* const model = AppListModelProvider::Get()->model(); AppListItemList* item_list = model->top_level_item_list(); @@ -536,8 +523,9 @@ sm_.Replay(); } +// TODO(https://crbug.com/1393235): Update this browser test to test recent +// apps. IN_PROC_BROWSER_TEST_P(SpokenFeedbackAppListTest, ClamshellLauncher) { - std::vector<std::string> suggestion_chips = GetPublishedSuggestionChips(); PopulateApps(3); int test_item_index = 0; @@ -566,15 +554,6 @@ sm_.Call([this]() { SendKeyPressWithSearch(ui::VKEY_RIGHT); }); sm_.ExpectSpeech("Button"); - // Move focus over recent apps, which are currently populated using suggestion - // chip results. - // TODO(https://crbug.com/1260427): Traverse over all recent apps when the - // linked issue is fixed. - if (!suggestion_chips.empty()) { - sm_.Call([this]() { SendKeyPressWithSearch(ui::VKEY_DOWN); }); - sm_.ExpectSpeech("Button"); - } - // Skip over apps that were installed before the test item. // This selects the first app installed by the test. for (int i = 0; i < test_item_index; ++i) {
diff --git a/chrome/browser/ash/android_sms/fcm_connection_establisher_unittest.cc b/chrome/browser/ash/android_sms/fcm_connection_establisher_unittest.cc index 48f6b18..45e56368 100644 --- a/chrome/browser/ash/android_sms/fcm_connection_establisher_unittest.cc +++ b/chrome/browser/ash/android_sms/fcm_connection_establisher_unittest.cc
@@ -31,12 +31,9 @@ : task_environment_(content::BrowserTaskEnvironment::IO_MAINLOOP) {} ~FcmConnectionEstablisherTest() override = default; - void VerifyTransferrableMessage( - const char* expected, - const content::FakeServiceWorkerContext:: - StartServiceWorkerAndDispatchMessageArgs& call_args) { - auto payload = blink::DecodeToWebMessagePayload( - std::get<blink::TransferableMessage>(call_args)); + void VerifyTransferrableMessage(const char* expected, + blink::TransferableMessage message) { + auto payload = blink::DecodeToWebMessagePayload(std::move(message)); EXPECT_EQ(base::UTF8ToUTF16(expected), absl::get<std::u16string>(payload.value())); } @@ -66,7 +63,8 @@ ASSERT_EQ(1u, message_dispatch_calls.size()); EXPECT_EQ(GetAndroidMessagesURL(), std::get<GURL>(message_dispatch_calls[0])); VerifyTransferrableMessage(FcmConnectionEstablisher::kStartFcmMessage, - message_dispatch_calls[0]); + std::move(std::get<blink::TransferableMessage>( + message_dispatch_calls[0]))); // Return success to result callback and verify that no retries are attempted // and success histogram is recorded. @@ -92,7 +90,8 @@ base::RunLoop().RunUntilIdle(); ASSERT_EQ(2u, message_dispatch_calls.size()); VerifyTransferrableMessage(FcmConnectionEstablisher::kStartFcmMessage, - message_dispatch_calls[1]); + std::move(std::get<blink::TransferableMessage>( + message_dispatch_calls[1]))); // Verify that if the first request fails then it's retried std::move(std::get<content::ServiceWorkerContext::ResultCallback>( @@ -107,7 +106,8 @@ mock_retry_timer_ptr->Fire(); ASSERT_EQ(3u, message_dispatch_calls.size()); VerifyTransferrableMessage(FcmConnectionEstablisher::kStartFcmMessage, - message_dispatch_calls[2]); + std::move(std::get<blink::TransferableMessage>( + message_dispatch_calls[2]))); // Verify that if the first request succeeds then the next message is // dispatched @@ -117,7 +117,8 @@ ASSERT_EQ(4u, message_dispatch_calls.size()); EXPECT_FALSE(mock_retry_timer_ptr->IsRunning()); VerifyTransferrableMessage(FcmConnectionEstablisher::kResumeFcmMessage, - message_dispatch_calls[3]); + std::move(std::get<blink::TransferableMessage>( + message_dispatch_calls[3]))); // Complete second request and verify that no more retries are scheduled. std::move(std::get<content::ServiceWorkerContext::ResultCallback>( @@ -176,7 +177,8 @@ ASSERT_EQ(1u, message_dispatch_calls.size()); EXPECT_EQ(GetAndroidMessagesURL(), std::get<GURL>(message_dispatch_calls[0])); VerifyTransferrableMessage(FcmConnectionEstablisher::kStopFcmMessage, - message_dispatch_calls[0]); + std::move(std::get<blink::TransferableMessage>( + message_dispatch_calls[0]))); } } // namespace android_sms
diff --git a/chrome/browser/ash/app_restore/arc_app_single_restore_handler.cc b/chrome/browser/ash/app_restore/arc_app_single_restore_handler.cc index 527124ba..86e34e7 100644 --- a/chrome/browser/ash/app_restore/arc_app_single_restore_handler.cc +++ b/chrome/browser/ash/app_restore/arc_app_single_restore_handler.cc
@@ -100,10 +100,12 @@ // bounds is from "recording data" in ash wm side, so it will reduce the top // caption bar size when launch ghost window. However, if here use the bounds // from Android side, the bounds should be added a "caption" size. - restore_data.bounds_in_root->Inset(gfx::Insets().set_top( - -views::GetCaptionButtonLayoutSize( - views::CaptionButtonLayoutSize::kNonBrowserCaption) - .height())); + if (restore_data.bounds_in_root.has_value()) { + restore_data.bounds_in_root->Inset(gfx::Insets().set_top( + -views::GetCaptionButtonLayoutSize( + views::CaptionButtonLayoutSize::kNonBrowserCaption) + .height())); + } restore_data.window_state_type = static_cast<chromeos::WindowStateType>(window_info->state); restore_data.event_flag = event_flags;
diff --git a/chrome/browser/ash/app_restore/arc_app_single_restore_handler.h b/chrome/browser/ash/app_restore/arc_app_single_restore_handler.h index 9eaca33b..68cd01b 100644 --- a/chrome/browser/ash/app_restore/arc_app_single_restore_handler.h +++ b/chrome/browser/ash/app_restore/arc_app_single_restore_handler.h
@@ -56,6 +56,8 @@ NotLaunchIfShelfNotReady); FRIEND_TEST_ALL_PREFIXES(ArcAppSingleRestoreHandlerTest, PendingLaunchIfShelfHasReady); + FRIEND_TEST_ALL_PREFIXES(ArcAppSingleRestoreHandlerTest, + NullBoundsNotCauseCrash); // Called when ARC app has ready. It's expected only called once. void SendAppLaunchRequestToARC();
diff --git a/chrome/browser/ash/app_restore/arc_app_single_restore_handler_unittest.cc b/chrome/browser/ash/app_restore/arc_app_single_restore_handler_unittest.cc index 1a693d7d..11512cc7 100644 --- a/chrome/browser/ash/app_restore/arc_app_single_restore_handler_unittest.cc +++ b/chrome/browser/ash/app_restore/arc_app_single_restore_handler_unittest.cc
@@ -109,4 +109,20 @@ ASSERT_FALSE(handler.IsAppPendingRestore(fake_app_id + "_not_equal_real_id")); } +TEST_F(ArcAppSingleRestoreHandlerTest, NullBoundsNotCauseCrash) { + ArcAppSingleRestoreHandler handler; + + const std::string fake_app_id = "not_exist_app_id"; + auto window_info = arc::mojom::WindowInfo::New(); + window_info->window_id = 100; + window_info->display_id = display::kInvalidDisplayId; + // leave the bounds null. + + handler.OnShelfReady(); + handler.ghost_window_handler_ = window_handler(); + handler.LaunchGhostWindowWithApp( + profile(), fake_app_id, nullptr, 0 /*event_flags*/, + arc::GhostWindowType::kAppLaunch, std::move(window_info)); +} + } // namespace ash::app_restore
diff --git a/chrome/browser/ash/arc/window_predictor/window_predictor.cc b/chrome/browser/ash/arc/window_predictor/window_predictor.cc index 3d79d97f..7c811cb3 100644 --- a/chrome/browser/ash/arc/window_predictor/window_predictor.cc +++ b/chrome/browser/ash/arc/window_predictor/window_predictor.cc
@@ -117,6 +117,10 @@ arc::mojom::WindowInfoPtr predict_window_info = PredictAppWindowInfo(app_info, window_info.Clone()); + // TODO(sstan): PredictAppWindowInfo should always return fulfilled info. + if (!predict_window_info || !predict_window_info->bounds.has_value()) + return false; + arc_task_handler->GetWindowPredictorArcAppRestoreHandler(launch_counter) ->LaunchGhostWindowWithApp( profile, arc_app_id, intent ? intent->Clone() : nullptr, event_flags,
diff --git a/chrome/browser/ash/borealis/borealis_features_util.cc b/chrome/browser/ash/borealis/borealis_features_util.cc index 9396684e..9d6808b 100644 --- a/chrome/browser/ash/borealis/borealis_features_util.cc +++ b/chrome/browser/ash/borealis/borealis_features_util.cc
@@ -53,10 +53,10 @@ // Returns the model name of this device (either from its CustomizationId or by // parsing its hardware class). Returns "" if it fails. std::string GetModelName() { - std::string ret; - if (chromeos::system::StatisticsProvider::GetInstance()->GetMachineStatistic( - chromeos::system::kCustomizationIdKey, &ret)) { - return ret; + if (const absl::optional<base::StringPiece> ret = + chromeos::system::StatisticsProvider::GetInstance() + ->GetMachineStatistic(chromeos::system::kCustomizationIdKey)) { + return std::string(ret.value()); } LOG(WARNING) << "CustomizationId unavailable, attempting to parse hardware class"; @@ -64,9 +64,10 @@ // As a fallback when the CustomizationId is not available, we try to parse it // out of the hardware class. If The hardware class is unavailable, all bets // are off. - std::string hardware_class; - if (!chromeos::system::StatisticsProvider::GetInstance()->GetMachineStatistic( - chromeos::system::kHardwareClassKey, &hardware_class)) { + const absl::optional<base::StringPiece> hardware_class_statistic = + chromeos::system::StatisticsProvider::GetInstance()->GetMachineStatistic( + chromeos::system::kHardwareClassKey); + if (!hardware_class_statistic) { return ""; } @@ -79,6 +80,7 @@ // // Naively searching for the first hyphen is fine until we start caring about // models with hyphens in the name. + base::StringPiece hardware_class = hardware_class_statistic.value(); size_t hyphen_pos = hardware_class.find('-'); if (hyphen_pos != std::string::npos) hardware_class = hardware_class.substr(0, hyphen_pos);
diff --git a/chrome/browser/ash/dbus/fusebox_service_provider.cc b/chrome/browser/ash/dbus/fusebox_service_provider.cc index f58a42e..359cbe7 100644 --- a/chrome/browser/ash/dbus/fusebox_service_provider.cc +++ b/chrome/browser/ash/dbus/fusebox_service_provider.cc
@@ -16,9 +16,12 @@ // The "fusebox_staging" concept is described in // chrome/browser/ash/fusebox/fusebox_staging.proto +// +// TODO(b/255520194): remove this section. namespace fusebox_staging { const char kRead2Method[] = "Read2"; -} +const char kWrite2Method[] = "Write2"; +} // namespace fusebox_staging namespace ash { @@ -175,6 +178,11 @@ base::BindRepeating(&FuseBoxServiceProvider::Stat, weak_ptr_factory_.GetWeakPtr()), base::BindOnce(&OnExportedCallback)); + object->ExportMethod(fusebox::kFuseBoxServiceInterface, + fusebox_staging::kWrite2Method, + base::BindRepeating(&FuseBoxServiceProvider::Write2, + weak_ptr_factory_.GetWeakPtr()), + base::BindOnce(&OnExportedCallback)); object->ExportMethod( fusebox::kFuseBoxServiceInterface, fusebox::kListStoragesMethod, @@ -411,6 +419,26 @@ base::BindOnce(&ReplyToStat, method_call, std::move(sender))); } +void FuseBoxServiceProvider::Write2( + dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender sender) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + dbus::MessageReader reader(method_call); + fusebox_staging::Write2RequestProto request_proto; + if (!reader.PopArrayOfBytesAsProto(&request_proto)) { + fusebox_staging::Write2ResponseProto response_proto; + response_proto.set_posix_error_code(EINVAL); + ReplyToProtoMethod(method_call, std::move(sender), response_proto); + return; + } + + server_.Write2( + request_proto, + base::BindOnce(&ReplyToProtoMethod<fusebox_staging::Write2ResponseProto>, + method_call, std::move(sender))); +} + void FuseBoxServiceProvider::ListStorages( dbus::MethodCall* method_call, dbus::ExportedObject::ResponseSender sender) {
diff --git a/chrome/browser/ash/dbus/fusebox_service_provider.h b/chrome/browser/ash/dbus/fusebox_service_provider.h index ed85cb9f..c5d6567 100644 --- a/chrome/browser/ash/dbus/fusebox_service_provider.h +++ b/chrome/browser/ash/dbus/fusebox_service_provider.h
@@ -58,6 +58,8 @@ dbus::ExportedObject::ResponseSender sender); void Stat(dbus::MethodCall* method_call, dbus::ExportedObject::ResponseSender sender); + void Write2(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender sender); void ListStorages(dbus::MethodCall* method_call, dbus::ExportedObject::ResponseSender sender);
diff --git a/chrome/browser/ash/extensions/input_method_api.cc b/chrome/browser/ash/extensions/input_method_api.cc index 208e79b6..925839b1 100644 --- a/chrome/browser/ash/extensions/input_method_api.cc +++ b/chrome/browser/ash/extensions/input_method_api.cc
@@ -521,8 +521,6 @@ registry .RegisterFunction<InputMethodPrivateFetchAllDictionaryWordsFunction>(); registry.RegisterFunction<InputMethodPrivateAddWordToDictionaryFunction>(); - registry - .RegisterFunction<InputMethodPrivateNotifyImeMenuItemActivatedFunction>(); registry.RegisterFunction<InputMethodPrivateOpenOptionsPageFunction>(); }
diff --git a/chrome/browser/ash/extensions/input_method_apitest_chromeos.cc b/chrome/browser/ash/extensions/input_method_apitest_chromeos.cc index 6461977..3f27cd2 100644 --- a/chrome/browser/ash/extensions/input_method_apitest_chromeos.cc +++ b/chrome/browser/ash/extensions/input_method_apitest_chromeos.cc
@@ -140,7 +140,6 @@ IN_PROC_BROWSER_TEST_F(ExtensionInputMethodApiTest, ImeMenuAPITest) { ExtensionTestMessageListener activated_listener("activated"); ExtensionTestMessageListener menu_listener("get_menu_update"); - ExtensionTestMessageListener item_activated_listenter("get_menu_activated"); ExtensionTestMessageListener list_listenter("list_change"); browser()->profile()->GetPrefs()->SetBoolean(prefs::kLanguageImeMenuActivated, true); @@ -163,7 +162,6 @@ ASSERT_TRUE(activated_listener.WaitUntilSatisfied()) << message_; ASSERT_TRUE(menu_listener.WaitUntilSatisfied()) << message_; - ASSERT_TRUE(item_activated_listenter.WaitUntilSatisfied()) << message_; InputMethodManager::Get()->GetActiveIMEState()->ChangeInputMethod( kTestIMEID2, false /* show_message */);
diff --git a/chrome/browser/ash/file_manager/file_tasks.cc b/chrome/browser/ash/file_manager/file_tasks.cc index 8c82a1b1..f5f05ac 100644 --- a/chrome/browser/ash/file_manager/file_tasks.cc +++ b/chrome/browser/ash/file_manager/file_tasks.cc
@@ -574,6 +574,7 @@ void RegisterProfilePrefs(PrefRegistrySimple* registry) { registry->RegisterDictionaryPref(prefs::kDefaultHandlersForFileExtensions); registry->RegisterBooleanPref(prefs::kOfficeSetupComplete, false); + registry->RegisterBooleanPref(prefs::kOfficeFilesAlwaysMove, false); } // Converts a string to a TaskType. Returns TASK_TYPE_UNKNOWN on error. @@ -1242,4 +1243,12 @@ return profile->GetPrefs()->GetBoolean(prefs::kOfficeSetupComplete); } +void SetAlwaysMoveOfficeFiles(Profile* profile, bool always_move) { + profile->GetPrefs()->SetBoolean(prefs::kOfficeFilesAlwaysMove, always_move); +} + +bool AlwaysMoveOfficeFiles(Profile* profile) { + return profile->GetPrefs()->GetBoolean(prefs::kOfficeFilesAlwaysMove); +} + } // namespace file_manager::file_tasks
diff --git a/chrome/browser/ash/file_manager/file_tasks.h b/chrome/browser/ash/file_manager/file_tasks.h index 42fd158..fbebab3 100644 --- a/chrome/browser/ash/file_manager/file_tasks.h +++ b/chrome/browser/ash/file_manager/file_tasks.h
@@ -389,6 +389,12 @@ // Whether or not the setup flow for office files has ever been completed. bool OfficeSetupComplete(Profile* profile); +// Sets the user preference storing whether we should always move office files +// without first asking the user. +void SetAlwaysMoveOfficeFiles(Profile* profile, bool complete = true); +// Whether we should always move office files without first asking the user. +bool AlwaysMoveOfficeFiles(Profile* profile); + } // namespace file_manager::file_tasks #endif // CHROME_BROWSER_ASH_FILE_MANAGER_FILE_TASKS_H_
diff --git a/chrome/browser/ash/fusebox/fusebox_server.cc b/chrome/browser/ash/fusebox/fusebox_server.cc index 92ac1ca..b3a5989 100644 --- a/chrome/browser/ash/fusebox/fusebox_server.cc +++ b/chrome/browser/ash/fusebox/fusebox_server.cc
@@ -21,10 +21,8 @@ #include "chrome/browser/profiles/profile_manager.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" -#include "net/base/io_buffer.h" #include "storage/browser/file_system/async_file_util.h" #include "storage/browser/file_system/external_mount_points.h" -#include "storage/browser/file_system/file_stream_reader.h" #include "storage/browser/file_system/file_system_url.h" #include "storage/common/file_system/file_system_util.h" #include "third_party/cros_system_api/dbus/fusebox/dbus-constants.h" @@ -361,6 +359,25 @@ std::move(callback).Run(response_proto); } +void RunWrite2CallbackFailure(Server::Write2Callback callback, + base::File::Error error_code) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + fusebox_staging::Write2ResponseProto response_proto; + response_proto.set_posix_error_code(FileErrorToErrno(error_code)); + std::move(callback).Run(response_proto); +} + +void RunWrite2CallbackTypical(Server::Write2Callback callback, int length) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + fusebox_staging::Write2ResponseProto response_proto; + if (length < 0) { + response_proto.set_posix_error_code(NetErrorToErrno(length)); + } + std::move(callback).Run(response_proto); +} + void ReadOnIOThread(scoped_refptr<storage::FileSystemContext> fs_context, storage::FileSystemURL fs_url, int64_t offset, @@ -496,6 +513,69 @@ std::move(buffer), length)); } +void Server::ReadWriter::Write( + scoped_refptr<storage::FileSystemContext> fs_context, + scoped_refptr<net::StringIOBuffer> buffer, + int64_t offset, + int length, + Server::Write2Callback callback) { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + + // See if we can re-use the previous storage::FileStreamWriter. + std::unique_ptr<storage::FileStreamWriter> fs_writer; + if (fs_writer_ && (write_offset_ == offset)) { + fs_writer = std::move(fs_writer_); + write_offset_ = -1; + } else { + fs_writer = fs_context->CreateFileStreamWriter(fs_url_, offset); + if (!fs_writer) { + content::GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, + base::BindOnce(&RunWrite2CallbackFailure, std::move(callback), + base::File::Error::FILE_ERROR_INVALID_URL)); + return; + } + } + + // Save the pointer before we std::move fs_writer into a base::OnceCallback. + // The std::move keeps the underlying storage::FileStreamWriter alive while + // any network I/O is pending. Without the std::move, the underlying + // storage::FileStreamWriter would get destroyed at the end of this function. + auto* saved_fs_writer = fs_writer.get(); + + auto pair = base::SplitOnceCallback(base::BindOnce( + &Server::ReadWriter::OnWrite, weak_ptr_factory_.GetWeakPtr(), + std::move(callback), fs_context, std::move(fs_writer), buffer, offset)); + + int result = + saved_fs_writer->Write(buffer.get(), length, std::move(pair.first)); + if (result != net::ERR_IO_PENDING) { // The write was synchronous. + std::move(pair.second).Run(result); + } +} + +void Server::ReadWriter::OnWrite( + Server::Write2Callback callback, + scoped_refptr<storage::FileSystemContext> fs_context, + std::unique_ptr<storage::FileStreamWriter> fs_writer, + scoped_refptr<net::IOBuffer> buffer, + int64_t offset, + int length) { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + + if (length >= 0) { + fs_writer_ = std::move(fs_writer); + write_offset_ = offset + length; + } else { + fs_writer_.reset(); + write_offset_ = -1; + } + + content::GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, + base::BindOnce(&RunWrite2CallbackTypical, std::move(callback), length)); +} + Server::FuseFileMapEntry::FuseFileMapEntry( scoped_refptr<storage::FileSystemContext> fs_context_arg, storage::FileSystemURL fs_url_arg, @@ -519,6 +599,22 @@ .WithArgs(fs_context_, offset, length, std::move(callback)); } +void Server::FuseFileMapEntry::DoWrite2( + const fusebox_staging::Write2RequestProto& request, + Server::Write2Callback callback) { + if (!request.has_data() || request.data().empty()) { + fusebox_staging::Write2ResponseProto response_proto; + std::move(callback).Run(response_proto); + return; + } + scoped_refptr<net::StringIOBuffer> buffer = + base::MakeRefCounted<net::StringIOBuffer>(request.data()); + int64_t offset = request.has_offset() ? request.offset() : 0; + seqbnd_read_writer_.AsyncCall(&Server::ReadWriter::Write) + .WithArgs(fs_context_, std::move(buffer), offset, + static_cast<int>(request.data().size()), std::move(callback)); +} + Server::PrefixMapEntry::PrefixMapEntry(std::string fs_url_prefix_arg, bool read_only_arg) : fs_url_prefix(fs_url_prefix_arg), read_only(read_only_arg) {} @@ -687,6 +783,8 @@ FuseFileMapEntry& entry = iter->second; base::circular_deque<PendingRead2> pending_reads = std::move(entry.pending_reads_); + base::circular_deque<PendingWrite2> pending_writes = + std::move(entry.pending_writes_); fuse_file_map_.erase(iter); @@ -700,6 +798,13 @@ std::move(pending_read.second).Run(read2_response_proto); } } + if (!pending_writes.empty()) { + fusebox_staging::Write2ResponseProto write2_esponse_proto; + write2_esponse_proto.set_posix_error_code(EBUSY); + for (auto& pending_read : pending_writes) { + std::move(pending_read.second).Run(write2_esponse_proto); + } + } } void Server::Create(const fusebox_staging::CreateRequestProto& request_proto, @@ -1012,6 +1117,41 @@ common.fs_url, metadata_fields, std::move(outer_callback))); } +void Server::Write2(const fusebox_staging::Write2RequestProto& request_proto, + Write2Callback callback) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + uint64_t fuse_handle = + request_proto.has_fuse_handle() ? request_proto.fuse_handle() : 0; + auto iter = fuse_file_map_.find(fuse_handle); + if (iter == fuse_file_map_.end()) { + fusebox_staging::Write2ResponseProto response_proto; + response_proto.set_posix_error_code(ENOENT); + std::move(callback).Run(response_proto); + return; + } else if (!iter->second.writable_) { + fusebox_staging::Write2ResponseProto response_proto; + response_proto.set_posix_error_code(EACCES); + std::move(callback).Run(response_proto); + return; + } else if (request_proto.has_data() && + (request_proto.data().size() > INT_MAX)) { + fusebox_staging::Write2ResponseProto response_proto; + response_proto.set_posix_error_code(EMSGSIZE); + std::move(callback).Run(response_proto); + return; + } else if (iter->second.has_in_flight_write_) { + iter->second.pending_writes_.emplace_back(request_proto, + std::move(callback)); + return; + } + iter->second.has_in_flight_write_ = true; + iter->second.DoWrite2( + request_proto, + base::BindOnce(&Server::OnWrite2, weak_ptr_factory_.GetWeakPtr(), + fuse_handle, std::move(callback))); +} + void Server::ListStorages(const ListStoragesRequestProto& request, ListStoragesCallback callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); @@ -1175,6 +1315,36 @@ } } +void Server::OnWrite2( + uint64_t fuse_handle, + Write2Callback callback, + const fusebox_staging::Write2ResponseProto& response_proto) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + auto iter = fuse_file_map_.find(fuse_handle); + if (iter == fuse_file_map_.end()) { + fusebox_staging::Write2ResponseProto enoent_response_proto; + enoent_response_proto.set_posix_error_code(ENOENT); + std::move(callback).Run(enoent_response_proto); + return; + } + FuseFileMapEntry& entry = iter->second; + entry.has_in_flight_write_ = false; + + std::move(callback).Run(std::move(response_proto)); + + if (entry.pending_writes_.empty()) { + return; + } + PendingWrite2 pending = std::move(entry.pending_writes_.front()); + entry.pending_writes_.pop_front(); + entry.has_in_flight_write_ = true; + entry.DoWrite2( + pending.first, + base::BindOnce(&Server::OnWrite2, weak_ptr_factory_.GetWeakPtr(), + fuse_handle, std::move(pending.second))); +} + void Server::EraseFuseFileMapEntry(uint64_t fuse_handle) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
diff --git a/chrome/browser/ash/fusebox/fusebox_server.h b/chrome/browser/ash/fusebox/fusebox_server.h index fb8bf44..840df0af 100644 --- a/chrome/browser/ash/fusebox/fusebox_server.h +++ b/chrome/browser/ash/fusebox/fusebox_server.h
@@ -17,7 +17,10 @@ #include "chrome/browser/ash/fusebox/fusebox.pb.h" #include "chrome/browser/ash/fusebox/fusebox_moniker.h" #include "chrome/browser/ash/fusebox/fusebox_staging.pb.h" +#include "net/base/io_buffer.h" #include "storage/browser/file_system/async_file_util.h" +#include "storage/browser/file_system/file_stream_reader.h" +#include "storage/browser/file_system/file_stream_writer.h" #include "storage/browser/file_system/file_system_context.h" class Profile; @@ -161,6 +164,12 @@ bool read_only)>; void Stat(const std::string& fs_url_as_string, StatCallback callback); + // Write2 writes to a virtual file opened by Open2. + using Write2Callback = base::OnceCallback<void( + const fusebox_staging::Write2ResponseProto& response)>; + void Write2(const fusebox_staging::Write2RequestProto& request, + Write2Callback callback); + // File operation D-Bus methods above. Meta D-Bus methods below, which do not // map 1:1 to FUSE or C standard library file operations. @@ -207,6 +216,8 @@ using PendingRead2 = std::pair<fusebox_staging::Read2RequestProto, Read2Callback>; + using PendingWrite2 = + std::pair<fusebox_staging::Write2RequestProto, Write2Callback>; // Lives entirely on the I/O thread, as enforced by base::SequenceBound. struct ReadWriter { @@ -224,13 +235,29 @@ int64_t offset, int length); + void Write(scoped_refptr<storage::FileSystemContext> fs_context, + scoped_refptr<net::StringIOBuffer> buffer, + int64_t offset, + int length, + Server::Write2Callback callback); + void OnWrite(Server::Write2Callback callback, + scoped_refptr<storage::FileSystemContext> fs_context, + std::unique_ptr<storage::FileStreamWriter> fs_writer, + scoped_refptr<net::IOBuffer> buffer, + int64_t offset, + int length); + const storage::FileSystemURL fs_url_; std::unique_ptr<storage::FileStreamReader> fs_reader_; // Unused whenever fs_reader_ is nullptr. int64_t read_offset_ = -1; - // TODO(b/255703917): write support and snapshot management. + std::unique_ptr<storage::FileStreamWriter> fs_writer_; + // Unused whenever fs_writer_ is nullptr. + int64_t write_offset_ = -1; + + // TODO(b/255703917): snapshot management. base::WeakPtrFactory<ReadWriter> weak_ptr_factory_{this}; }; @@ -245,13 +272,17 @@ void DoRead2(const fusebox_staging::Read2RequestProto& request, Read2Callback callback); + void DoWrite2(const fusebox_staging::Write2RequestProto& request, + Write2Callback callback); const scoped_refptr<storage::FileSystemContext> fs_context_; const bool readable_; const bool writable_; bool has_in_flight_read_ = false; + bool has_in_flight_write_ = false; base::circular_deque<PendingRead2> pending_reads_; + base::circular_deque<PendingWrite2> pending_writes_; base::SequenceBound<ReadWriter> seqbnd_read_writer_; }; @@ -330,6 +361,10 @@ storage::AsyncFileUtil::EntryList entry_list, bool has_more); + void OnWrite2(uint64_t fuse_handle, + Write2Callback callback, + const fusebox_staging::Write2ResponseProto& response); + // Removes the entry (if present) for the given map key. void EraseFuseFileMapEntry(uint64_t fuse_handle); // Returns the fuse_handle that is the map key.
diff --git a/chrome/browser/ash/fusebox/fusebox_staging.proto b/chrome/browser/ash/fusebox/fusebox_staging.proto index fc96038a..38ad8d6c 100644 --- a/chrome/browser/ash/fusebox/fusebox_staging.proto +++ b/chrome/browser/ash/fusebox/fusebox_staging.proto
@@ -132,3 +132,15 @@ message RmDirResponseProto { optional int32 posix_error_code = 1; } + +// Write2 writes to a fuse_handle previously returned by Open2. + +message Write2RequestProto { + optional uint64 fuse_handle = 2; + optional int64 offset = 4; + optional bytes data = 5; +} + +message Write2ResponseProto { + optional int32 posix_error_code = 1; +}
diff --git a/chrome/browser/ash/input_method/input_method_settings.cc b/chrome/browser/ash/input_method/input_method_settings.cc index 09c2fedb..cd52eb27 100644 --- a/chrome/browser/ash/input_method/input_method_settings.cc +++ b/chrome/browser/ash/input_method/input_method_settings.cc
@@ -232,11 +232,10 @@ return settings; } -} // namespace - -mojom::InputMethodSettingsPtr CreateSettingsFromPrefs( +const base::Value::Dict& GetPrefsDictionaryForEngineId( const PrefService& prefs, - const std::string& engine_id) { + const std::string& engine_id, + const base::Value::Dict& fallback_dictionary) { // All input method settings are stored in a single pref whose value is a // dictionary. const base::Value::Dict& all_input_method_pref = @@ -244,19 +243,28 @@ // For each input method, the dictionary contains an entry, with the key being // a string that identifies the input method, and the value being a - // subdictionary with the specific settings for that input method. - // The subdictionary structure depends on the type of input method it's for. - // The subdictionary may be null if the user hasn't changed any settings for - // that input method. + // subdictionary with the specific settings for that input method. The + // subdictionary structure depends on the type of input method it's for. The + // subdictionary may be null if the user hasn't changed any settings for that + // input method. const base::Value::Dict* input_method_specific_pref_or_null = all_input_method_pref.FindDict(engine_id); // For convenience, pass an empty dictionary if there are no settings for this // input method yet. - base::Value::Dict empty_value; + return input_method_specific_pref_or_null + ? *input_method_specific_pref_or_null + : fallback_dictionary; +} + +} // namespace + +mojom::InputMethodSettingsPtr CreateSettingsFromPrefs( + const PrefService& prefs, + const std::string& engine_id) { + base::Value::Dict empty_dictionary; const auto& input_method_specific_pref = - input_method_specific_pref_or_null ? *input_method_specific_pref_or_null - : empty_value; + GetPrefsDictionaryForEngineId(prefs, engine_id, empty_dictionary); if (IsFstEngine(engine_id)) { return mojom::InputMethodSettings::NewLatinSettings(
diff --git a/chrome/browser/ash/login/oobe_quick_start/BUILD.gn b/chrome/browser/ash/login/oobe_quick_start/BUILD.gn index 8d50351..e8fe6a4e 100644 --- a/chrome/browser/ash/login/oobe_quick_start/BUILD.gn +++ b/chrome/browser/ash/login/oobe_quick_start/BUILD.gn
@@ -11,6 +11,9 @@ "connectivity", "//base", "//chrome/common:channel_info", + "//chromeos/ash/components/attestation:attestation", + "//chromeos/ash/components/dbus/attestation:attestation_proto", + "//components/account_id:account_id", "//components/endpoint_fetcher:endpoint_fetcher", "//components/qr_code_generator:qr_code_generator", "//components/version_info:channel", @@ -37,11 +40,16 @@ "connectivity:unit_tests", "//base", "//base/test:test_support", + "//chromeos/ash/components/attestation:test_support", + "//chromeos/ash/components/dbus/constants:constants", + "//components/account_id:account_id", "//google_apis:google_apis", "//google_apis/common:common", "//services/data_decoder/public/cpp:test_support", "//services/network:test_support", "//services/network/public/cpp:cpp", + "//testing/gmock", + "//testing/gtest", ] sources = [ "second_device_auth_broker_unittest.cc",
diff --git a/chrome/browser/ash/login/oobe_quick_start/second_device_auth_broker.cc b/chrome/browser/ash/login/oobe_quick_start/second_device_auth_broker.cc index aea44f00d..4e2fb30 100644 --- a/chrome/browser/ash/login/oobe_quick_start/second_device_auth_broker.cc +++ b/chrome/browser/ash/login/oobe_quick_start/second_device_auth_broker.cc
@@ -12,11 +12,15 @@ #include "base/check.h" #include "base/functional/bind.h" #include "base/functional/callback_forward.h" +#include "base/guid.h" #include "base/logging.h" #include "base/strings/stringprintf.h" #include "base/types/expected.h" #include "base/values.h" #include "chrome/common/channel_info.h" +#include "chromeos/ash/components/attestation/attestation_flow.h" +#include "chromeos/ash/components/dbus/attestation/keystore.pb.h" +#include "components/account_id/account_id.h" #include "components/endpoint_fetcher/endpoint_fetcher.h" #include "components/version_info/channel.h" #include "google_apis/common/api_error_codes.h" @@ -105,7 +109,7 @@ } void RunChallengeBytesCallback( - SecondDeviceAuthBroker::GetChallengeBytesCallback challenge_callback, + SecondDeviceAuthBroker::ChallengeBytesCallback challenge_callback, const std::string& challenge_bytes) { if (challenge_bytes.empty()) { std::move(challenge_callback) @@ -119,7 +123,7 @@ } void HandleGetChallengeBytesErrorResponse( - SecondDeviceAuthBroker::GetChallengeBytesCallback challenge_callback, + SecondDeviceAuthBroker::ChallengeBytesCallback challenge_callback, std::unique_ptr<EndpointResponse> response) { LOG(ERROR) << "Could not fetch challenge bytes. HTTP status code: " << response->http_status_code; @@ -160,19 +164,50 @@ } } +void RunAttestationCertificateCallback( + SecondDeviceAuthBroker::AttestationCertificateCallback callback, + attestation::AttestationStatus status, + const std::string& pem_certificate_chain) { + switch (status) { + case attestation::ATTESTATION_SUCCESS: + if (pem_certificate_chain.empty()) { + LOG(ERROR) << "Got an empty certificate chain with a success response " + "from attestation server"; + std::move(callback).Run(base::unexpected( + SecondDeviceAuthBroker::AttestationErrorType::kPermanentError)); + return; + } + std::move(callback).Run(base::ok(pem_certificate_chain)); + return; + case attestation::ATTESTATION_UNSPECIFIED_FAILURE: + // TODO(b/259021973): Is it safe to consider + // `ATTESTATION_UNSPECIFIED_FAILURE` transient? Check its side effects. + std::move(callback).Run(base::unexpected( + SecondDeviceAuthBroker::AttestationErrorType::kTransientError)); + return; + case attestation::ATTESTATION_SERVER_BAD_REQUEST_FAILURE: + std::move(callback).Run(base::unexpected( + SecondDeviceAuthBroker::AttestationErrorType::kPermanentError)); + return; + } +} + } // namespace SecondDeviceAuthBroker::SecondDeviceAuthBroker( - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, + std::unique_ptr<attestation::AttestationFlow> attestation_flow) : url_loader_factory_(std::move(url_loader_factory)), + attestation_(std::move(attestation_flow)), weak_ptr_factory_(this) { DCHECK(url_loader_factory_); + DCHECK(attestation_); } SecondDeviceAuthBroker::~SecondDeviceAuthBroker() = default; void SecondDeviceAuthBroker::GetChallengeBytes( - GetChallengeBytesCallback challenge_callback) { + ChallengeBytesCallback challenge_callback) { DCHECK(!endpoint_fetcher_) << "This class can handle only one request at a time"; @@ -196,7 +231,7 @@ } void SecondDeviceAuthBroker::OnChallengeBytesFetched( - GetChallengeBytesCallback challenge_callback, + ChallengeBytesCallback challenge_callback, std::unique_ptr<EndpointResponse> response) { DCHECK(endpoint_fetcher_) << "Received an unexpected callback for challenge bytes"; @@ -216,4 +251,26 @@ std::move(challenge_callback)))); } +void SecondDeviceAuthBroker::FetchAttestationCertificate( + const std::string& fido_credential_id, + AttestationCertificateCallback certificate_callback) { + // TODO(b/259021973): Figure out if we can use ECC keys where they are + // available. + ::attestation::DeviceSetupCertificateRequestMetadata profile_specific_data; + profile_specific_data.set_id(base::GenerateGUID()); + profile_specific_data.set_content_binding(fido_credential_id); + attestation_->GetCertificate( + /*certificate_profile=*/attestation::AttestationCertificateProfile:: + PROFILE_DEVICE_SETUP_CERTIFICATE, + /*account_id=*/EmptyAccountId(), /*request_origin=*/std::string(), + /*force_new_key=*/true, /*key_crypto_type=*/::attestation::KEY_TYPE_RSA, + /*key_name=*/std::string(), + /*profile_specific_data=*/ + absl::make_optional(attestation::AttestationFlow::CertProfileSpecificData( + profile_specific_data)), + /*callback=*/ + base::BindOnce(&RunAttestationCertificateCallback, + std::move(certificate_callback))); +} + } // namespace ash::quick_start
diff --git a/chrome/browser/ash/login/oobe_quick_start/second_device_auth_broker.h b/chrome/browser/ash/login/oobe_quick_start/second_device_auth_broker.h index c5cf03e..461b90f 100644 --- a/chrome/browser/ash/login/oobe_quick_start/second_device_auth_broker.h +++ b/chrome/browser/ash/login/oobe_quick_start/second_device_auth_broker.h
@@ -12,23 +12,30 @@ #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" #include "base/types/expected.h" +#include "chromeos/ash/components/attestation/attestation_flow.h" #include "components/endpoint_fetcher/endpoint_fetcher.h" class GoogleServiceAuthError; namespace network { class SharedURLLoaderFactory; -} +} // namespace network namespace ash::quick_start { class SecondDeviceAuthBroker { public: - using GetChallengeBytesCallback = base::OnceCallback<void( - const base::expected<std::string, GoogleServiceAuthError>&)>; + enum class AttestationErrorType { kTransientError, kPermanentError }; - explicit SecondDeviceAuthBroker( - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory); + using ChallengeBytesCallback = base::OnceCallback<void( + const base::expected<std::string, GoogleServiceAuthError>&)>; + using AttestationCertificateCallback = base::OnceCallback<void( + const base::expected<std::string, AttestationErrorType>&)>; + + // Constructs an instance of `SecondDeviceAuthBroker`. + SecondDeviceAuthBroker( + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, + std::unique_ptr<attestation::AttestationFlow> attestation_flow); SecondDeviceAuthBroker(const SecondDeviceAuthBroker&) = delete; SecondDeviceAuthBroker& operator=(const SecondDeviceAuthBroker&) = delete; ~SecondDeviceAuthBroker(); @@ -37,11 +44,20 @@ // service. // The callback is completed with either the challenge bytes - for successful // execution, or with a `GoogleServiceAuthError` - for a failed execution. - void GetChallengeBytes(GetChallengeBytesCallback challenge_callback); + void GetChallengeBytes(ChallengeBytesCallback challenge_callback); + + // Fetches a new Remote Attestation certificate - for proving device + // integrity. + // The callback is completed with either a PEM encoded certificate chain + // string, or with the type of error (`AttestationErrorType`) which occurred + // during attestation. + void FetchAttestationCertificate( + const std::string& fido_credential_id, + AttestationCertificateCallback certificate_callback); private: // Callback for handling challenge bytes response from Gaia. - void OnChallengeBytesFetched(GetChallengeBytesCallback challenge_callback, + void OnChallengeBytesFetched(ChallengeBytesCallback challenge_callback, std::unique_ptr<EndpointResponse> response); scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; @@ -49,6 +65,10 @@ // Used for fetching results from Gaia endpoints. std::unique_ptr<EndpointFetcher> endpoint_fetcher_ = nullptr; + // Used for interacting with Google's Privacy CA, for getting a Remote + // Attestation certificate. + std::unique_ptr<attestation::AttestationFlow> attestation_; + base::WeakPtrFactory<SecondDeviceAuthBroker> weak_ptr_factory_; };
diff --git a/chrome/browser/ash/login/oobe_quick_start/second_device_auth_broker_unittest.cc b/chrome/browser/ash/login/oobe_quick_start/second_device_auth_broker_unittest.cc index 063d86f..bfa07be74 100644 --- a/chrome/browser/ash/login/oobe_quick_start/second_device_auth_broker_unittest.cc +++ b/chrome/browser/ash/login/oobe_quick_start/second_device_auth_broker_unittest.cc
@@ -13,6 +13,10 @@ #include "base/test/bind.h" #include "base/test/task_environment.h" #include "base/types/expected.h" +#include "chromeos/ash/components/attestation/attestation_flow.h" +#include "chromeos/ash/components/attestation/mock_attestation_flow.h" +#include "chromeos/ash/components/dbus/constants/attestation_constants.h" +#include "components/account_id/account_id.h" #include "google_apis/gaia/google_service_auth_error.h" #include "net/http/http_status_code.h" #include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h" @@ -24,10 +28,16 @@ namespace ash::quick_start { +using ::testing::_; using ::testing::Eq; using ::testing::Gt; +using ::testing::Invoke; using ::testing::IsFalse; using ::testing::IsTrue; +using ::testing::Optional; +using ::testing::StrictMock; +using ::testing::VariantWith; +using ::testing::WithArg; namespace { @@ -49,13 +59,52 @@ "\"Not-a-base64-character()\"" "}" "}"; +constexpr char kFidoCredentialId[] = "fido_credential_id"; + +MATCHER_P(ProtoBufContentBindingEq, expected, "") { + return arg.content_binding() == expected; +} + +// This class simply delegates all API calls to its mock object. It is used for +// passing information from inside `SecondDeviceAuthBroker` to the mock object, +// without passing ownership of the mock object to `SecondDeviceAuthBroker`. +class MockAttestationFlowFacade : public attestation::MockAttestationFlow { + public: + explicit MockAttestationFlowFacade( + raw_ptr<attestation::MockAttestationFlow> mock_attestation_flow) + : mock_attestation_flow_(std::move(mock_attestation_flow)) {} + MockAttestationFlowFacade(const MockAttestationFlowFacade&) = delete; + MockAttestationFlowFacade& operator=(const MockAttestationFlowFacade&) = + delete; + ~MockAttestationFlowFacade() override = default; + + void GetCertificate( + attestation::AttestationCertificateProfile certificate_profile, + const AccountId& account_id, + const std::string& request_origin, + bool force_new_key, + ::attestation::KeyType key_crypto_type, + const std::string& key_name, + const absl::optional<CertProfileSpecificData>& profile_specific_data, + CertificateCallback callback) override { + mock_attestation_flow_->GetCertificate( + certificate_profile, account_id, request_origin, force_new_key, + key_crypto_type, key_name, profile_specific_data, std::move(callback)); + } + + private: + raw_ptr<attestation::MockAttestationFlow> mock_attestation_flow_; +}; } // namespace class SecondDeviceAuthBrokerTest : public ::testing::Test { public: SecondDeviceAuthBrokerTest() - : second_device_auth_broker_(test_factory_.GetSafeWeakWrapper()) {} + : second_device_auth_broker_(test_factory_.GetSafeWeakWrapper(), + std::make_unique<MockAttestationFlowFacade>( + &mock_attestation_flow_)) {} + SecondDeviceAuthBrokerTest(const SecondDeviceAuthBrokerTest&) = delete; SecondDeviceAuthBrokerTest& operator=(const SecondDeviceAuthBrokerTest&) = delete; @@ -65,16 +114,36 @@ base::expected<std::string, GoogleServiceAuthError> GetChallengeBytes() { base::expected<std::string, GoogleServiceAuthError> response; base::RunLoop run_loop; - base::OnceCallback<void( - const base::expected<std::string, GoogleServiceAuthError>&)> - callback = base::BindLambdaForTesting( + SecondDeviceAuthBroker::ChallengeBytesCallback callback = + base::BindLambdaForTesting( [&response, &run_loop]( const base::expected<std::string, GoogleServiceAuthError>& returned_response) -> void { response = returned_response; run_loop.Quit(); }); - second_device_auth_broker().GetChallengeBytes(std::move(callback)); + second_device_auth_broker_.GetChallengeBytes(std::move(callback)); + run_loop.Run(); + + return response; + } + + base::expected<std::string, SecondDeviceAuthBroker::AttestationErrorType> + FetchAttestationCertificate(const std::string& fido_credential_id) { + base::expected<std::string, SecondDeviceAuthBroker::AttestationErrorType> + response; + base::RunLoop run_loop; + SecondDeviceAuthBroker::AttestationCertificateCallback callback = + base::BindLambdaForTesting( + [&response, &run_loop]( + const base::expected< + std::string, SecondDeviceAuthBroker::AttestationErrorType>& + returned_response) -> void { + response = returned_response; + run_loop.Quit(); + }); + second_device_auth_broker_.FetchAttestationCertificate(fido_credential_id, + std::move(callback)); run_loop.Run(); return response; @@ -89,8 +158,8 @@ net::HTTP_UNAUTHORIZED); } - SecondDeviceAuthBroker& second_device_auth_broker() { - return second_device_auth_broker_; + attestation::MockAttestationFlow& mock_attestation_flow() { + return mock_attestation_flow_; } private: @@ -99,6 +168,7 @@ data_decoder::test::InProcessDataDecoder in_process_data_decoder_; network::TestURLLoaderFactory test_factory_; + StrictMock<attestation::MockAttestationFlow> mock_attestation_flow_; SecondDeviceAuthBroker second_device_auth_broker_; }; @@ -152,4 +222,89 @@ EXPECT_THAT(response->size(), Gt(0UL)); } +TEST_F( + SecondDeviceAuthBrokerTest, + FetchAttestationCertificateReturnsATransientErrorForUnspecifiedFailures) { + EXPECT_CALL( + mock_attestation_flow(), + GetCertificate( + /*certificate_profile=*/attestation::AttestationCertificateProfile:: + PROFILE_DEVICE_SETUP_CERTIFICATE, + /*account_id=*/EmptyAccountId(), /*request_origin=*/"", + /*force_new_key=*/_, /*key_crypto_type=*/_, /*key_name=*/_, + /*profile_specific_data=*/_, /*callback=*/_)) + .WillOnce(WithArg<7>( + Invoke([](attestation::AttestationFlow::CertificateCallback callback) + -> void { + std::move(callback).Run( + /*status=*/ash::attestation::AttestationStatus:: + ATTESTATION_UNSPECIFIED_FAILURE, + /*pem_certificate_chain=*/std::string()); + }))); + + base::expected<std::string, SecondDeviceAuthBroker::AttestationErrorType> + response = FetchAttestationCertificate(kFidoCredentialId); + ASSERT_THAT(response.has_value(), IsFalse()); + EXPECT_THAT( + response.error(), + Eq(SecondDeviceAuthBroker::AttestationErrorType::kTransientError)); +} + +TEST_F(SecondDeviceAuthBrokerTest, + FetchAttestationCertificateReturnsAPermanentErrorForBadRequests) { + EXPECT_CALL( + mock_attestation_flow(), + GetCertificate( + /*certificate_profile=*/attestation::AttestationCertificateProfile:: + PROFILE_DEVICE_SETUP_CERTIFICATE, + /*account_id=*/EmptyAccountId(), /*request_origin=*/"", + /*force_new_key=*/_, /*key_crypto_type=*/_, /*key_name=*/_, + /*profile_specific_data=*/_, /*callback=*/_)) + .WillOnce(WithArg<7>( + Invoke([](attestation::AttestationFlow::CertificateCallback callback) + -> void { + std::move(callback).Run( + /*status=*/ash::attestation::AttestationStatus:: + ATTESTATION_SERVER_BAD_REQUEST_FAILURE, + /*pem_certificate_chain=*/std::string()); + }))); + + base::expected<std::string, SecondDeviceAuthBroker::AttestationErrorType> + response = FetchAttestationCertificate(kFidoCredentialId); + ASSERT_THAT(response.has_value(), IsFalse()); + EXPECT_THAT( + response.error(), + Eq(SecondDeviceAuthBroker::AttestationErrorType::kPermanentError)); +} + +TEST_F(SecondDeviceAuthBrokerTest, + FetchAttestationCertificateReturnsACertificate) { + const std::string kCertificate = "fake_certificate"; + EXPECT_CALL( + mock_attestation_flow(), + GetCertificate( + /*certificate_profile=*/attestation::AttestationCertificateProfile:: + PROFILE_DEVICE_SETUP_CERTIFICATE, + /*account_id=*/EmptyAccountId(), /*request_origin=*/"", + /*force_new_key=*/_, /*key_crypto_type=*/_, /*key_name=*/_, + /*profile_specific_data=*/ + Optional( + VariantWith<::attestation::DeviceSetupCertificateRequestMetadata>( + ProtoBufContentBindingEq(kFidoCredentialId))), + /*callback*/ _)) + .WillOnce(WithArg< + 7>(Invoke([&kCertificate]( + attestation::AttestationFlow::CertificateCallback + callback) -> void { + std::move(callback).Run( + /*status=*/ash::attestation::AttestationStatus::ATTESTATION_SUCCESS, + /*pem_certificate_chain=*/kCertificate); + }))); + + base::expected<std::string, SecondDeviceAuthBroker::AttestationErrorType> + response = FetchAttestationCertificate(kFidoCredentialId); + ASSERT_THAT(response.has_value(), IsTrue()); + EXPECT_THAT(response.value(), Eq(kCertificate)); +} + } // namespace ash::quick_start
diff --git a/chrome/browser/ash/web_applications/files_internals_ui_delegate.cc b/chrome/browser/ash/web_applications/files_internals_ui_delegate.cc index a5974dd..85341b7 100644 --- a/chrome/browser/ash/web_applications/files_internals_ui_delegate.cc +++ b/chrome/browser/ash/web_applications/files_internals_ui_delegate.cc
@@ -55,3 +55,16 @@ file_manager::file_tasks::SetOfficeSetupComplete(profile, complete); } } + +bool ChromeFilesInternalsUIDelegate::GetAlwaysMoveOfficeFiles() const { + Profile* profile = Profile::FromWebUI(web_ui_); + return profile && file_manager::file_tasks::AlwaysMoveOfficeFiles(profile); +} + +void ChromeFilesInternalsUIDelegate::SetAlwaysMoveOfficeFiles( + bool always_move) { + Profile* profile = Profile::FromWebUI(web_ui_); + if (profile) { + file_manager::file_tasks::SetAlwaysMoveOfficeFiles(profile, always_move); + } +}
diff --git a/chrome/browser/ash/web_applications/files_internals_ui_delegate.h b/chrome/browser/ash/web_applications/files_internals_ui_delegate.h index 44e3b297e..0be68ac9 100644 --- a/chrome/browser/ash/web_applications/files_internals_ui_delegate.h +++ b/chrome/browser/ash/web_applications/files_internals_ui_delegate.h
@@ -30,6 +30,9 @@ bool GetOfficeSetupComplete() const override; void SetOfficeSetupComplete(bool complete) override; + bool GetAlwaysMoveOfficeFiles() const override; + void SetAlwaysMoveOfficeFiles(bool always_move) override; + private: raw_ptr<content::WebUI> web_ui_; // Owns |this|. };
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc index 496c41b..4a16890 100644 --- a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc +++ b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc
@@ -94,6 +94,17 @@ std::move(mock_tpm_challenge_key)); } + void SetMockTpmChallengerBadBase64Error() { + auto mock_tpm_challenge_key = + std::make_unique<NiceMock<ash::attestation::MockTpmChallengeKey>>(); + // Error text is "Challenge is not base64 encoded." + mock_tpm_challenge_key->EnableFakeError( + ash::attestation::TpmChallengeKeyResultCode::kChallengeBadBase64Error); + // transfer ownership inside factory + ash::attestation::TpmChallengeKeyFactory::SetForTesting( + std::move(mock_tpm_challenge_key)); + } + // This will be called by BrowserWithTestWindowTest::SetUp(); TestingProfile* CreateProfile() override { fake_user_manager_->AddUserWithAffiliation( @@ -216,6 +227,21 @@ EXPECT_EQ("response", response); } +TEST_F(EPKChallengeMachineKeyTest, BadChallengeThenErrorMessageReturned) { + SetMockTpmChallengerBadBase64Error(); + + base::Value allowlist(base::Value::Type::LIST); + allowlist.Append(extension_->id()); + prefs_->Set(prefs::kAttestationExtensionAllowlist, allowlist); + + base::Value value( + RunFunctionAndReturnError(func_.get(), CreateArgs(), browser())); + + EXPECT_EQ( + ash::attestation::TpmChallengeKeyResult::kChallengeBadBase64ErrorMsg, + value); +} + TEST_F(EPKChallengeMachineKeyTest, KeyNotRegisteredByDefault) { SetMockTpmChallenger(); @@ -266,7 +292,37 @@ scoped_refptr<EnterprisePlatformKeysChallengeUserKeyFunction> func_; }; -TEST_F(EPKChallengeUserKeyTest, ExtensionNotAllowed) { +TEST_F(EPKChallengeUserKeyTest, Success) { + SetMockTpmChallenger(); + + base::Value allowlist(base::Value::Type::LIST); + allowlist.Append(extension_->id()); + prefs_->Set(prefs::kAttestationExtensionAllowlist, allowlist); + + base::Value value( + RunFunctionAndReturnSingleResult(func_.get(), CreateArgs(), browser())); + + ASSERT_TRUE(value.is_blob()); + std::string response(value.GetBlob().begin(), value.GetBlob().end()); + EXPECT_EQ("response", response); +} + +TEST_F(EPKChallengeUserKeyTest, BadChallengeThenErrorMessageReturned) { + SetMockTpmChallengerBadBase64Error(); + + base::Value allowlist(base::Value::Type::LIST); + allowlist.Append(extension_->id()); + prefs_->Set(prefs::kAttestationExtensionAllowlist, allowlist); + + base::Value value( + RunFunctionAndReturnError(func_.get(), CreateArgs(), browser())); + + EXPECT_EQ( + ash::attestation::TpmChallengeKeyResult::kChallengeBadBase64ErrorMsg, + value); +} + +TEST_F(EPKChallengeUserKeyTest, ExtensionNotAllowedThenErrorMessageReturned) { base::ListValue empty_allowlist; prefs_->Set(prefs::kAttestationExtensionAllowlist, empty_allowlist);
diff --git a/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc b/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc index 0bb57d6b..fda585e1 100644 --- a/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc +++ b/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc
@@ -55,8 +55,6 @@ namespace ClearComposition = extensions::api::input_ime::ClearComposition; namespace OnCompositionBoundsChanged = extensions::api::input_method_private::OnCompositionBoundsChanged; -namespace NotifyImeMenuItemActivated = - extensions::api::input_method_private::NotifyImeMenuItemActivated; namespace OnScreenProjectionChanged = extensions::api::input_method_private::OnScreenProjectionChanged; namespace FinishComposingText = @@ -1327,31 +1325,6 @@ } ExtensionFunction::ResponseAction -InputMethodPrivateNotifyImeMenuItemActivatedFunction::Run() { - ash::input_method::InputMethodDescriptor current_input_method = - ash::input_method::InputMethodManager::Get() - ->GetActiveIMEState() - ->GetCurrentInputMethod(); - std::string active_extension_id = - ash::extension_ime_util::GetExtensionIDFromInputMethodID( - current_input_method.id()); - std::string error; - InputMethodEngine* engine = - GetEngineIfActive(Profile::FromBrowserContext(browser_context()), - active_extension_id, &error); - if (!engine) - return RespondNow(Error(InformativeError(error, static_function_name()))); - - std::unique_ptr<NotifyImeMenuItemActivated::Params> params( - NotifyImeMenuItemActivated::Params::Create(args())); - if (params->engine_id != engine->GetActiveComponentId()) - return RespondNow( - Error(InformativeError(kErrorEngineNotActive, static_function_name()))); - engine->PropertyActivate(params->name); - return RespondNow(NoArguments()); -} - -ExtensionFunction::ResponseAction InputMethodPrivateGetCompositionBoundsFunction::Run() { std::string error; InputMethodEngine* engine = GetEngineIfActive(
diff --git a/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.h b/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.h index a820debb..016ccbf3 100644 --- a/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.h +++ b/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.h
@@ -152,27 +152,6 @@ INPUTMETHODPRIVATE_FINISHCOMPOSINGTEXT) }; -class InputMethodPrivateNotifyImeMenuItemActivatedFunction - : public ExtensionFunction { - public: - InputMethodPrivateNotifyImeMenuItemActivatedFunction() = default; - - InputMethodPrivateNotifyImeMenuItemActivatedFunction( - const InputMethodPrivateNotifyImeMenuItemActivatedFunction&) = delete; - InputMethodPrivateNotifyImeMenuItemActivatedFunction& operator=( - const InputMethodPrivateNotifyImeMenuItemActivatedFunction&) = delete; - - protected: - ~InputMethodPrivateNotifyImeMenuItemActivatedFunction() override = default; - - // ExtensionFunction: - ResponseAction Run() override; - - private: - DECLARE_EXTENSION_FUNCTION("inputMethodPrivate.notifyImeMenuItemActivated", - INPUTMETHODPRIVATE_NOTIFYIMEMENUITEMACTIVATED) -}; - class InputMethodPrivateGetCompositionBoundsFunction : public ExtensionFunction { public:
diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/sort_ui/FeedOptionsView.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/sort_ui/FeedOptionsView.java index e7c85b1f..78f3262 100644 --- a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/sort_ui/FeedOptionsView.java +++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/sort_ui/FeedOptionsView.java
@@ -4,6 +4,9 @@ package org.chromium.chrome.browser.feed.sort_ui; +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; + import android.content.Context; import android.util.AttributeSet; import android.view.View; @@ -59,7 +62,14 @@ /** Expands this view to full height. */ private void expand() { - if (this.getParent() == null) return; + // If the view's parent is not shown, we want to set this view as VISIBLE without the + // animation, and reset the height if it was previously set by collapse() animation. + if (getParent() == null || !(((View) getParent()).isShown())) { + setVisibility(VISIBLE); + setLayoutParams(new LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT)); + return; + } + // Width is match_parent and height is wrap_content. int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec( ((ViewGroup) getParent()).getWidth(), View.MeasureSpec.EXACTLY); @@ -97,7 +107,13 @@ /** Collapses this view to 0 height and then marks it GONE. */ private void collapse() { - if (this.getParent() == null) return; + // If the view's parent is not shown, we want to set this view as GONE without the + // animation. + if (getParent() == null || !(((View) getParent()).isShown())) { + setVisibility(GONE); + return; + } + int initialHeight = getMeasuredHeight(); Animation animation = new Animation() {
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 2ebfcb2..0ca8280 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -325,24 +325,6 @@ "When enabled, manual fallback will be auto-triggered on form interaction " "in the case where autofill failed to fill a credit card form accurately."; -const char kAutofillCenterAligngedSuggestionsName[] = - "Center-aligned Autofill suggestions."; -const char kAutofillCenterAligngedSuggestionsDescription[] = - "When enabled, the Autofill suggestion popup will be aligned to the center " - "of the initiating field and not to its border."; - -const char kAutofillVisualImprovementsForSuggestionUiName[] = - "Visual improvements for the Autofill and Password Manager suggestion UI."; -const char kAutofillVisualImprovementsForSuggestionUiDescription[] = - "Non function changes that visually improve the suggestion UI used for " - "addresses, passswords and credit cards."; - -const char kAutofillTypeSpecificPopupWidthName[] = - "Type-specific width limits for the Autofill popup"; -const char kAutofillTypeSpecificPopupWidthDescription[] = - "Controls if different width limits are used for the popup that provides " - "Autofill suggestions, depending on the type of data that is filled."; - const char kAutofillEnableGetDetailsForEnrollParsingInUploadCardResponseName[] = "Enable parsing of the GetDetailsForEnrollResponseDetails in the " "UploadCardResponseDetails"; @@ -589,12 +571,6 @@ "Enables biometric" "re-authentication before password filling"; -const char kTouchToFillPasswordSubmissionName[] = - "Form submission in Touch-To-Fill"; -const char kTouchToFillPasswordSubmissionDescription[] = - "Enables automatic form submission after filling credentials with " - "Touch-To-Fill"; - const char kFastCheckoutName[] = "Fast Checkout"; const char kFastCheckoutDescription[] = "Enables Fast Checkout experiences in Chrome.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 04eee2b..f6158de 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -192,15 +192,6 @@ extern const char kAutofillAutoTriggerManualFallbackForCardsName[]; extern const char kAutofillAutoTriggerManualFallbackForCardsDescription[]; -extern const char kAutofillCenterAligngedSuggestionsName[]; -extern const char kAutofillCenterAligngedSuggestionsDescription[]; - -extern const char kAutofillVisualImprovementsForSuggestionUiName[]; -extern const char kAutofillVisualImprovementsForSuggestionUiDescription[]; - -extern const char kAutofillTypeSpecificPopupWidthName[]; -extern const char kAutofillTypeSpecificPopupWidthDescription[]; - extern const char kAutofillEnableGetDetailsForEnrollParsingInUploadCardResponseName[]; extern const char @@ -319,9 +310,6 @@ extern const char kBiometricReauthForPasswordFillingName[]; extern const char kBiometricReauthForPasswordFillingDescription[]; -extern const char kTouchToFillPasswordSubmissionName[]; -extern const char kTouchToFillPasswordSubmissionDescription[]; - extern const char kFastCheckoutName[]; extern const char kFastCheckoutDescription[];
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java index fd64bb8b..e91e9eb 100644 --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -313,7 +313,6 @@ public static final String EARLY_LIBRARY_LOAD = "EarlyLibraryLoad"; public static final String ENABLE_AUTOMATIC_SNOOZE = "EnableAutomaticSnooze"; public static final String ENABLE_PASSWORDS_ACCOUNT_STORAGE = "EnablePasswordsAccountStorage"; - public static final String ELASTIC_OVERSCROLL = "ElasticOverscroll"; public static final String EXPERIMENTS_FOR_AGSA = "ExperimentsForAgsa"; public static final String EXPLICIT_LANGUAGE_ASK = "ExplicitLanguageAsk"; public static final String EXPLORE_SITES = "ExploreSites"; @@ -655,7 +654,6 @@ public static final CachedFlag sDownloadsAutoResumptionNative = new CachedFlag(DOWNLOADS_AUTO_RESUMPTION_NATIVE, true); public static final CachedFlag sEarlyLibraryLoad = new CachedFlag(EARLY_LIBRARY_LOAD, true); - public static final CachedFlag sElasticOverscroll = new CachedFlag(ELASTIC_OVERSCROLL, true); public static final CachedFlag sExperimentsForAgsa = new CachedFlag(EXPERIMENTS_FOR_AGSA, true); public static final CachedFlag sFeedLoadingPlaceholder = new CachedFlag(FEED_LOADING_PLACEHOLDER, false);
diff --git a/chrome/browser/history/history_tab_helper_unittest.cc b/chrome/browser/history/history_tab_helper_unittest.cc index 35ef277..986393e 100644 --- a/chrome/browser/history/history_tab_helper_unittest.cc +++ b/chrome/browser/history/history_tab_helper_unittest.cc
@@ -471,11 +471,10 @@ {{"implementation_type", "mparch"}}); break; case MPArchType::kPrerender: - scoped_feature_list_.InitWithFeatures( - {blink::features::kPrerender2}, + scoped_feature_list_.InitAndDisableFeature( // Disable the memory requirement of Prerender2 so the test can run // on any bot. - {blink::features::kPrerender2MemoryControls}); + blink::features::kPrerender2MemoryControls); break; } }
diff --git a/chrome/browser/infobars/infobars_browsertest.cc b/chrome/browser/infobars/infobars_browsertest.cc index 979ae74..533e94e 100644 --- a/chrome/browser/infobars/infobars_browsertest.cc +++ b/chrome/browser/infobars/infobars_browsertest.cc
@@ -13,6 +13,7 @@ #include "build/build_config.h" #include "build/buildflag.h" #include "build/chromeos_buildflags.h" +#include "chrome/browser/buildflags.h" #include "chrome/browser/devtools/devtools_infobar_delegate.h" #include "chrome/browser/extensions/api/debugger/extension_dev_tools_infobar_delegate.h" #include "chrome/browser/extensions/api/messaging/incognito_connectability_infobar_delegate.h" @@ -65,7 +66,7 @@ #include "chrome/browser/ui/startup/default_browser_infobar_delegate.h" #endif -#if BUILDFLAG(IS_MAC) +#if BUILDFLAG(IS_MAC) && BUILDFLAG(ENABLE_UPDATER) #include "chrome/browser/ui/cocoa/keystone_infobar_delegate.h" #endif @@ -279,7 +280,7 @@ break; case IBD::KEYSTONE_PROMOTION_INFOBAR_DELEGATE_MAC: -#if BUILDFLAG(IS_MAC) +#if BUILDFLAG(IS_MAC) && BUILDFLAG(ENABLE_UPDATER) KeystonePromotionInfoBarDelegate::Create(GetWebContents()); #else ADD_FAILURE() << "This infobar is not supported on this OS."; @@ -410,7 +411,7 @@ ShowAndVerifyUi(); } -#if BUILDFLAG(IS_MAC) +#if BUILDFLAG(IS_MAC) && BUILDFLAG(ENABLE_UPDATER) IN_PROC_BROWSER_TEST_F(InfoBarUiTest, InvokeUi_keystone_promotion) { ShowAndVerifyUi(); }
diff --git a/chrome/browser/invalidation/profile_invalidation_provider_factory.cc b/chrome/browser/invalidation/profile_invalidation_provider_factory.cc index 5d1acce..98847c8 100644 --- a/chrome/browser/invalidation/profile_invalidation_provider_factory.cc +++ b/chrome/browser/invalidation/profile_invalidation_provider_factory.cc
@@ -17,7 +17,9 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/common/chrome_content_client.h" +#include "components/gcm_driver/gcm_driver.h" #include "components/gcm_driver/gcm_profile_service.h" +#include "components/gcm_driver/instance_id/instance_id_driver.h" #include "components/gcm_driver/instance_id/instance_id_profile_service.h" #include "components/invalidation/impl/fcm_invalidation_service.h" #include "components/invalidation/impl/fcm_network_handler.h"
diff --git a/chrome/browser/media/media_engagement_contents_observer_unittest.cc b/chrome/browser/media/media_engagement_contents_observer_unittest.cc index 766637e6..b083091 100644 --- a/chrome/browser/media/media_engagement_contents_observer_unittest.cc +++ b/chrome/browser/media/media_engagement_contents_observer_unittest.cc
@@ -1370,11 +1370,10 @@ : public MediaEngagementContentsObserverTest { public: MediaEngagementContentsObserverPrerenderTest() { - scoped_feature_list_.InitWithFeatures( - {blink::features::kPrerender2}, + scoped_feature_list_.InitAndDisableFeature( // Disable the memory requirement of Prerender2 so the test can run on // any bot. - {blink::features::kPrerender2MemoryControls}); + blink::features::kPrerender2MemoryControls); } ~MediaEngagementContentsObserverPrerenderTest() override = default;
diff --git a/chrome/browser/net/nss_service.cc b/chrome/browser/net/nss_service.cc index 78cd32e..bb67767f 100644 --- a/chrome/browser/net/nss_service.cc +++ b/chrome/browser/net/nss_service.cc
@@ -12,6 +12,7 @@ #include "base/task/sequenced_task_runner.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" +#include "net/cert/nss_cert_database.h" // Note: This file contains the platform-agnostic components of NssService; // platform-specific portions are implemented in the _linux.cc and
diff --git a/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.cc b/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.cc index a5827c8a..66d2177c 100644 --- a/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.cc +++ b/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.cc
@@ -35,7 +35,6 @@ void PageLoadMetricsObserverTestHarness::InitializeFeatureList() { scoped_feature_list_.InitWithFeaturesAndParameters( { - {blink::features::kPrerender2, {}}, {blink::features::kFencedFrames, {{"implementation_type", "mparch"}}}, }, {
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc index b80ba44..3db8618e 100644 --- a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc +++ b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
@@ -82,6 +82,7 @@ #include "content/public/common/content_paths.h" #include "content/public/common/content_switches.h" #include "content/public/common/referrer.h" +#include "content/public/common/result_codes.h" #include "content/public/test/back_forward_cache_util.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" @@ -99,6 +100,7 @@ #include "services/network/public/cpp/features.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/chrome_debug_urls.h" #include "third_party/blink/public/common/features.h" #include "third_party/blink/public/common/user_agent/user_agent_metadata.h" #include "third_party/blink/public/mojom/use_counter/metrics/css_property_id.mojom.h" @@ -3317,7 +3319,7 @@ ASSERT_EQ(all_frames_value, main_frame_value); } -class PageLoadMetricsBrowserTestDiscardedPage +class PageLoadMetricsBrowserTestTerminatedPage : public PageLoadMetricsBrowserTest { protected: void SetUpOnMainThread() override { @@ -3400,7 +3402,7 @@ } }; -IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTestDiscardedPage, +IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTestTerminatedPage, UkmIsRecordedForDiscardedForegroundTabPage) { // Open a new foreground tab and navigate. The new tab would be of index 1 // which would be used below in verifying the tab is discarded. @@ -3424,7 +3426,7 @@ lcp_time, 10); } -IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTestDiscardedPage, +IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTestTerminatedPage, UkmIsRecordedForDiscardedBackgroundTabPage) { // Open a new foreground tab and navigate. content::WebContents* contents = OpenTabAndNavigate(); @@ -3452,6 +3454,80 @@ lcp_time, 10); } +// This test is to verify page load metrics are recorded in case when the +// render process is shut down. +IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTestTerminatedPage, + UkmIsRecordedWhenRenderProcessShutsDown) { + content::WebContents* contents = OpenTabAndNavigate(); + + // Wait for LCP emission and observation. + double lcp_time = GetLCPTimeFromEmittedLCPEntry(contents); + content::RenderProcessHost* process = RenderFrameHost()->GetProcess(); + + // Shut down render process. + content::RenderProcessHostWatcher crash_observer( + process, content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); + EXPECT_TRUE(process->Shutdown(content::RESULT_CODE_KILLED)); + crash_observer.Wait(); + EXPECT_FALSE(RenderFrameHost()->IsRenderFrameLive()); + + // Verify page load metric is recorded. + EXPECT_NEAR( + GetUKMPageLoadMetric( + PageLoad::kPaintTiming_NavigationToLargestContentfulPaint2Name), + lcp_time, 10); +} + +// This class is used to verify page load metrics are recorded in case of +// crashes of different kinds. These crashes are simulated by navigating to the +// chrome debug urls. +class PageLoadMetricsBrowserTestCrashedPage + : public PageLoadMetricsBrowserTestTerminatedPage, + public ::testing::WithParamInterface<const char*> {}; + +IN_PROC_BROWSER_TEST_P(PageLoadMetricsBrowserTestCrashedPage, + UkmIsRecordedForCrashedTabPage) { + // Open a new foreground tab and navigate. + content::WebContents* contents = OpenTabAndNavigate(); + + // The back/forward cache is disabled because page load metrics can also be + // recorded when entering into the bfcache. We want to test that page load + // metrics are recorded via the PageLoadTracker destructor which is called in + // all crash cases. + content::DisableBackForwardCacheForTesting( + contents, content::BackForwardCache::TEST_REQUIRES_NO_CACHING); + + // Wait for LCP emission and observation. This is to ensure there is an LCP + // entry to report at the time of killing the page. + double lcp_time = GetLCPTimeFromEmittedLCPEntry(contents); + + // Kill the page. + content::ScopedAllowRendererCrashes scoped_allow_renderer_crashes; + EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL(GetParam()))); + + // Page being crashed is only verifiable in these crashes. + if (GetParam() == blink::kChromeUIKillURL || + GetParam() == blink::kChromeUICrashURL) + EXPECT_TRUE( + browser()->tab_strip_model()->GetActiveWebContents()->IsCrashed()); + + // Verify page load metric is recorded. + EXPECT_NEAR( + GetUKMPageLoadMetric( + PageLoad::kPaintTiming_NavigationToLargestContentfulPaint2Name), + lcp_time, 10); +} + +INSTANTIATE_TEST_SUITE_P( + CrashCases, + PageLoadMetricsBrowserTestCrashedPage, + testing::ValuesIn({blink::kChromeUIKillURL, blink::kChromeUICrashURL, + blink::kChromeUIGpuCrashURL, + blink::kChromeUIBrowserCrashURL, + blink::kChromeUIMemoryExhaustURL, + blink::kChromeUINetworkErrorURL, + blink::kChromeUIProcessInternalsURL})); + // Test is flaky. https://crbug.com/1260953 #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX) || \ BUILDFLAG(IS_WIN) @@ -3759,9 +3835,6 @@ // is re-enabled, it should be updated to use a different mechanism. PageLoadMetricsBrowserTest::SetUpCommandLine(command_line); } - - private: - base::test::ScopedFeatureList scoped_feature_list_; }; // Flaky. See https://crbug.com/1224780. @@ -3837,9 +3910,7 @@ PrerenderPageLoadMetricsBrowserTest() : prerender_helper_(base::BindRepeating( &PrerenderPageLoadMetricsBrowserTest::web_contents, - base::Unretained(this))) { - feature_list_.InitAndEnableFeature(blink::features::kPrerender2); - } + base::Unretained(this))) {} void SetUp() override { prerender_helper_.SetUp(embedded_test_server()); @@ -3848,7 +3919,6 @@ protected: content::test::PrerenderTestHelper prerender_helper_; - base::test::ScopedFeatureList feature_list_; }; IN_PROC_BROWSER_TEST_F(PrerenderPageLoadMetricsBrowserTest, PrerenderEvent) {
diff --git a/chrome/browser/platform_util_linux.cc b/chrome/browser/platform_util_linux.cc index de23908..90bf7b59 100644 --- a/chrome/browser/platform_util_linux.cc +++ b/chrome/browser/platform_util_linux.cc
@@ -24,6 +24,7 @@ #include "base/threading/scoped_blocking_call.h" #include "chrome/browser/lifetime/termination_notification.h" #include "chrome/browser/platform_util_internal.h" +#include "chrome/browser/profiles/profile.h" // This file gets pulled in in Chromecast builds, which causes "gn check" to // complain as Chromecast doesn't use (or depend on) //components/dbus. // TODO(crbug.com/1215474): Eliminate //chrome being visible in the GN structure
diff --git a/chrome/browser/policy/chrome_browser_cloud_management_controller_desktop.cc b/chrome/browser/policy/chrome_browser_cloud_management_controller_desktop.cc index a97257e..3f03198c 100644 --- a/chrome/browser/policy/chrome_browser_cloud_management_controller_desktop.cc +++ b/chrome/browser/policy/chrome_browser_cloud_management_controller_desktop.cc
@@ -26,6 +26,7 @@ #include "chrome/browser/policy/cloud/remote_commands_invalidator_impl.h" #include "chrome/common/chrome_features.h" #include "chrome/common/chrome_paths.h" +#include "components/gcm_driver/gcm_driver.h" #include "components/gcm_driver/instance_id/instance_id_driver.h" #include "components/invalidation/impl/fcm_invalidation_service.h" #include "components/invalidation/impl/fcm_network_handler.h"
diff --git a/chrome/browser/preloading/prerender/prerender_omnibox_ui_browsertest.cc b/chrome/browser/preloading/prerender/prerender_omnibox_ui_browsertest.cc index ccaf7c8..2b35343 100644 --- a/chrome/browser/preloading/prerender/prerender_omnibox_ui_browsertest.cc +++ b/chrome/browser/preloading/prerender/prerender_omnibox_ui_browsertest.cc
@@ -500,8 +500,7 @@ public: PrerenderPreloaderHoldbackBrowserTest() { feature_list_.InitWithFeatures( - /*enabled_features=*/{blink::features::kPrerender2, - features::kOmniboxTriggerForPrerender2, + /*enabled_features=*/{features::kOmniboxTriggerForPrerender2, features::kPrerender2Holdback}, /* disabled_features=*/{}); }
diff --git a/chrome/browser/push_messaging/push_messaging_service_impl.cc b/chrome/browser/push_messaging/push_messaging_service_impl.cc index a0f5d82..680a1858 100644 --- a/chrome/browser/push_messaging/push_messaging_service_impl.cc +++ b/chrome/browser/push_messaging/push_messaging_service_impl.cc
@@ -64,6 +64,7 @@ #include "content/public/common/content_features.h" #include "content/public/common/content_switches.h" #include "third_party/blink/public/common/permissions/permission_utils.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" #include "third_party/blink/public/mojom/devtools/console_message.mojom.h" #include "third_party/blink/public/mojom/permissions/permission_status.mojom.h" #include "third_party/blink/public/mojom/push_messaging/push_messaging_status.mojom.h" @@ -179,9 +180,10 @@ else if (was_encrypted) event_metadata["Payload"] = payload; + url::Origin origin = url::Origin::Create(app_identifier.origin()); devtools_context->LogBackgroundServiceEvent( app_identifier.service_worker_registration_id(), - url::Origin::Create(app_identifier.origin()), + blink::StorageKey(origin), content::DevToolsBackgroundService::kPushMessaging, "Push message received" /* event_name */, message_id, event_metadata); } @@ -723,12 +725,13 @@ if (app_identifier.is_null()) return; + url::Origin origin = url::Origin::Create(app_identifier.origin()); if (auto* devtools_context = GetDevToolsContext(app_identifier.origin())) { std::stringstream ss; ss << unsubscribe_reason; devtools_context->LogBackgroundServiceEvent( app_identifier.service_worker_registration_id(), - url::Origin::Create(app_identifier.origin()), + blink::StorageKey(origin), content::DevToolsBackgroundService::kPushMessaging, "Unsubscribed due to error" /* event_name */, message.message_id, {{"Reason", ss.str()}}); @@ -793,10 +796,11 @@ if (app_identifier.is_null() || !did_show_generic_notification) return; + url::Origin origin = url::Origin::Create(app_identifier.origin()); if (auto* devtools_context = GetDevToolsContext(app_identifier.origin())) { devtools_context->LogBackgroundServiceEvent( app_identifier.service_worker_registration_id(), - url::Origin::Create(app_identifier.origin()), + blink::StorageKey(origin), content::DevToolsBackgroundService::kPushMessaging, "Generic notification shown" /* event_name */, push_message_id, {} /* event_metadata */);
diff --git a/chrome/browser/resources/chromeos/cloud_upload/BUILD.gn b/chrome/browser/resources/chromeos/cloud_upload/BUILD.gn index 0b7026e..05ff935 100644 --- a/chrome/browser/resources/chromeos/cloud_upload/BUILD.gn +++ b/chrome/browser/resources/chromeos/cloud_upload/BUILD.gn
@@ -20,6 +20,7 @@ "base_setup_page.ts", "drive_upload_page.ts", "file_handler_page.ts", + "move_confirmation_page.ts", "office_pwa_install_page.ts", "one_drive_upload_page.ts", "sign_in_page.ts",
diff --git a/chrome/browser/resources/chromeos/cloud_upload/drive_upload_page.ts b/chrome/browser/resources/chromeos/cloud_upload/drive_upload_page.ts index b6f8502b..a88499e 100644 --- a/chrome/browser/resources/chromeos/cloud_upload/drive_upload_page.ts +++ b/chrome/browser/resources/chromeos/cloud_upload/drive_upload_page.ts
@@ -35,7 +35,8 @@ } private onContinueButtonClick(): void { - this.proxy.handler.respondAndClose(UserAction.kUploadToGoogleDrive); + this.proxy.handler.respondAndClose( + UserAction.kConfirmOrUploadToGoogleDrive); } private onCancelButtonClick(): void {
diff --git a/chrome/browser/resources/chromeos/cloud_upload/main.ts b/chrome/browser/resources/chromeos/cloud_upload/main.ts index 6db2907..d7916d0 100644 --- a/chrome/browser/resources/chromeos/cloud_upload/main.ts +++ b/chrome/browser/resources/chromeos/cloud_upload/main.ts
@@ -10,6 +10,7 @@ import {DialogPage} from './cloud_upload.mojom-webui.js'; import {CloudUploadBrowserProxy} from './cloud_upload_browser_proxy.js'; +import {CloudProvider, MoveConfirmationPageElement} from './move_confirmation_page.js'; const dialogArgs = await CloudUploadBrowserProxy.getInstance().handler.getDialogArgs(); @@ -28,4 +29,16 @@ document.body.append(document.createElement('drive-upload-page')); break; } + case DialogPage.kMoveConfirmationOneDrive: { + const movePage = new MoveConfirmationPageElement(); + movePage.setCloudProvider(CloudProvider.ONE_DRIVE); + document.body.append(movePage); + break; + } + case DialogPage.kMoveConfirmationGoogleDrive: { + const movePage = new MoveConfirmationPageElement(); + movePage.setCloudProvider(CloudProvider.GOOGLE_DRIVE); + document.body.append(movePage); + break; + } } \ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/cloud_upload/move_confirmation_page.html b/chrome/browser/resources/chromeos/cloud_upload/move_confirmation_page.html new file mode 100644 index 0000000..991ce001 --- /dev/null +++ b/chrome/browser/resources/chromeos/cloud_upload/move_confirmation_page.html
@@ -0,0 +1,53 @@ +<style> + :host { + box-sizing: border-box; + display: flex; + flex-direction: column; + padding: 24px; + width: 448px; + } + + /* TODO(petermarshall): Possibly change font based on the specs */ + .title { + color: var(--cros-text-color-primary); + font: var(--cros-display-7-font); + } + + .normal-text { + color: var(--cros-text-color-secondary); + font: var(--cros-body-1-font); + margin-block-start: 16px; + } + + cr-checkbox { + margin-block-end: 2px; + margin-block-start: 18px; + } + + .checkbox-text { + color: var(--cros-text-color-secondary); + font: var(--cros-body-1-font); + } + + #button-container { + display: flex; + justify-content: flex-end; + } +</style> + +<!-- TODO(b/258071752): Use localized strings --> +<div class="title"> + Move file to <span id="provider-name"></span> to open +</div> +<div class="normal-text"> + The <span id="app-name"></span> app requires files to be in + <span id="provider-short-name"></span>. We can move your files + whenever you chose to open them. +</div> +<cr-checkbox id="always-move-checkbox"> + <p class="checkbox-text">Do this automatically next time</p> +</cr-checkbox> +<div id="button-container"> + <cr-button class="cancel-button">$i18n{cancel}</cr-button> + <cr-button class="action-button">Move & open file</cr-button> +</div> \ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/cloud_upload/move_confirmation_page.ts b/chrome/browser/resources/chromeos/cloud_upload/move_confirmation_page.ts new file mode 100644 index 0000000..faed50a8 --- /dev/null +++ b/chrome/browser/resources/chromeos/cloud_upload/move_confirmation_page.ts
@@ -0,0 +1,87 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'chrome://resources/cr_elements/cr_button/cr_button.js'; +import 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.js'; + +import {UserAction} from './cloud_upload.mojom-webui.js'; +import {CloudUploadBrowserProxy} from './cloud_upload_browser_proxy.js'; +import {getTemplate} from './move_confirmation_page.html.js'; +import type {CrCheckboxElement} from 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.js'; + +export enum CloudProvider { + GOOGLE_DRIVE, + ONE_DRIVE, +} + +/** + * The MoveConfirmationPageElement represents the dialog page shown when the + * user opens a file that needs to be moved first, and they haven't yet decided + * to always move files. + */ +export class MoveConfirmationPageElement extends HTMLElement { + private proxy: CloudUploadBrowserProxy = + CloudUploadBrowserProxy.getInstance(); + private cloudProvider: CloudProvider|undefined; + + constructor() { + super(); + + const shadowRoot = this.attachShadow({mode: 'open'}); + + shadowRoot.innerHTML = getTemplate(); + const moveButton = shadowRoot.querySelector<HTMLElement>('.action-button')!; + const cancelButton = + shadowRoot.querySelector<HTMLElement>('.cancel-button')!; + + moveButton.addEventListener('click', () => this.onMoveButtonClick()); + cancelButton.addEventListener('click', () => this.onCancelButtonClick()); + } + + private getProviderText(cloudProvider: CloudProvider) { + if (cloudProvider === CloudProvider.ONE_DRIVE) { + return { + name: 'Microsoft OneDrive', + appName: 'Microsoft 365', + shortName: 'OneDrive', + }; + } + // TODO(b/260141250): Display Slides or Sheets when appropriate instead? + return {name: 'Google Drive', appName: 'Google Docs', shortName: 'Drive'}; + } + + setCloudProvider(cloudProvider: CloudProvider) { + this.cloudProvider = cloudProvider; + + const {name, appName, shortName} = this.getProviderText(this.cloudProvider); + this.shadowRoot!.getElementById('provider-name')!.innerText = name; + this.shadowRoot!.getElementById('app-name')!.innerText = appName; + this.shadowRoot!.getElementById('provider-short-name')!.innerText = + shortName; + } + + private onMoveButtonClick(): void { + const checkbox = this.shadowRoot!.querySelector<CrCheckboxElement>( + '#always-move-checkbox')!; + this.proxy.handler.setAlwaysMoveOfficeFiles(checkbox.checked); + + if (this.cloudProvider === CloudProvider.ONE_DRIVE) { + this.proxy.handler.respondAndClose(UserAction.kUploadToOneDrive); + } else { + this.proxy.handler.respondAndClose(UserAction.kUploadToGoogleDrive); + } + } + + private onCancelButtonClick(): void { + this.proxy.handler.respondAndClose(UserAction.kCancel); + } +} + +declare global { + interface HTMLElementTagNameMap { + 'move-confirmation-page': MoveConfirmationPageElement; + } +} + +customElements.define('move-confirmation-page', MoveConfirmationPageElement); \ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/cloud_upload/one_drive_upload_page.ts b/chrome/browser/resources/chromeos/cloud_upload/one_drive_upload_page.ts index c38dcdf8..12c0444 100644 --- a/chrome/browser/resources/chromeos/cloud_upload/one_drive_upload_page.ts +++ b/chrome/browser/resources/chromeos/cloud_upload/one_drive_upload_page.ts
@@ -61,7 +61,7 @@ } private onUploadButtonClick(): void { - this.proxy.handler.respondAndClose(UserAction.kUploadToOneDrive); + this.proxy.handler.respondAndClose(UserAction.kConfirmOrUploadToOneDrive); } private onCancelButtonClick(): void {
diff --git a/chrome/browser/resources/chromeos/drive_internals.html b/chrome/browser/resources/chromeos/drive_internals.html index ca6b2456..8ac22fe 100644 --- a/chrome/browser/resources/chromeos/drive_internals.html +++ b/chrome/browser/resources/chromeos/drive_internals.html
@@ -107,6 +107,14 @@ </table> </section> + <section id="bulk-pinning-section" hidden> + <h2>Bulk Pinning</h2> + <label> + Enable Bulk Pinning + <input type="checkbox" id="bulk-pinning-toggle"> + </label> + </section> + <section id="delta-update-status-section" hidden> <h2>Delta Update Status</h2> <table>
diff --git a/chrome/browser/resources/chromeos/drive_internals.js b/chrome/browser/resources/chromeos/drive_internals.js index ec9908e..e6ab44f 100644 --- a/chrome/browser/resources/chromeos/drive_internals.js +++ b/chrome/browser/resources/chromeos/drive_internals.js
@@ -100,6 +100,10 @@ $('mirroring-toggle').checked = enabled; } +function updateBulkPinning(enabled) { + $('bulk-pinning-toggle').checked = enabled; +} + function updateStartupArguments(args) { $('startup-arguments-input').value = args; } @@ -365,6 +369,10 @@ chrome.send('setMirroringEnabled', [e.target.checked]); }); + $('bulk-pinning-toggle').addEventListener('change', function(e) { + chrome.send('setBulkPinningEnabled', [e.target.checked]); + }); + $('startup-arguments-form').addEventListener('submit', function(e) { e.preventDefault(); $('arguments-status-text').textContent = 'applying...';
diff --git a/chrome/browser/resources/chromeos/login/BUILD.gn b/chrome/browser/resources/chromeos/login/BUILD.gn index 9f10a01..4cd118b 100644 --- a/chrome/browser/resources/chromeos/login/BUILD.gn +++ b/chrome/browser/resources/chromeos/login/BUILD.gn
@@ -215,7 +215,6 @@ "components/web_view_helper.m.js", "components/web_view_loader.m.js", "screens/common/family_link_notice.m.js", - "screens/common/guest_tos.m.js", "screens/common/hw_data_collection.m.js", "screens/common/smart_privacy_protection.m.js", "screens/common/sync_consent.m.js", @@ -271,6 +270,7 @@ "screens/common/fingerprint_setup.js", "screens/common/gaia_signin.js", "screens/common/gesture_navigation.js", + "screens/common/guest_tos.js", "screens/common/local_state_error.js", "screens/common/managed_terms_of_service.js", "screens/common/marketing_opt_in.js",
diff --git a/chrome/browser/resources/chromeos/login/screens.js b/chrome/browser/resources/chromeos/login/screens.js index aff3ace0..2c7c65b0c 100644 --- a/chrome/browser/resources/chromeos/login/screens.js +++ b/chrome/browser/resources/chromeos/login/screens.js
@@ -21,7 +21,7 @@ import './screens/common/fingerprint_setup.js'; import './screens/common/gaia_signin.js'; import './screens/common/gesture_navigation.js'; -import './screens/common/guest_tos.m.js'; +import './screens/common/guest_tos.js'; import './screens/common/hw_data_collection.m.js'; import './screens/common/local_state_error.js'; import './screens/common/managed_terms_of_service.js';
diff --git a/chrome/browser/resources/chromeos/login/screens/common/BUILD.gn b/chrome/browser/resources/chromeos/login/screens/common/BUILD.gn index a180498..859bd12 100644 --- a/chrome/browser/resources/chromeos/login/screens/common/BUILD.gn +++ b/chrome/browser/resources/chromeos/login/screens/common/BUILD.gn
@@ -14,7 +14,6 @@ group("polymer3_elements") { public_deps = [ ":family_link_notice_module", - ":guest_tos_module", ":hw_data_collection_module", ":smart_privacy_protection_module", ":sync_consent_module", @@ -54,7 +53,7 @@ ":fingerprint_setup", ":gaia_signin", ":gesture_navigation", - ":guest_tos.m", + ":guest_tos", ":hw_data_collection.m", ":local_state_error", ":managed_terms_of_service", @@ -294,8 +293,8 @@ extra_deps = [ ":web_components" ] } -js_library("guest_tos.m") { - sources = [ "$root_gen_dir/chrome/browser/resources/chromeos/login/screens/common/guest_tos.m.js" ] +js_library("guest_tos") { + sources = [ "$root_gen_dir/chrome/browser/resources/chromeos/login/screens/common/guest_tos.js" ] deps = [ "../..:display_manager.m", "../../components:web_view_helper.m", @@ -311,7 +310,7 @@ "../../components/dialogs:oobe_modal_dialog.m", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", ] - extra_deps = [ ":guest_tos_module" ] + extra_deps = [ ":web_components" ] externs_list = [ "$externs_path/chrome_extensions.js", "$externs_path/webview_tag.js", @@ -685,15 +684,6 @@ namespace_rewrites = oobe_namespace_rewrites } -polymer_modulizer("guest_tos") { - js_file = "guest_tos.js" - html_file = "guest_tos.html" - html_type = "dom-module" - auto_imports = oobe_auto_imports - migrated_imports = oobe_migrated_imports - namespace_rewrites = oobe_namespace_rewrites -} - polymer_modulizer("hw_data_collection") { js_file = "hw_data_collection.js" html_file = "hw_data_collection.html" @@ -737,6 +727,7 @@ "fingerprint_setup.js", "gaia_signin.js", "gesture_navigation.js", + "guest_tos.js", "local_state_error.js", "managed_terms_of_service.js", "marketing_opt_in.js",
diff --git a/chrome/browser/resources/chromeos/login/screens/common/guest_tos.html b/chrome/browser/resources/chromeos/login/screens/common/guest_tos.html index 6aafcbb..67f8bef 100644 --- a/chrome/browser/resources/chromeos/login/screens/common/guest_tos.html +++ b/chrome/browser/resources/chromeos/login/screens/common/guest_tos.html
@@ -4,143 +4,115 @@ found in the LICENSE file. --> -<link rel="import" href="chrome://resources/html/polymer.html"> +<style include="oobe-dialog-host-styles"> + #termsTitle { + color: var(--google-grey-900); + font-family: var(--oobe-header-font-family); + font-size: 18px; + font-weight: var(--oobe-header-font-weight); + line-height: 24px; + margin-bottom: 4px; + } -<link rel="import" href="chrome://resources/cr_elements/cr_shared_style.css.html"> -<link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html"> -<link rel="import" href="chrome://resources/html/action_link.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> + .tos-webview { + display: flex; + height: 470px; + } +</style> -<link rel="import" href="../../components/behaviors/login_screen_behavior.html"> -<link rel="import" href="../../components/behaviors/multi_step_behavior.html"> -<link rel="import" href="../../components/behaviors/oobe_i18n_behavior.html"> -<link rel="import" href="../../components/buttons/oobe_back_button.html"> -<link rel="import" href="../../components/buttons/oobe_next_button.html"> -<link rel="import" href="../../components/buttons/oobe_text_button.html"> -<link rel="import" href="../../components/common_styles/common_styles.html"> -<link rel="import" href="../../components/common_styles/oobe_dialog_host_styles.html"> -<link rel="import" href="../../components/display_manager_types.html"> -<link rel="import" href="../../components/oobe_icons.html"> -<link rel="import" href="../../components/web_view_loader.html"> -<link rel="import" href="../../components/web_view_helper.html"> -<link rel="import" href="../../components/dialogs/oobe_adaptive_dialog.html"> -<link rel="import" href="../../components/dialogs/oobe_loading_dialog.html"> -<link rel="import" href="../../components/dialogs/oobe_modal_dialog.html"> +<!-- LOADING DIALOG --> +<oobe-loading-dialog id="loading" for-step="loading" role="dialog" + title-key="guestTosLoading" + aria-label$="[[i18nDynamic(locale, 'guestTosLoading')]]"> + <iron-icon slot="icon" icon="oobe-32:googleg"></iron-icon> +</oobe-loading-dialog> -<dom-module id="guest-tos-element"> - <template> - <style include="oobe-dialog-host-styles"> - #termsTitle { - color: var(--google-grey-900); - font-family: var(--oobe-header-font-family); - font-size: 18px; - font-weight: var(--oobe-header-font-weight); - line-height: 24px; - margin-bottom: 4px; - } - - .tos-webview { - display: flex; - height: 470px; - } - </style> - - <!-- LOADING DIALOG --> - <oobe-loading-dialog id="loading" for-step="loading" role="dialog" - title-key="guestTosLoading" - aria-label$="[[i18nDynamic(locale, 'guestTosLoading')]]"> - <iron-icon slot="icon" icon="oobe-32:googleg"></iron-icon> - </oobe-loading-dialog> - - <!-- Google EULA Dialog --> - <oobe-adaptive-dialog id="googleEulaDialog" for-step="google-eula" - role="dialog" - aria-label$="[[i18nDynamic(locale, 'guestTosGoogleEulaTitle')]]"> - <iron-icon slot="icon" icon="oobe-32:googleg"></iron-icon> - <h1 slot="title"> - [[i18nDynamic(locale, 'guestTosGoogleEulaTitle')]] - </h1> - <div slot="content" class="flex layout vertical"> - <webview id="guestTosGoogleEulaWebview" role="document" - class="oobe-tos-webview tos-webview" - on-contentload="onGoogleEulaContentLoad_"> - </webview> - </div> - <div slot="bottom-buttons"> - <oobe-text-button id="googleEulaOkButton" - class="focus-on-show" inverse on-click="onTermsStepOkClick_" - text-key="guestTosOk"></oobe-text-button> - </div> - </oobe-adaptive-dialog> - - <!-- CrOS EULA Dialog --> - <oobe-adaptive-dialog id="crosEulaDialog" for-step="cros-eula" +<!-- Google EULA Dialog --> +<oobe-adaptive-dialog id="googleEulaDialog" for-step="google-eula" role="dialog" - aria-label$="[[i18nDynamic(locale, 'guestTosCrosEulaTitle')]]"> - <iron-icon slot="icon" icon="oobe-32:googleg"></iron-icon> - <h1 slot="title"> - [[i18nDynamic(locale, 'guestTosCrosEulaTitle')]] - </h1> - <div slot="content" class="flex layout vertical"> - <webview id="guestTosCrosEulaWebview" role="document" - class="oobe-tos-webview tos-webview"> - </webview> - </div> - <div slot="bottom-buttons"> - <oobe-text-button id="crosEulaOkButton" - class="focus-on-show" inverse on-click="onTermsStepOkClick_" - text-key="guestTosOk"></oobe-text-button> - </div> - </oobe-adaptive-dialog> + aria-label$="[[i18nDynamic(locale, 'guestTosGoogleEulaTitle')]]"> + <iron-icon slot="icon" icon="oobe-32:googleg"></iron-icon> + <h1 slot="title"> + [[i18nDynamic(locale, 'guestTosGoogleEulaTitle')]] + </h1> + <div slot="content" class="flex layout vertical"> + <webview id="guestTosGoogleEulaWebview" role="document" + class="oobe-tos-webview tos-webview" + on-contentload="onGoogleEulaContentLoad_"> + </webview> + </div> + <div slot="bottom-buttons"> + <oobe-text-button id="googleEulaOkButton" + class="focus-on-show" inverse on-click="onTermsStepOkClick_" + text-key="guestTosOk"></oobe-text-button> + </div> +</oobe-adaptive-dialog> - <!-- Loaded Dialog --> - <oobe-adaptive-dialog id="loaded" for-step="loaded" role="dialog" - aria-label$="[[i18nDynamic(locale, 'guestTosTitle')]]"> - <iron-icon slot="icon" icon="oobe-32:avatar"></iron-icon> - <h1 slot="title"> - [[i18nDynamic(locale, 'guestTosTitle')]] - </h1> - <div slot="content" class="landscape-header-aligned"> - <div id="termsTitle"> - [[i18nDynamic(locale, 'guestTosTermsTitle')]] - </div> - <div id="terms"> - <div inner-h-t-m-l="[[getTerms_(locale)]]"> - </div> - </div> +<!-- CrOS EULA Dialog --> +<oobe-adaptive-dialog id="crosEulaDialog" for-step="cros-eula" +role="dialog" +aria-label$="[[i18nDynamic(locale, 'guestTosCrosEulaTitle')]]"> + <iron-icon slot="icon" icon="oobe-32:googleg"></iron-icon> + <h1 slot="title"> + [[i18nDynamic(locale, 'guestTosCrosEulaTitle')]] + </h1> + <div slot="content" class="flex layout vertical"> + <webview id="guestTosCrosEulaWebview" role="document" + class="oobe-tos-webview tos-webview"> + </webview> + </div> + <div slot="bottom-buttons"> + <oobe-text-button id="crosEulaOkButton" + class="focus-on-show" inverse on-click="onTermsStepOkClick_" + text-key="guestTosOk"></oobe-text-button> + </div> +</oobe-adaptive-dialog> - <!-- Usage stats toggle row --> - <div id="usageStats" class="layout horizontal center oobe-optin-row"> - <div class="oobe-optin-content"> - <span id="usageTitle" class="oobe-optin-title"> - [[i18nDynamic(locale, 'guestTosUsageOptinTitle')]] - </span> - [[i18nDynamic(locale, 'guestTosUsageOptin')]] - <a id="usageLearnMore" on-click="onUsageLearnMoreClick_" - class="oobe-local-link" is="action-link"> - [[i18nDynamic(locale, 'guestTosLearnMore')]] - </a> - </div> - <cr-toggle id="usageOptin" checked="{{usageChecked}}" - aria-describedby="usageTitle"> - </cr-toggle> - </div> +<!-- Loaded Dialog --> +<oobe-adaptive-dialog id="loaded" for-step="loaded" role="dialog" +aria-label$="[[i18nDynamic(locale, 'guestTosTitle')]]"> + <iron-icon slot="icon" icon="oobe-32:avatar"></iron-icon> + <h1 slot="title"> + [[i18nDynamic(locale, 'guestTosTitle')]] + </h1> + <div slot="content" class="landscape-header-aligned"> + <div id="termsTitle"> + [[i18nDynamic(locale, 'guestTosTermsTitle')]] + </div> + <div id="terms"> + <div inner-h-t-m-l="[[getTerms_(locale)]]"> </div> - <div slot="back-navigation"> - <oobe-back-button on-click="onBackClick_"></oobe-back-button> - </div> - <div slot="bottom-buttons"> - <oobe-next-button id="acceptButton" inverse on-click="onAcceptClick_" - text-key="guestTosAccept" class="focus-on-show"> - </oobe-next-button> - </div> - </oobe-adaptive-dialog> + </div> - <oobe-modal-dialog id="usageLearnMorePopUp"> - <div slot="content"> - <span inner-h-t-m-l="[[getUsageLearnMoreText_(locale)]]"></span> + <!-- Usage stats toggle row --> + <div id="usageStats" class="layout horizontal center oobe-optin-row"> + <div class="oobe-optin-content"> + <span id="usageTitle" class="oobe-optin-title"> + [[i18nDynamic(locale, 'guestTosUsageOptinTitle')]] + </span> + [[i18nDynamic(locale, 'guestTosUsageOptin')]] + <a id="usageLearnMore" on-click="onUsageLearnMoreClick_" + class="oobe-local-link" is="action-link"> + [[i18nDynamic(locale, 'guestTosLearnMore')]] + </a> </div> - </oobe-modal-dialog> - </template> - <script src="guest_tos.js"></script> -</dom-module> + <cr-toggle id="usageOptin" checked="{{usageChecked}}" + aria-describedby="usageTitle"> + </cr-toggle> + </div> + </div> + <div slot="back-navigation"> + <oobe-back-button on-click="onBackClick_"></oobe-back-button> + </div> + <div slot="bottom-buttons"> + <oobe-next-button id="acceptButton" inverse on-click="onAcceptClick_" + text-key="guestTosAccept" class="focus-on-show"> + </oobe-next-button> + </div> +</oobe-adaptive-dialog> + +<oobe-modal-dialog id="usageLearnMorePopUp"> + <div slot="content"> + <span inner-h-t-m-l="[[getUsageLearnMoreText_(locale)]]"></span> + </div> +</oobe-modal-dialog>
diff --git a/chrome/browser/resources/chromeos/login/screens/common/guest_tos.js b/chrome/browser/resources/chromeos/login/screens/common/guest_tos.js index b5c5971..4ae84b1e 100644 --- a/chrome/browser/resources/chromeos/login/screens/common/guest_tos.js +++ b/chrome/browser/resources/chromeos/login/screens/common/guest_tos.js
@@ -6,7 +6,29 @@ * @fileoverview guest tos screen implementation. */ -/* #js_imports_placeholder */ +import '//resources/cr_elements/cr_shared_style.css.js'; +import '//resources/cr_elements/cr_toggle/cr_toggle.js'; +import '//resources/js/action_link.js'; +import '//resources/polymer/v3_0/iron-icon/iron-icon.js'; +import '../../components/common_styles/common_styles.m.js'; +import '../../components/common_styles/oobe_dialog_host_styles.m.js'; +import '../../components/oobe_icons.m.js'; +import '../../components/dialogs/oobe_loading_dialog.m.js'; +import '../../components/dialogs/oobe_modal_dialog.m.js'; + +import {html, mixinBehaviors, Polymer, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +import {LoginScreenBehavior, LoginScreenBehaviorInterface} from '../../components/behaviors/login_screen_behavior.m.js'; +import {MultiStepBehavior, MultiStepBehaviorInterface} from '../../components/behaviors/multi_step_behavior.m.js'; +import {OobeI18nBehavior, OobeI18nBehaviorInterface} from '../../components/behaviors/oobe_i18n_behavior.m.js'; +import {OobeBackButton} from '../../components/buttons/oobe_back_button.js'; +import {OobeNextButton} from '../../components/buttons/oobe_next_button.js'; +import {OobeTextButton} from '../../components/buttons/oobe_text_button.js'; +import {OobeAdaptiveDialog} from '../../components/dialogs/oobe_adaptive_dialog.js'; +import {OOBE_UI_STATE} from '../../components/display_manager_types.m.js'; +import {WebViewHelper} from '../../components/web_view_helper.m.js'; +import {WebViewLoader} from '../../components/web_view_loader.m.js'; + // Enum that describes the current state of the Guest ToS screen const GuestTosScreenState = { @@ -35,9 +57,8 @@ * @implements {OobeI18nBehaviorInterface} * @implements {MultiStepBehaviorInterface} */ -const GuestTosScreenElementBase = Polymer.mixinBehaviors( - [OobeI18nBehavior, MultiStepBehavior, LoginScreenBehavior], - Polymer.Element); +const GuestTosScreenElementBase = mixinBehaviors( + [OobeI18nBehavior, MultiStepBehavior, LoginScreenBehavior], PolymerElement); /** * @polymer @@ -47,7 +68,9 @@ return 'guest-tos-element'; } - /* #html_template_placeholder */ + static get template() { + return html`{__html_template__}`; + } static get properties() { return { @@ -58,11 +81,6 @@ }; } - constructor() { - super(); - this.usageChecked = true; - } - /** @override */ defaultUIStep() { return GuestTosScreenState.LOADING;
diff --git a/chrome/browser/resources/downloads/BUILD.gn b/chrome/browser/resources/downloads/BUILD.gn index a806dad5..c701a409 100644 --- a/chrome/browser/resources/downloads/BUILD.gn +++ b/chrome/browser/resources/downloads/BUILD.gn
@@ -34,8 +34,10 @@ icons_html_files = [ "icons.html" ] mojo_files_deps = - [ "//chrome/browser/ui/webui/downloads:mojo_bindings_js__generator" ] - mojo_files = [ "$root_gen_dir/mojom-webui/chrome/browser/ui/webui/downloads/downloads.mojom-webui.js" ] + [ "//chrome/browser/ui/webui/downloads:mojo_bindings_ts__generator" ] + mojo_files = [ + "$root_gen_dir/chrome/browser/ui/webui/downloads/downloads.mojom-webui.ts", + ] ts_composite = true ts_definitions = [ "//tools/typescript/definitions/chrome_send.d.ts" ]
diff --git a/chrome/browser/resources/downloads/data.ts b/chrome/browser/resources/downloads/data.ts index a16da6f..90ee91d 100644 --- a/chrome/browser/resources/downloads/data.ts +++ b/chrome/browser/resources/downloads/data.ts
@@ -9,6 +9,6 @@ import {Data} from './downloads.mojom-webui.js'; -export class MojomData extends Data { +export interface MojomData extends Data { hideDate: boolean; }
diff --git a/chrome/browser/resources/downloads/tsconfig_base.json b/chrome/browser/resources/downloads/tsconfig_base.json index 3e71f763..afa07315 100644 --- a/chrome/browser/resources/downloads/tsconfig_base.json +++ b/chrome/browser/resources/downloads/tsconfig_base.json
@@ -1,7 +1,6 @@ { "extends": "../../../../tools/typescript/tsconfig_base.json", "compilerOptions": { - "allowJs": true, "noUncheckedIndexedAccess": false, "noUnusedLocals": false, "strictPropertyInitialization": false
diff --git a/chrome/browser/resources/settings/safety_check_page/safety_check_notification_permissions.html b/chrome/browser/resources/settings/safety_check_page/safety_check_notification_permissions.html index f3025e35..710b458f 100644 --- a/chrome/browser/resources/settings/safety_check_page/safety_check_notification_permissions.html +++ b/chrome/browser/resources/settings/safety_check_page/safety_check_notification_permissions.html
@@ -4,7 +4,7 @@ icon-status="[[iconStatus_]]" label="[[headerString_]]" button-label="$i18n{safetyCheckReview}" - button-aria-label="[[buttonAriaLabel_]]" + button-aria-label="$i18n{safetyCheckNotificationPermissionReviewButtonAriaLabel}" on-button-click="onButtonClick_" role="presentation" class="two-line">
diff --git a/chrome/browser/resources/settings/safety_check_page/safety_check_notification_permissions.ts b/chrome/browser/resources/settings/safety_check_page/safety_check_notification_permissions.ts index 36878e3..9a01dde 100644 --- a/chrome/browser/resources/settings/safety_check_page/safety_check_notification_permissions.ts +++ b/chrome/browser/resources/settings/safety_check_page/safety_check_notification_permissions.ts
@@ -50,35 +50,25 @@ }, }, - sites_: { - type: Array, - observer: 'onSitesChanged_', - }, - headerString_: String, - - buttonAriaLabel_: String, }; } private iconStatus_: SafetyCheckIconStatus; private headerString_: string; - private buttonAriaLabel_: string; - private sites_: NotificationPermission[] = []; private siteSettingsBrowserProxy_: SiteSettingsPrefsBrowserProxy = SiteSettingsPrefsBrowserProxyImpl.getInstance(); - override async connectedCallback() { + override connectedCallback() { super.connectedCallback(); // Register for review notification permission list updates. this.addWebUIListener( 'notification-permission-review-list-maybe-changed', - (sites: NotificationPermission[]) => - this.onReviewNotificationPermissionListChanged_(sites)); + (sites: NotificationPermission[]) => this.onSitesChanged_(sites)); - this.sites_ = - await this.siteSettingsBrowserProxy_.getNotificationPermissionReview(); + this.siteSettingsBrowserProxy_.getNotificationPermissionReview().then( + this.onSitesChanged_.bind(this)); } private onButtonClick_() { @@ -87,20 +77,10 @@ /* removeSearch= */ true); } - private async onReviewNotificationPermissionListChanged_( - sites: NotificationPermission[]) { - this.sites_ = sites; - } - - private async onSitesChanged_() { + private async onSitesChanged_(sites: NotificationPermission[]) { this.headerString_ = await PluralStringProxyImpl.getInstance().getPluralString( - 'safetyCheckNotificationPermissionReviewHeaderLabel', - this.sites_.length); - this.buttonAriaLabel_ = - await PluralStringProxyImpl.getInstance().getPluralString( - 'safetyCheckNotificationPermissionReviewPrimaryLabel', - this.sites_!.length); + 'safetyCheckNotificationPermissionReviewHeaderLabel', sites.length); } }
diff --git a/chrome/browser/resources/settings/site_settings/review_notification_permissions.html b/chrome/browser/resources/settings/site_settings/review_notification_permissions.html index 89a50e51..00712aa 100644 --- a/chrome/browser/resources/settings/site_settings/review_notification_permissions.html +++ b/chrome/browser/resources/settings/site_settings/review_notification_permissions.html
@@ -29,6 +29,7 @@ } .header-group-wrapper { + flex: 1; margin-inline-start: 15px; } @@ -113,12 +114,12 @@ <template is="dom-if" if="[[!shouldShowCompletionInfo_]]"> <div id="review-header" class="header-with-icon"> <iron-icon role="img" icon="settings:notifications-none"></iron-icon> - <cr-expand-button id="expandButton" class="header-group-wrapper" no-hover - expanded="{{notificationPermissionReviewListExpanded_}}"> + <div class="header-group-wrapper"> <h2>[[headerString_]]</h2> - <div class="secondary"> - $i18n{safetyCheckNotificationPermissionReviewSecondaryLabel} - </div> + <div class="secondary">[[subtitleString_]]</div> + </div> + <cr-expand-button id="expandButton" no-hover + expanded="{{notificationPermissionReviewListExpanded_}}"> </cr-expand-button> </div> <iron-collapse class="notification-permissions-list" @@ -168,7 +169,7 @@ </template> <cr-toast id="undoToast" duration="5000"> <div id="undoNotification">[[toastText_]]</div> - <cr-button aria-label="$i18n{safetyCheckNotificationPermissionReviewUndo}" + <cr-button aria-label="$i18n{safetyCheckNotificationPermissionReviewUndo}" on-click="onUndoButtonClick_"> $i18n{safetyCheckNotificationPermissionReviewUndo} </cr-button>
diff --git a/chrome/browser/resources/settings/site_settings/review_notification_permissions.ts b/chrome/browser/resources/settings/site_settings/review_notification_permissions.ts index bc071117..b186371 100644 --- a/chrome/browser/resources/settings/site_settings/review_notification_permissions.ts +++ b/chrome/browser/resources/settings/site_settings/review_notification_permissions.ts
@@ -102,6 +102,9 @@ /* The string for the primary header label. */ headerString_: String, + /* The string for the subtitle. */ + subtitleString_: String, + /** * The text that will be shown in the toast element upon clicking one of * the actions. @@ -113,18 +116,19 @@ private sites_: NotificationPermission[]; private notificationPermissionReviewListExpanded_: boolean; private shouldShowCompletionInfo_: boolean; - private browserProxy_: SiteSettingsPrefsBrowserProxy = - SiteSettingsPrefsBrowserProxyImpl.getInstance(); private lastOrigins_: string[] = []; private lastUserAction_: Actions|null; private headerString_: string; + private subtitleString_: string; private sitesLoaded_: boolean = false; private modelUpdateDelayMsForTesting_: number|null = null; private toastText_: string|null; + private eventTracker_: EventTracker = new EventTracker(); + private shouldRefocusExpandButton_: boolean = false; + private browserProxy_: SiteSettingsPrefsBrowserProxy = + SiteSettingsPrefsBrowserProxyImpl.getInstance(); private metricsBrowserProxy_: MetricsBrowserProxy = MetricsBrowserProxyImpl.getInstance(); - private shouldRefocusExpandButton_: boolean = false; - private eventTracker_: EventTracker = new EventTracker(); override async connectedCallback() { super.connectedCallback(); @@ -427,6 +431,10 @@ await PluralStringProxyImpl.getInstance().getPluralString( 'safetyCheckNotificationPermissionReviewPrimaryLabel', this.sites_.length); + this.subtitleString_ = + await PluralStringProxyImpl.getInstance().getPluralString( + 'safetyCheckNotificationPermissionReviewSecondaryLabel', + this.sites_.length); /** * Focus on the expand button after the undo button is clicked and sites are * loaded again.
diff --git a/chrome/browser/safe_browsing/chrome_client_side_detection_host_delegate.cc b/chrome/browser/safe_browsing/chrome_client_side_detection_host_delegate.cc index 1761775..269e3b8 100644 --- a/chrome/browser/safe_browsing/chrome_client_side_detection_host_delegate.cc +++ b/chrome/browser/safe_browsing/chrome_client_side_detection_host_delegate.cc
@@ -21,6 +21,7 @@ #include "components/safe_browsing/core/browser/db/database_manager.h" #include "components/safe_browsing/core/browser/sync/safe_browsing_primary_account_token_fetcher.h" #include "components/safe_browsing/core/browser/sync/sync_utils.h" +#include "components/signin/public/identity_manager/identity_manager.h" #include "content/public/browser/global_routing_id.h" namespace safe_browsing {
diff --git a/chrome/browser/sharesheet/sharesheet_service.cc b/chrome/browser/sharesheet/sharesheet_service.cc index 9e82405..a78557f 100644 --- a/chrome/browser/sharesheet/sharesheet_service.cc +++ b/chrome/browser/sharesheet/sharesheet_service.cc
@@ -128,6 +128,10 @@ std::move(action_cleanup_callback)); SharesheetMetrics::RecordSharesheetLaunchSource(source); + if (!native_window) { + std::move(delivered_callback).Run(SharesheetResult::kErrorWindowClosed); + return; + } auto* sharesheet_service_delegator = GetOrCreateDelegator(native_window); sharesheet_service_delegator->ShowNearbyShareBubbleForArc( std::move(intent), std::move(delivered_callback),
diff --git a/chrome/browser/signin/bound_session_credentials/bound_session_cookie_fetcher.cc b/chrome/browser/signin/bound_session_credentials/bound_session_cookie_fetcher.cc new file mode 100644 index 0000000..3d2862e --- /dev/null +++ b/chrome/browser/signin/bound_session_credentials/bound_session_cookie_fetcher.cc
@@ -0,0 +1,80 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/signin/bound_session_credentials/bound_session_cookie_fetcher.h" + +#include "base/callback.h" +#include "base/task/sequenced_task_runner.h" +#include "base/time/time.h" +#include "components/signin/public/base/signin_client.h" +#include "google_apis/gaia/gaia_urls.h" +#include "mojo/public/cpp/bindings/callback_helpers.h" +#include "net/cookies/canonical_cookie.h" +#include "services/network/public/mojom/cookie_manager.mojom.h" +#include "third_party/abseil-cpp/absl/types/optional.h" + +BoundSessionCookieFetcher::BoundSessionCookieFetcher( + SigninClient* client, + SetCookieCompleteCallback callback) + : client_(client), callback_(std::move(callback)) { + constexpr base::TimeDelta kFakeNetworkRequestEquivalentDelay( + base::Milliseconds(100)); + base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&BoundSessionCookieFetcher::StartSettingCookie, + weak_ptr_factory_.GetWeakPtr()), + kFakeNetworkRequestEquivalentDelay); +} + +void BoundSessionCookieFetcher::StartSettingCookie() { + constexpr char kSIDTSCookieName[] = "__Secure-1PSIDTS"; + constexpr char kFakeCookieValue[] = "FakeCookieValue"; + const base::TimeDelta kMaxAge = base::Minutes(10); + + base::Time now = base::Time::Now(); + base::Time expiration = now + kMaxAge; + GURL google_url = GaiaUrls::GetInstance()->secure_google_url(); + + // Create fake SIDTS cookie until the server endpoint is available. + std::unique_ptr<net::CanonicalCookie> new_cookie = + net::CanonicalCookie::CreateSanitizedCookie( + /*url=*/google_url, /*name=*/kSIDTSCookieName, + /*value=*/kFakeCookieValue, + /*domain=*/google_url.host(), /*path=*/"/", + /*creation_time=*/now, /*expiration_time=*/expiration, + /*last_access_time=*/now, /*secure=*/true, + /*http_only=*/true, net::CookieSameSite::UNSPECIFIED, + net::CookiePriority::COOKIE_PRIORITY_HIGH, + /*same_party=*/true, /*partition_key=*/absl::nullopt); + + DCHECK(new_cookie); + base::OnceCallback<void(net::CookieAccessResult)> callback = + base::BindOnce(&BoundSessionCookieFetcher::OnCookieSet, + weak_ptr_factory_.GetWeakPtr(), new_cookie->ExpiryDate()); + net::CookieOptions options; + options.set_include_httponly(); + // Permit it to set a SameSite cookie if it wants to. + options.set_same_site_cookie_context( + net::CookieOptions::SameSiteCookieContext::MakeInclusive()); + client_->GetCookieManager()->SetCanonicalCookie( + *new_cookie, google_url, options, + mojo::WrapCallbackWithDefaultInvokeIfNotRun( + std::move(callback), + net::CookieAccessResult(net::CookieInclusionStatus( + net::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR)))); +} + +void BoundSessionCookieFetcher::OnCookieSet( + const base::Time& expiry_date, + net::CookieAccessResult access_result) { + bool success = access_result.status.IsInclude(); + if (!success) { + std::move(callback_).Run(absl::nullopt); + } else { + std::move(callback_).Run(expiry_date); + } + // |This| may be destroyed +} + +BoundSessionCookieFetcher::~BoundSessionCookieFetcher() = default;
diff --git a/chrome/browser/signin/bound_session_credentials/bound_session_cookie_fetcher.h b/chrome/browser/signin/bound_session_credentials/bound_session_cookie_fetcher.h new file mode 100644 index 0000000..029e34a --- /dev/null +++ b/chrome/browser/signin/bound_session_credentials/bound_session_cookie_fetcher.h
@@ -0,0 +1,36 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_SIGNIN_BOUND_SESSION_CREDENTIALS_BOUND_SESSION_COOKIE_FETCHER_H_ +#define CHROME_BROWSER_SIGNIN_BOUND_SESSION_CREDENTIALS_BOUND_SESSION_COOKIE_FETCHER_H_ + +#include "base/callback.h" +#include "base/memory/raw_ptr.h" +#include "base/time/time.h" +#include "net/cookies/canonical_cookie.h" +#include "third_party/abseil-cpp/absl/types/optional.h" + +class SigninClient; + +class BoundSessionCookieFetcher { + public: + // Returns the expected expiration date of the cookie. This is optional as + // set cookie might fail. + using SetCookieCompleteCallback = + base::OnceCallback<void(absl::optional<const base::Time>)>; + + BoundSessionCookieFetcher(SigninClient* client, + SetCookieCompleteCallback callback); + ~BoundSessionCookieFetcher(); + + private: + void StartSettingCookie(); + void OnCookieSet(const base::Time& expiry_date, + net::CookieAccessResult access_result); + + const raw_ptr<SigninClient> client_; + SetCookieCompleteCallback callback_; + base::WeakPtrFactory<BoundSessionCookieFetcher> weak_ptr_factory_{this}; +}; +#endif // CHROME_BROWSER_SIGNIN_BOUND_SESSION_CREDENTIALS_BOUND_SESSION_COOKIE_FETCHER_H_
diff --git a/chrome/browser/signin/bound_session_credentials/bound_session_cookie_fetcher_unittest.cc b/chrome/browser/signin/bound_session_credentials/bound_session_cookie_fetcher_unittest.cc new file mode 100644 index 0000000..fb5c119e --- /dev/null +++ b/chrome/browser/signin/bound_session_credentials/bound_session_cookie_fetcher_unittest.cc
@@ -0,0 +1,90 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/signin/bound_session_credentials/bound_session_cookie_fetcher.h" + +#include "base/run_loop.h" +#include "base/test/task_environment.h" +#include "base/time/time.h" +#include "components/signin/public/base/test_signin_client.h" +#include "components/sync_preferences/testing_pref_service_syncable.h" +#include "net/cookies/canonical_cookie.h" +#include "net/cookies/cookie_access_result.h" +#include "services/network/test/test_cookie_manager.h" +#include "testing/gtest/include/gtest/gtest.h" + +class FakeCookieManager : public network::TestCookieManager { + public: + void SetCanonicalCookie(const net::CanonicalCookie& cookie, + const GURL& source_url, + const net::CookieOptions& cookie_options, + SetCanonicalCookieCallback callback) override { + cookie_ = cookie; + if (callback) { + std::move(callback).Run(net::CookieAccessResult()); + } + } + + net::CanonicalCookie& cookie() { return cookie_; } + + private: + net::CanonicalCookie cookie_; +}; + +class BoundSessionCookieFetcherTest : public testing::Test { + public: + BoundSessionCookieFetcherTest() + : task_environment_( + base::test::SingleThreadTaskEnvironment::TimeSource::MOCK_TIME) { + std::unique_ptr<FakeCookieManager> fake_cookie_manager = + std::make_unique<FakeCookieManager>(); + cookie_manager_ = fake_cookie_manager.get(); + signin_client_.set_cookie_manager(std::move(fake_cookie_manager)); + } + + ~BoundSessionCookieFetcherTest() override = default; + + void InitializeFetcher(base::OnceClosure on_done) { + fetcher_ = std::make_unique<BoundSessionCookieFetcher>( + &signin_client_, + base::BindOnce(&BoundSessionCookieFetcherTest::OnCookieSet, + base::Unretained(this), std::move(on_done))); + } + + void OnCookieSet(base::OnceClosure on_done, + absl::optional<const base::Time> result) { + expected_expiry_date_ = result.value_or(base::Time()); + std::move(on_done).Run(); + } + + void VerifyCookie() { + EXPECT_TRUE(cookie_manager_); + constexpr char kSIDTSCookieName[] = "__Secure-1PSIDTS"; + constexpr char kFakeCookieValue[] = "FakeCookieValue"; + + net::CanonicalCookie& cookie = cookie_manager_->cookie(); + EXPECT_TRUE(cookie.IsCanonical()); + EXPECT_EQ(cookie.ExpiryDate(), expected_expiry_date_); + EXPECT_EQ(cookie.Domain(), ".google.com"); + EXPECT_EQ(cookie.Name(), kSIDTSCookieName); + EXPECT_EQ(cookie.Value(), kFakeCookieValue); + EXPECT_TRUE(cookie.IsExpired(base::Time::Now() + base::Minutes(10))); + } + + protected: + base::test::SingleThreadTaskEnvironment task_environment_; + base::Time expected_expiry_date_; + std::unique_ptr<BoundSessionCookieFetcher> fetcher_; + sync_preferences::TestingPrefServiceSyncable prefs_; + TestSigninClient signin_client_{&prefs_}; + FakeCookieManager* cookie_manager_ = nullptr; +}; + +TEST_F(BoundSessionCookieFetcherTest, SetSIDTSCookie) { + base::RunLoop run_loop; + InitializeFetcher(run_loop.QuitClosure()); + task_environment_.FastForwardBy(base::Milliseconds(100)); + run_loop.Run(); + VerifyCookie(); +}
diff --git a/chrome/browser/signin/dice_tab_helper_unittest.cc b/chrome/browser/signin/dice_tab_helper_unittest.cc index 33dcee7..a788f3a 100644 --- a/chrome/browser/signin/dice_tab_helper_unittest.cc +++ b/chrome/browser/signin/dice_tab_helper_unittest.cc
@@ -217,11 +217,10 @@ class DiceTabHelperPrerenderTest : public DiceTabHelperTest { public: DiceTabHelperPrerenderTest() { - feature_list_.InitWithFeatures( - {blink::features::kPrerender2}, + feature_list_.InitAndDisableFeature( // Disable the memory requirement of Prerender2 so the test can run on // any bot. - {blink::features::kPrerender2MemoryControls}); + blink::features::kPrerender2MemoryControls); } ~DiceTabHelperPrerenderTest() override = default;
diff --git a/chrome/browser/signin/reauth_tab_helper_unittest.cc b/chrome/browser/signin/reauth_tab_helper_unittest.cc index db77189b..00191ec 100644 --- a/chrome/browser/signin/reauth_tab_helper_unittest.cc +++ b/chrome/browser/signin/reauth_tab_helper_unittest.cc
@@ -154,11 +154,10 @@ class ReauthTabHelperPrerenderTest : public ReauthTabHelperTest { public: ReauthTabHelperPrerenderTest() { - feature_list_.InitWithFeatures( - {blink::features::kPrerender2}, + feature_list_.InitAndDisableFeature( // Disable the memory requirement of Prerender2 so the test can run on // any bot. - {blink::features::kPrerender2MemoryControls}); + blink::features::kPrerender2MemoryControls); } private:
diff --git a/chrome/browser/site_isolation/site_details_browsertest.cc b/chrome/browser/site_isolation/site_details_browsertest.cc index 7faeeef..f03f2c6 100644 --- a/chrome/browser/site_isolation/site_details_browsertest.cc +++ b/chrome/browser/site_isolation/site_details_browsertest.cc
@@ -819,9 +819,7 @@ PrerenderSiteDetailsBrowserTest() : prerender_helper_( base::BindRepeating(&PrerenderSiteDetailsBrowserTest::web_contents, - base::Unretained(this))) { - feature_list_.InitAndEnableFeature(blink::features::kPrerender2); - } + base::Unretained(this))) {} ~PrerenderSiteDetailsBrowserTest() override = default; PrerenderSiteDetailsBrowserTest(const PrerenderSiteDetailsBrowserTest&) = @@ -842,9 +840,6 @@ return browser()->tab_strip_model()->GetActiveWebContents(); } content::test::PrerenderTestHelper prerender_helper_; - - private: - base::test::ScopedFeatureList feature_list_; }; IN_PROC_BROWSER_TEST_F(PrerenderSiteDetailsBrowserTest,
diff --git a/chrome/browser/sync/sync_encryption_keys_tab_helper_unittest.cc b/chrome/browser/sync/sync_encryption_keys_tab_helper_unittest.cc index 100c6fd..5d3b65f 100644 --- a/chrome/browser/sync/sync_encryption_keys_tab_helper_unittest.cc +++ b/chrome/browser/sync/sync_encryption_keys_tab_helper_unittest.cc
@@ -161,11 +161,10 @@ : public SyncEncryptionKeysTabHelperTest { public: SyncEncryptionKeysTabHelperPrerenderingTest() { - scoped_feature_list_.InitWithFeatures( - {blink::features::kPrerender2}, + scoped_feature_list_.InitAndDisableFeature( // Disable the memory requirement of Prerender2 so the test can run on // any bot. - {blink::features::kPrerender2MemoryControls}); + blink::features::kPrerender2MemoryControls); } ~SyncEncryptionKeysTabHelperPrerenderingTest() override = default;
diff --git a/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewBinder.java b/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewBinder.java index be61137..681f59a 100644 --- a/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewBinder.java +++ b/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewBinder.java
@@ -35,7 +35,6 @@ import androidx.appcompat.content.res.AppCompatResources; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.password_manager.PasswordManagerResourceProviderFactory; import org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.FaviconOrFallback; import org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.ItemType; @@ -237,22 +236,14 @@ }); } else if (propertyKey == SHOW_SUBMIT_BUTTON) { TextView buttonTitleText = view.findViewById(R.id.touch_to_fill_button_title); - if (ChromeFeatureList.isEnabled(ChromeFeatureList.TOUCH_TO_FILL_PASSWORD_SUBMISSION)) { - buttonTitleText.setText(view.getContext().getString(model.get(SHOW_SUBMIT_BUTTON) - ? R.string.touch_to_fill_signin - : R.string.touch_to_fill_continue)); - } else { - buttonTitleText.setText(R.string.touch_to_fill_continue); - } + buttonTitleText.setText(view.getContext().getString(model.get(SHOW_SUBMIT_BUTTON) + ? R.string.touch_to_fill_signin + : R.string.touch_to_fill_continue)); } else if (propertyKey == SHOW_WEBAUTHN_SUBMIT_BUTTON) { TextView buttonTitleText = view.findViewById(R.id.touch_to_fill_button_title); - if (ChromeFeatureList.isEnabled(ChromeFeatureList.TOUCH_TO_FILL_PASSWORD_SUBMISSION)) { - buttonTitleText.setText(view.getContext().getString( - model.get(SHOW_WEBAUTHN_SUBMIT_BUTTON) ? R.string.touch_to_fill_signin - : R.string.touch_to_fill_continue)); - } else { - buttonTitleText.setText(R.string.touch_to_fill_continue); - } + buttonTitleText.setText(view.getContext().getString( + model.get(SHOW_WEBAUTHN_SUBMIT_BUTTON) ? R.string.touch_to_fill_signin + : R.string.touch_to_fill_continue)); } else if (propertyKey == FAVICON_OR_FALLBACK || propertyKey == FORMATTED_ORIGIN || propertyKey == CREDENTIAL || propertyKey == WEBAUTHN_CREDENTIAL || propertyKey == WEBAUTHN_FAVICON_OR_FALLBACK) { @@ -270,7 +261,6 @@ */ private static String getSubtitle(PropertyModel model, Context context) { if (model.get(SHOW_SUBMIT_SUBTITLE)) { - assert ChromeFeatureList.isEnabled(ChromeFeatureList.TOUCH_TO_FILL_PASSWORD_SUBMISSION); return String.format( context.getString(model.get(ORIGIN_SECURE) ? R.string.touch_to_fill_sheet_subtitle_submission
diff --git a/chrome/browser/touch_to_fill/android/javatests/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewTest.java b/chrome/browser/touch_to_fill/android/javatests/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewTest.java index b4fb53259..bffb304 100644 --- a/chrome/browser/touch_to_fill/android/javatests/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewTest.java +++ b/chrome/browser/touch_to_fill/android/javatests/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewTest.java
@@ -376,9 +376,11 @@ @Test @MediumTest public void testButtonTitleWithoutAutoSubmission() { + final boolean showSubmitButton = false; TestThreadUtils.runOnUiThreadBlocking(() -> { mModel.get(SHEET_ITEMS) - .addAll(asList(buildCredentialItem(ANA), buildConfirmationButton(ANA, false))); + .addAll(asList(buildCredentialItem(ANA), + buildConfirmationButton(ANA, showSubmitButton))); mModel.set(VISIBLE, true); }); BottomSheetTestSupport.waitForOpen(mBottomSheetController);
diff --git a/chrome/browser/touch_to_fill/payments/android/internal/BUILD.gn b/chrome/browser/touch_to_fill/payments/android/internal/BUILD.gn index 3e3eff558..da4bf5d 100644 --- a/chrome/browser/touch_to_fill/payments/android/internal/BUILD.gn +++ b/chrome/browser/touch_to_fill/payments/android/internal/BUILD.gn
@@ -42,3 +42,48 @@ "java/res/values/dimens.xml", ] } + +robolectric_library("junit") { + testonly = true + + sources = [ "java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardControllerRobolectricTest.java" ] + + deps = [ + ":java", + "//base:base_java", + "//base:base_java_test_support", + "//base:base_junit_test_support", + "//chrome/browser/touch_to_fill/payments/android:public_java", + "//chrome/test/android:chrome_java_unit_test_support", + "//components/browser_ui/bottomsheet/android:java", + "//third_party/junit", + "//third_party/mockito:mockito_java", + "//ui/android:ui_java_test_support", + "//ui/android:ui_no_recycler_view_java", + ] +} + +android_library("javatests") { + testonly = true + + sources = [ "java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardViewTest.java" ] + + deps = [ + ":java", + "//base:base_java", + "//base:base_java_test_support", + "//chrome/android:chrome_java", + "//chrome/browser/flags:java", + "//chrome/browser/touch_to_fill/payments/android:public_java", + "//chrome/test/android:chrome_java_integration_test_support", + "//components/browser_ui/bottomsheet/android:java", + "//components/browser_ui/bottomsheet/android/test:java", + "//content/public/test/android:content_java_test_support", + "//third_party/android_deps:espresso_java", + "//third_party/androidx:androidx_test_runner_java", + "//third_party/hamcrest:hamcrest_library_java", + "//third_party/junit:junit", + "//third_party/mockito:mockito_java", + "//ui/android:ui_no_recycler_view_java", + ] +}
diff --git a/chrome/browser/touch_to_fill/payments/android/internal/java/res/layout/touch_to_fill_credit_card_sheet.xml b/chrome/browser/touch_to_fill/payments/android/internal/java/res/layout/touch_to_fill_credit_card_sheet.xml index 2c4bd68..c6779a24 100644 --- a/chrome/browser/touch_to_fill/payments/android/internal/java/res/layout/touch_to_fill_credit_card_sheet.xml +++ b/chrome/browser/touch_to_fill/payments/android/internal/java/res/layout/touch_to_fill_credit_card_sheet.xml
@@ -38,7 +38,6 @@ android:clipToPadding="false" android:divider="@null" tools:listitem="@layout/touch_to_fill_credit_card_sheet_item"/> - <!-- Divider --> <View style="@style/HorizontalDivider" android:layout_width="match_parent" @@ -59,6 +58,7 @@ android:paddingHorizontal="@dimen/ttf_for_payments_sheet_padding_horizontal" android:textAppearance="@style/TextAppearance.TextMedium.Primary" android:text="@string/autofill_scan_credit_card" + android:visibility="gone" app:drawableStartCompat="@drawable/ic_photo_camera" app:drawableTint="@color/default_icon_color_tint_list"/> -</RelativeLayout> \ No newline at end of file +</RelativeLayout>
diff --git a/chrome/browser/touch_to_fill/payments/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardControllerBridge.java b/chrome/browser/touch_to_fill/payments/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardControllerBridge.java index 2515909b..10d681ef 100644 --- a/chrome/browser/touch_to_fill/payments/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardControllerBridge.java +++ b/chrome/browser/touch_to_fill/payments/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardControllerBridge.java
@@ -38,8 +38,17 @@ } } + @Override + public void scanCreditCard() { + if (mNativeTouchToFillCreditCardViewController != 0) { + TouchToFillCreditCardControllerBridgeJni.get().scanCreditCard( + mNativeTouchToFillCreditCardViewController); + } + } + @NativeMethods interface Natives { void onDismissed(long nativeTouchToFillCreditCardViewController); + void scanCreditCard(long nativeTouchToFillCreditCardViewController); } }
diff --git a/chrome/browser/touch_to_fill/payments/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardControllerRobolectricTest.java b/chrome/browser/touch_to_fill/payments/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardControllerRobolectricTest.java new file mode 100644 index 0000000..3c75e9d --- /dev/null +++ b/chrome/browser/touch_to_fill/payments/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardControllerRobolectricTest.java
@@ -0,0 +1,61 @@ +// Copyright 2022 The Chromium Authors +// 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.touch_to_fill.payments; + +import static org.mockito.Mockito.verify; + +import android.app.Activity; +import android.content.Context; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.robolectric.Robolectric; + +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; +import org.chromium.ui.modelutil.PropertyModel; + +/** Tests for {@link TouchToFillCreditCardCoordinator} and {@link TouchToFillCreditCardMediator} */ +@RunWith(BaseRobolectricTestRunner.class) +public class TouchToFillCreditCardControllerRobolectricTest { + @Rule + public MockitoRule mMockitoRule = MockitoJUnit.rule(); + + private TouchToFillCreditCardCoordinator mCoordinator; + private PropertyModel mTouchToFillCreditCardModel; + Context mContext; + + @Mock + private BottomSheetController mBottomSheetController; + + @Mock + TouchToFillCreditCardComponent.Delegate mDelegateMock; + + public TouchToFillCreditCardControllerRobolectricTest() { + mCoordinator = new TouchToFillCreditCardCoordinator(); + mContext = Robolectric.buildActivity(Activity.class).get(); + } + + @Before + public void setUp() { + mCoordinator.initialize(mContext, mBottomSheetController, mDelegateMock); + mTouchToFillCreditCardModel = + mCoordinator.getTouchToFillCreditCardPropertyModelForTesting(); + } + + @Test + public void testScanNewCard() { + mCoordinator.showSheet(true); + Runnable scanNewCardCallback = mTouchToFillCreditCardModel.get( + TouchToFillCreditCardProperties.SCAN_CREDIT_CARD_CALLBACK); + scanNewCardCallback.run(); + verify(mDelegateMock).scanCreditCard(); + } +}
diff --git a/chrome/browser/touch_to_fill/payments/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardCoordinator.java b/chrome/browser/touch_to_fill/payments/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardCoordinator.java index 429786c..90aff50 100644 --- a/chrome/browser/touch_to_fill/payments/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardCoordinator.java +++ b/chrome/browser/touch_to_fill/payments/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardCoordinator.java
@@ -18,23 +18,28 @@ */ public class TouchToFillCreditCardCoordinator implements TouchToFillCreditCardComponent { private final TouchToFillCreditCardMediator mMediator = new TouchToFillCreditCardMediator(); + private PropertyModel mTouchToFillCreditCardModel; @Override public void initialize(Context context, BottomSheetController sheetController, TouchToFillCreditCardComponent.Delegate delegate) { - PropertyModel model = new PropertyModel.Builder(TouchToFillCreditCardProperties.ALL_KEYS) - .with(TouchToFillCreditCardProperties.VISIBLE, false) - .with(TouchToFillCreditCardProperties.DISMISS_HANDLER, - mMediator::onDismissed) - .build(); + mTouchToFillCreditCardModel = + new PropertyModel.Builder(TouchToFillCreditCardProperties.ALL_KEYS) + .with(TouchToFillCreditCardProperties.VISIBLE, false) + .with(TouchToFillCreditCardProperties.DISMISS_HANDLER, + mMediator::onDismissed) + .with(TouchToFillCreditCardProperties.SCAN_CREDIT_CARD_CALLBACK, + mMediator::scanCreditCard) + .build(); - mMediator.initialize(delegate, model); - setUpModelChangeProcessors(model, new TouchToFillCreditCardView(context, sheetController)); + mMediator.initialize(delegate, mTouchToFillCreditCardModel); + setUpModelChangeProcessors(mTouchToFillCreditCardModel, + new TouchToFillCreditCardView(context, sheetController)); } @Override - public void showSheet() { - mMediator.showSheet(); + public void showSheet(boolean shouldShowScanCreditCard) { + mMediator.showSheet(shouldShowScanCreditCard); } @Override @@ -52,4 +57,9 @@ PropertyModelChangeProcessor.create( model, view, TouchToFillCreditCardViewBinder::bindTouchToFillCreditCardView); } + + @VisibleForTesting + PropertyModel getTouchToFillCreditCardPropertyModelForTesting() { + return mTouchToFillCreditCardModel; + } }
diff --git a/chrome/browser/touch_to_fill/payments/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardMediator.java b/chrome/browser/touch_to_fill/payments/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardMediator.java index 739431e..26c58ff5 100644 --- a/chrome/browser/touch_to_fill/payments/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardMediator.java +++ b/chrome/browser/touch_to_fill/payments/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardMediator.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser.touch_to_fill.payments; +import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillCreditCardProperties.SHOULD_SHOW_SCAN_CREDIT_CARD; import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillCreditCardProperties.VISIBLE; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; @@ -24,8 +25,9 @@ mModel = model; } - void showSheet() { + void showSheet(boolean shouldShowScanCreditCard) { mModel.set(VISIBLE, true); + mModel.set(SHOULD_SHOW_SCAN_CREDIT_CARD, shouldShowScanCreditCard); } void hideSheet() { @@ -37,4 +39,8 @@ mModel.set(VISIBLE, false); mDelegate.onDismissed(); } + + public void scanCreditCard() { + mDelegate.scanCreditCard(); + } }
diff --git a/chrome/browser/touch_to_fill/payments/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardProperties.java b/chrome/browser/touch_to_fill/payments/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardProperties.java index db84708..3703887 100644 --- a/chrome/browser/touch_to_fill/payments/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardProperties.java +++ b/chrome/browser/touch_to_fill/payments/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardProperties.java
@@ -7,6 +7,7 @@ import org.chromium.base.Callback; import org.chromium.ui.modelutil.PropertyKey; import org.chromium.ui.modelutil.PropertyModel; +import org.chromium.ui.modelutil.PropertyModel.ReadableObjectPropertyKey; /** * Properties defined here reflect the visible state of the TouchToFillCreditCard component. @@ -16,6 +17,11 @@ new PropertyModel.WritableBooleanPropertyKey("visible"); static final PropertyModel.ReadableObjectPropertyKey<Callback<Integer>> DISMISS_HANDLER = new PropertyModel.ReadableObjectPropertyKey<>("dismiss_handler"); + static final PropertyModel.WritableBooleanPropertyKey SHOULD_SHOW_SCAN_CREDIT_CARD = + new PropertyModel.WritableBooleanPropertyKey("should_show_scan_credit_card"); + static final PropertyModel.ReadableObjectPropertyKey<Runnable> SCAN_CREDIT_CARD_CALLBACK = + new ReadableObjectPropertyKey<>("scan_credit_card_callback"); - static final PropertyKey[] ALL_KEYS = {VISIBLE, DISMISS_HANDLER}; + static final PropertyKey[] ALL_KEYS = { + VISIBLE, DISMISS_HANDLER, SHOULD_SHOW_SCAN_CREDIT_CARD, SCAN_CREDIT_CARD_CALLBACK}; }
diff --git a/chrome/browser/touch_to_fill/payments/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardView.java b/chrome/browser/touch_to_fill/payments/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardView.java index 8575af8..0c3d842 100644 --- a/chrome/browser/touch_to_fill/payments/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardView.java +++ b/chrome/browser/touch_to_fill/payments/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardView.java
@@ -29,6 +29,7 @@ private final BottomSheetController mBottomSheetController; private final RelativeLayout mContentView; private Callback<Integer> mDismissHandler; + private Runnable mScanCreditCardHandler; // TODO(): show gpay logo if there is at least one card coming from GPay, // if there are only local cards show chrome logo private boolean mOnlyLocalCards; @@ -69,6 +70,17 @@ ContextUtils.getApplicationContext().getTheme())); } + void setScanCreditCardButton(boolean shouldShowScanCreditCard) { + View scanCreditCard = mContentView.findViewById(R.id.scan_new_card); + if (shouldShowScanCreditCard) { + scanCreditCard.setVisibility(View.VISIBLE); + scanCreditCard.setOnClickListener(unused -> mScanCreditCardHandler.run()); + } else { + scanCreditCard.setVisibility(View.GONE); + scanCreditCard.setOnClickListener(null); + } + } + /** * Sets a new listener that reacts to a dismisal event. * @@ -78,6 +90,10 @@ mDismissHandler = dismissHandler; } + void setScanCreditCardCallback(Runnable callback) { + mScanCreditCardHandler = callback; + } + /** * If set to true, requests to show the bottom sheet. Otherwise, requests to hide the sheet. *
diff --git a/chrome/browser/touch_to_fill/payments/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardViewBinder.java b/chrome/browser/touch_to_fill/payments/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardViewBinder.java index 1cca5a2..0c9b810 100644 --- a/chrome/browser/touch_to_fill/payments/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardViewBinder.java +++ b/chrome/browser/touch_to_fill/payments/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardViewBinder.java
@@ -5,6 +5,8 @@ package org.chromium.chrome.browser.touch_to_fill.payments; import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillCreditCardProperties.DISMISS_HANDLER; +import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillCreditCardProperties.SCAN_CREDIT_CARD_CALLBACK; +import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillCreditCardProperties.SHOULD_SHOW_SCAN_CREDIT_CARD; import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillCreditCardProperties.VISIBLE; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; @@ -26,6 +28,10 @@ PropertyModel model, TouchToFillCreditCardView view, PropertyKey propertyKey) { if (propertyKey == DISMISS_HANDLER) { view.setDismissHandler(model.get(DISMISS_HANDLER)); + } else if (propertyKey == SHOULD_SHOW_SCAN_CREDIT_CARD) { + view.setScanCreditCardButton(model.get(SHOULD_SHOW_SCAN_CREDIT_CARD)); + } else if (propertyKey == SCAN_CREDIT_CARD_CALLBACK) { + view.setScanCreditCardCallback(model.get(SCAN_CREDIT_CARD_CALLBACK)); } else if (propertyKey == VISIBLE) { boolean visibilityChangeSuccessful = view.setVisible(model.get(VISIBLE)); if (!visibilityChangeSuccessful && model.get(VISIBLE)) {
diff --git a/chrome/browser/touch_to_fill/payments/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardViewBridge.java b/chrome/browser/touch_to_fill/payments/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardViewBridge.java index 1841df7..dcd564c 100644 --- a/chrome/browser/touch_to_fill/payments/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardViewBridge.java +++ b/chrome/browser/touch_to_fill/payments/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardViewBridge.java
@@ -43,8 +43,9 @@ } @CalledByNative - private void showSheet(PersonalDataManager.CreditCard[] cards) { - mComponent.showSheet(); + private void showSheet( + PersonalDataManager.CreditCard[] cards, boolean shouldShowScanCreditCard) { + mComponent.showSheet(shouldShowScanCreditCard); } @CalledByNative
diff --git a/chrome/browser/touch_to_fill/payments/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardViewTest.java b/chrome/browser/touch_to_fill/payments/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardViewTest.java new file mode 100644 index 0000000..115d790 --- /dev/null +++ b/chrome/browser/touch_to_fill/payments/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardViewTest.java
@@ -0,0 +1,91 @@ +// Copyright 2022 The Chromium Authors +// 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.touch_to_fill.payments; + +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.action.ViewActions.click; +import static androidx.test.espresso.assertion.ViewAssertions.matches; +import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; +import static androidx.test.espresso.matcher.ViewMatchers.withId; + +import static org.hamcrest.Matchers.not; +import static org.mockito.Mockito.verify; + +import static org.chromium.content_public.browser.test.util.TestThreadUtils.runOnUiThreadBlocking; + +import androidx.test.filters.MediumTest; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.mockito.quality.Strictness; + +import org.chromium.base.test.util.Batch; +import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.chrome.browser.flags.ChromeSwitches; +import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.ChromeTabbedActivityTestRule; +import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; +import org.chromium.components.browser_ui.bottomsheet.BottomSheetController.SheetState; +import org.chromium.components.browser_ui.bottomsheet.BottomSheetTestSupport; + +/** Tests for {@link TouchToFillCreditCardView} */ +@RunWith(ChromeJUnit4ClassRunner.class) +@Batch(Batch.PER_CLASS) +@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) +public class TouchToFillCreditCardViewTest { + private BottomSheetController mBottomSheetController; + private BottomSheetTestSupport mSheetSupport; + private TouchToFillCreditCardCoordinator mCoordinator; + + @Rule + public final MockitoRule mMockitoRule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS); + + @Mock + private TouchToFillCreditCardComponent.Delegate mDelegateMock; + + @Rule + public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); + + @Before + public void setupTest() throws InterruptedException { + mActivityTestRule.startMainActivityOnBlankPage(); + mBottomSheetController = mActivityTestRule.getActivity() + .getRootUiCoordinatorForTesting() + .getBottomSheetController(); + mSheetSupport = new BottomSheetTestSupport(mBottomSheetController); + runOnUiThreadBlocking(() -> { + mCoordinator = new TouchToFillCreditCardCoordinator(); + mCoordinator.initialize( + mActivityTestRule.getActivity(), mBottomSheetController, mDelegateMock); + }); + } + + @Test + @MediumTest + public void testScanNewCardButtonIsHidden() { + runOnUiThreadBlocking(() -> mCoordinator.showSheet(false)); + BottomSheetTestSupport.waitForOpen(mBottomSheetController); + runOnUiThreadBlocking(() -> { mSheetSupport.setSheetState(SheetState.FULL, false); }); + + onView(withId(R.id.scan_new_card)).check(matches(not(isDisplayed()))); + } + + @Test + @MediumTest + public void testScanNewCardClick() { + runOnUiThreadBlocking(() -> mCoordinator.showSheet(true)); + BottomSheetTestSupport.waitForOpen(mBottomSheetController); + runOnUiThreadBlocking(() -> { mSheetSupport.setSheetState(SheetState.FULL, false); }); + + onView(withId(R.id.scan_new_card)).perform(click()); + + verify(mDelegateMock).scanCreditCard(); + } +}
diff --git a/chrome/browser/touch_to_fill/payments/android/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardComponent.java b/chrome/browser/touch_to_fill/payments/android/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardComponent.java index 688e778d..bf802561 100644 --- a/chrome/browser/touch_to_fill/payments/android/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardComponent.java +++ b/chrome/browser/touch_to_fill/payments/android/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillCreditCardComponent.java
@@ -21,6 +21,11 @@ * Called whenever the sheet is dismissed (by user or native). */ void onDismissed(); + + /** + * Called when user requests to scan a new credit card. + */ + void scanCreditCard(); } /** @@ -34,7 +39,7 @@ /** * Displays a new bottom sheet. */ - void showSheet(); + void showSheet(boolean shouldShowScanCreditCard); /** * Hides the bottom sheet if shown.
diff --git a/chrome/browser/touch_to_fill/payments/android/touch_to_fill_credit_card_controller.cc b/chrome/browser/touch_to_fill/payments/android/touch_to_fill_credit_card_controller.cc index 39d6113..95e022f 100644 --- a/chrome/browser/touch_to_fill/payments/android/touch_to_fill_credit_card_controller.cc +++ b/chrome/browser/touch_to_fill/payments/android/touch_to_fill_credit_card_controller.cc
@@ -3,7 +3,6 @@ // found in the LICENSE file. #include "chrome/browser/touch_to_fill/payments/android/touch_to_fill_credit_card_controller.h" - #include "chrome/browser/touch_to_fill/payments/android/jni_headers/TouchToFillCreditCardControllerBridge_jni.h" #include "chrome/browser/touch_to_fill/payments/android/touch_to_fill_credit_card_view.h" #include "components/autofill/content/browser/content_autofill_driver.h" @@ -27,7 +26,8 @@ if (view_) return false; - if (!view->Show(this, std::move(cards_to_suggest))) { + if (!view->Show(this, std::move(cards_to_suggest), + delegate->ShouldShowScanCreditCard())) { java_object_.Reset(); return false; } @@ -57,6 +57,10 @@ java_object_.Reset(); } +void TouchToFillCreditCardController::ScanCreditCard(JNIEnv* env) { + delegate_->ScanCreditCard(); +} + base::android::ScopedJavaLocalRef<jobject> TouchToFillCreditCardController::GetJavaObject() { if (!java_object_) {
diff --git a/chrome/browser/touch_to_fill/payments/android/touch_to_fill_credit_card_controller.h b/chrome/browser/touch_to_fill/payments/android/touch_to_fill_credit_card_controller.h index 344c49e..8ccb2ce 100644 --- a/chrome/browser/touch_to_fill/payments/android/touch_to_fill_credit_card_controller.h +++ b/chrome/browser/touch_to_fill/payments/android/touch_to_fill_credit_card_controller.h
@@ -43,13 +43,16 @@ // Hides the surface if it is currently shown. void Hide(); + // TouchToFillCreditCardViewController: + // Called whenever the surface gets hidden (regardless of the cause). + void OnDismissed(JNIEnv* env) override; + // Calls credit card scanner + void ScanCreditCard(JNIEnv* env) override; + private: // Called after the surface gets shown or hidden. void SetShouldSuppressKeyboard(bool suppress); - // TouchToFillCreditCardViewController: - // Called whenever the surface gets hidden (regardless of the cause). - void OnDismissed(JNIEnv* env) override; // Gets or creates the Java counterpart. base::android::ScopedJavaLocalRef<jobject> GetJavaObject() override;
diff --git a/chrome/browser/touch_to_fill/payments/android/touch_to_fill_credit_card_controller_unittest.cc b/chrome/browser/touch_to_fill/payments/android/touch_to_fill_credit_card_controller_unittest.cc index 84f04b4..85b66f8 100644 --- a/chrome/browser/touch_to_fill/payments/android/touch_to_fill_credit_card_controller_unittest.cc +++ b/chrome/browser/touch_to_fill/payments/android/touch_to_fill_credit_card_controller_unittest.cc
@@ -7,7 +7,9 @@ #include "chrome/browser/touch_to_fill/payments/android/touch_to_fill_credit_card_controller.h" #include "chrome/browser/touch_to_fill/payments/android/touch_to_fill_credit_card_view.h" +#include "chrome/browser/touch_to_fill/payments/android/touch_to_fill_credit_card_view_controller.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" +#include "components/autofill/content/browser/content_autofill_driver.h" #include "components/autofill/core/browser/autofill_driver.h" #include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/browser/data_model/autofill_profile.h" @@ -19,25 +21,42 @@ namespace { using ::autofill::CreditCard; using ::testing::ElementsAreArray; +using ::testing::Return; class MockTouchToFillCreditCardViewImpl : public autofill::TouchToFillCreditCardView { public: - MockTouchToFillCreditCardViewImpl() = default; + MockTouchToFillCreditCardViewImpl() { + ON_CALL(*this, Show).WillByDefault(Return(true)); + } ~MockTouchToFillCreditCardViewImpl() override = default; MOCK_METHOD(bool, Show, (autofill::TouchToFillCreditCardViewController * controller, - base::span<const autofill::CreditCard* const> cards_to_suggest)); + base::span<const autofill::CreditCard* const> cards_to_suggest, + bool should_show_scan_credit_card)); MOCK_METHOD(void, Hide, ()); }; -// virtual AutofillDriver* GetDriver() +class MockContentAutofillDriver : public autofill::ContentAutofillDriver { + public: + MockContentAutofillDriver() + : autofill::ContentAutofillDriver(nullptr, nullptr) {} + MockContentAutofillDriver(const MockContentAutofillDriver&) = delete; + MockContentAutofillDriver& operator=(const MockContentAutofillDriver&) = + delete; + ~MockContentAutofillDriver() override = default; + + MOCK_METHOD(void, SetShouldSuppressKeyboard, (bool), (override)); +}; class MockTouchToFillDelegateImpl : public autofill::TouchToFillDelegate { public: - MockTouchToFillDelegateImpl() = default; + MockTouchToFillDelegateImpl() { + ON_CALL(*this, GetDriver).WillByDefault(Return(&driver_)); + ON_CALL(*this, ShouldShowScanCreditCard).WillByDefault(Return(true)); + } ~MockTouchToFillDelegateImpl() override = default; base::WeakPtr<MockTouchToFillDelegateImpl> GetWeakPointer() { @@ -50,8 +69,12 @@ const autofill::FormData& form, const autofill::FormFieldData& field)); MOCK_METHOD(autofill::AutofillDriver*, GetDriver, (), (override)); + MOCK_METHOD(bool, ShouldShowScanCreditCard, (), (override)); + MOCK_METHOD(void, ScanCreditCard, (), (override)); + MOCK_METHOD(void, OnCreditCardScanned, (const CreditCard& card), (override)); private: + MockContentAutofillDriver driver_; base::WeakPtrFactory<MockTouchToFillDelegateImpl> weak_factory_{this}; }; @@ -71,20 +94,27 @@ std::unique_ptr<MockTouchToFillCreditCardViewImpl> mock_view_; MockTouchToFillDelegateImpl mock_delegate_; + const CreditCard credit_card1_ = autofill::test::GetCreditCard(); + const CreditCard credit_card2_ = autofill::test::GetCreditCard2(); + const std::vector<const autofill::CreditCard*> credit_cards_ = { + &credit_card1_, &credit_card2_}; // The object to be tested. autofill::TouchToFillCreditCardController credit_card_controller_; }; TEST_F(TouchToFillCreditCardControllerTest, ShowPassesCardsToTheView) { - CreditCard credit_card1 = autofill::test::GetCreditCard(); - CreditCard credit_card2 = autofill::test::GetCreditCard2(); - std::vector<autofill::CreditCard*> credit_cards = {&credit_card1, - &credit_card2}; - // Test that the cards have ptopagated to the view. EXPECT_CALL(*mock_view_, - Show(&credit_card_controller_, ElementsAreArray(credit_cards))); + Show(&credit_card_controller_, ElementsAreArray(credit_cards_), + testing::Eq(true))); credit_card_controller_.Show(std::move(mock_view_), - mock_delegate_.GetWeakPointer(), credit_cards); + mock_delegate_.GetWeakPointer(), credit_cards_); +} + +TEST_F(TouchToFillCreditCardControllerTest, ScanCreditCardIsCalled) { + credit_card_controller_.Show(std::move(mock_view_), + mock_delegate_.GetWeakPointer(), credit_cards_); + EXPECT_CALL(mock_delegate_, ScanCreditCard); + credit_card_controller_.ScanCreditCard(nullptr); }
diff --git a/chrome/browser/touch_to_fill/payments/android/touch_to_fill_credit_card_view.h b/chrome/browser/touch_to_fill/payments/android/touch_to_fill_credit_card_view.h index 88fdeddd..2cbdce60 100644 --- a/chrome/browser/touch_to_fill/payments/android/touch_to_fill_credit_card_view.h +++ b/chrome/browser/touch_to_fill/payments/android/touch_to_fill_credit_card_view.h
@@ -20,7 +20,8 @@ virtual bool Show( TouchToFillCreditCardViewController* controller, - base::span<const autofill::CreditCard* const> cards_to_suggest) = 0; + base::span<const autofill::CreditCard* const> cards_to_suggest, + bool should_show_scan_credit_card) = 0; virtual void Hide() = 0; };
diff --git a/chrome/browser/touch_to_fill/payments/android/touch_to_fill_credit_card_view_controller.h b/chrome/browser/touch_to_fill/payments/android/touch_to_fill_credit_card_view_controller.h index 5d3dfc54..2b833c4a 100644 --- a/chrome/browser/touch_to_fill/payments/android/touch_to_fill_credit_card_view_controller.h +++ b/chrome/browser/touch_to_fill/payments/android/touch_to_fill_credit_card_view_controller.h
@@ -15,6 +15,7 @@ virtual ~TouchToFillCreditCardViewController() = default; virtual void OnDismissed(JNIEnv* env) = 0; + virtual void ScanCreditCard(JNIEnv* env) = 0; virtual base::android::ScopedJavaLocalRef<jobject> GetJavaObject() = 0; };
diff --git a/chrome/browser/touch_to_fill/payments/android/touch_to_fill_credit_card_view_impl.cc b/chrome/browser/touch_to_fill/payments/android/touch_to_fill_credit_card_view_impl.cc index 07d7c4a..d7d3cc2b 100644 --- a/chrome/browser/touch_to_fill/payments/android/touch_to_fill_credit_card_view_impl.cc +++ b/chrome/browser/touch_to_fill/payments/android/touch_to_fill_credit_card_view_impl.cc
@@ -28,7 +28,8 @@ bool TouchToFillCreditCardViewImpl::Show( TouchToFillCreditCardViewController* controller, - base::span<const autofill::CreditCard* const> cards_to_suggest) { + base::span<const autofill::CreditCard* const> cards_to_suggest, + bool should_show_scan_credit_card) { if (java_object_) return false; // Already shown. @@ -59,8 +60,8 @@ PersonalDataManagerAndroid::CreateJavaCreditCardFromNative( env, *cards_to_suggest[i])); } - Java_TouchToFillCreditCardViewBridge_showSheet(env, java_object_, - credit_cards_array); + Java_TouchToFillCreditCardViewBridge_showSheet( + env, java_object_, credit_cards_array, should_show_scan_credit_card); return true; }
diff --git a/chrome/browser/touch_to_fill/payments/android/touch_to_fill_credit_card_view_impl.h b/chrome/browser/touch_to_fill/payments/android/touch_to_fill_credit_card_view_impl.h index 2f3252dc..ed9a669 100644 --- a/chrome/browser/touch_to_fill/payments/android/touch_to_fill_credit_card_view_impl.h +++ b/chrome/browser/touch_to_fill/payments/android/touch_to_fill_credit_card_view_impl.h
@@ -31,9 +31,9 @@ private: // TouchToFillCreditCardView: - bool Show( - TouchToFillCreditCardViewController* controller, - base::span<const autofill::CreditCard* const> cards_to_suggest) override; + bool Show(TouchToFillCreditCardViewController* controller, + base::span<const autofill::CreditCard* const> cards_to_suggest, + bool should_show_scan_credit_card) override; void Hide() override; // The corresponding Java TouchToFillCreditCardViewBridge.
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index c9164ad..5246977 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -3781,8 +3781,6 @@ "cocoa/javascript_app_modal_dialog_cocoa.mm", "cocoa/key_equivalent_constants.h", "cocoa/key_equivalent_constants.mm", - "cocoa/keystone_infobar_delegate.h", - "cocoa/keystone_infobar_delegate.mm", "cocoa/l10n_util.h", "cocoa/l10n_util.mm", "cocoa/last_active_browser_cocoa.cc", @@ -3869,6 +3867,13 @@ "window_sizer/window_sizer_mac.mm", ] + if (enable_updater) { + sources += [ + "cocoa/keystone_infobar_delegate.h", + "cocoa/keystone_infobar_delegate.mm", + ] + } + allow_circular_includes_from += [ "//chrome/browser/apps/app_shim" ] deps += [
diff --git a/chrome/browser/ui/app_list/search/app_result.cc b/chrome/browser/ui/app_list/search/app_result.cc index ae18023..1ac0fbc 100644 --- a/chrome/browser/ui/app_list/search/app_result.cc +++ b/chrome/browser/ui/app_list/search/app_result.cc
@@ -16,7 +16,7 @@ : profile_(profile), app_id_(app_id), controller_(controller) { - SetDisplayType(ash::SearchResultDisplayType::kTile); + SetDisplayType(ash::SearchResultDisplayType::kList); SetResultType(ash::AppListSearchResultType::kInstalledApp); SetMetricsType(ash::SEARCH_RESULT_TYPE_BOUNDARY); SetIsRecommendation(is_recommendation);
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.cc b/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.cc index d9afa414..3b4b722c 100644 --- a/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.cc +++ b/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.cc
@@ -46,7 +46,7 @@ SetCategory(Category::kAppShortcuts); SetAccessibleName(ComputeAccessibleName()); SetResultType(ash::AppListSearchResultType::kArcAppShortcut); - SetDisplayType(ash::SearchResultDisplayType::kTile); + SetDisplayType(ash::SearchResultDisplayType::kList); SetMetricsType(ash::PLAY_STORE_APP_SHORTCUT); SetIsRecommendation(is_recommendation);
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider_unittest.cc b/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider_unittest.cc index 46f809d6..1683755e 100644 --- a/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider_unittest.cc +++ b/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider_unittest.cc
@@ -121,7 +121,7 @@ for (size_t i = 0; i < results.size(); ++i) { EXPECT_EQ(base::StringPrintf("ShortLabel %zu", i), base::UTF16ToUTF8(results[i]->title())); - EXPECT_EQ(ash::SearchResultDisplayType::kTile, results[i]->display_type()); + EXPECT_EQ(ash::SearchResultDisplayType::kList, results[i]->display_type()); } }
diff --git a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider_unittest.cc b/chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider_unittest.cc index 2ce6769..4420e57 100644 --- a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider_unittest.cc +++ b/chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider_unittest.cc
@@ -108,7 +108,7 @@ SCOPED_TRACE(base::StringPrintf("Testing result %zu", i)); EXPECT_EQ(results[i]->title(), base::StrCat({kQuery, u" ", base::NumberToString16(i)})); - EXPECT_EQ(results[i]->display_type(), ash::SearchResultDisplayType::kTile); + EXPECT_EQ(results[i]->display_type(), ash::SearchResultDisplayType::kList); EXPECT_EQ(base::UTF16ToUTF8(results[i]->formatted_price()), base::StringPrintf("$%zu.22", i)); EXPECT_EQ(results[i]->rating(), i); @@ -149,7 +149,7 @@ SCOPED_TRACE(base::StringPrintf("Testing result %zu", i)); EXPECT_EQ(results[i]->title(), base::StrCat({kQuery, u" ", base::NumberToString16(i)})); - EXPECT_EQ(results[i]->display_type(), ash::SearchResultDisplayType::kTile); + EXPECT_EQ(results[i]->display_type(), ash::SearchResultDisplayType::kList); EXPECT_EQ(base::UTF16ToUTF8(results[i]->formatted_price()), base::StringPrintf("$%zu.22", i)); EXPECT_EQ(results[i]->rating(), i); @@ -186,7 +186,7 @@ SCOPED_TRACE(base::StringPrintf("Testing result %zu", i)); EXPECT_EQ(results[i]->title(), base::StrCat({kQuery, u" ", base::NumberToString16(i)})); - EXPECT_EQ(results[i]->display_type(), ash::SearchResultDisplayType::kTile); + EXPECT_EQ(results[i]->display_type(), ash::SearchResultDisplayType::kList); EXPECT_EQ(base::UTF16ToUTF8(results[i]->formatted_price()), ""); EXPECT_EQ(results[i]->rating(), -1); const bool is_instant_app = i % 2 == 0; @@ -223,7 +223,7 @@ SCOPED_TRACE(base::StringPrintf("Testing result %zu", i)); EXPECT_EQ(results[i]->title(), base::StrCat({kQuery, u" ", base::NumberToString16(i)})); - EXPECT_EQ(results[i]->display_type(), ash::SearchResultDisplayType::kTile); + EXPECT_EQ(results[i]->display_type(), ash::SearchResultDisplayType::kList); EXPECT_EQ(base::UTF16ToUTF8(results[i]->formatted_price()), base::StringPrintf("$%zu.22", i)); EXPECT_EQ(results[i]->rating(), i);
diff --git a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.cc b/chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.cc index a2232384..4b96fae 100644 --- a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.cc +++ b/chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.cc
@@ -110,7 +110,7 @@ set_id(kPlayAppPrefix + crx_file::id_util::GenerateId(install_intent_uri().value())); SetCategory(Category::kPlayStore); - SetDisplayType(ash::SearchResultDisplayType::kTile); + SetDisplayType(ash::SearchResultDisplayType::kList); // TODO: The badge icon should be updated to pass through a vector icon and // color id rather than hardcoding the colors here. This will require // tweaking sizes/paddings so we can set use_badge_icon_background to true and
diff --git a/chrome/browser/ui/app_list/search/common/types_util.cc b/chrome/browser/ui/app_list/search/common/types_util.cc index 56a3a96..21dcebce 100644 --- a/chrome/browser/ui/app_list/search/common/types_util.cc +++ b/chrome/browser/ui/app_list/search/common/types_util.cc
@@ -180,12 +180,8 @@ return "None"; case ash::SearchResultDisplayType::kList: return "List"; - case ash::SearchResultDisplayType::kTile: - return "Tile"; case ash::SearchResultDisplayType::kAnswerCard: return "AnswerCard"; - case ash::SearchResultDisplayType::kChip: - return "Chip"; case ash::SearchResultDisplayType::kContinue: return "Continue"; case ash::SearchResultDisplayType::kRecentApps:
diff --git a/chrome/browser/ui/app_list/search/files/file_result.cc b/chrome/browser/ui/app_list/search/files/file_result.cc index 134a583..021fb73 100644 --- a/chrome/browser/ui/app_list/search/files/file_result.cc +++ b/chrome/browser/ui/app_list/search/files/file_result.cc
@@ -254,9 +254,7 @@ dark_light_mode_controller->IsDarkModeEnabled(); const bool dark_background = !is_dark_light_enabled || is_dark_mode_enabled; - if (display_type() == DisplayType::kChip) { - SetChipIcon(chromeos::GetChipIconForPath(filepath_, dark_background)); - } else if (display_type() == DisplayType::kContinue) { + if (display_type() == DisplayType::kContinue) { // For Continue Section, if dark/light mode is disabled, we should use the // icon and not the chip icon with a dark background as default. const gfx::ImageSkia chip_icon =
diff --git a/chrome/browser/ui/app_list/search/files/file_result_unittest.cc b/chrome/browser/ui/app_list/search/files/file_result_unittest.cc index 030bbe5..b6b0a5ad 100644 --- a/chrome/browser/ui/app_list/search/files/file_result_unittest.cc +++ b/chrome/browser/ui/app_list/search/files/file_result_unittest.cc
@@ -100,15 +100,6 @@ } TEST_F(FileResultTest, Icons) { - const base::FilePath chipPath("/my/test/file.Pdf"); - FileResult chipResult( - /*id=*/"zero_state_file://" + chipPath.value(), chipPath, u"some details", - ash::AppListSearchResultType::kZeroStateFile, - ash::SearchResultDisplayType::kChip, 0.2f, std::u16string(), - FileResult::Type::kFile, profile_.get()); - EXPECT_FALSE(chipResult.chip_icon().isNull()); - EXPECT_TRUE(chipResult.icon().icon.isNull()); - const base::FilePath excelPath("/my/test/mySheet.xlsx"); FileResult fileResult( /*id=*/"zero_state_file://" + excelPath.value(), excelPath,
diff --git a/chrome/browser/ui/app_list/search/help_app_zero_state_provider.cc b/chrome/browser/ui/app_list/search/help_app_zero_state_provider.cc index 3e9d0dc..8de2760d 100644 --- a/chrome/browser/ui/app_list/search/help_app_zero_state_provider.cc +++ b/chrome/browser/ui/app_list/search/help_app_zero_state_provider.cc
@@ -176,8 +176,7 @@ ash::AppListNotifier::Location location, const std::vector<ash::AppListNotifier::Result>& results, const std::u16string& query) { - if (location != ash::AppListNotifier::Location::kChip && - location != ash::AppListNotifier::Location::kContinue) { + if (location != ash::AppListNotifier::Location::kContinue) { return; }
diff --git a/chrome/browser/ui/app_list/search/search_controller_impl.cc b/chrome/browser/ui/app_list/search/search_controller_impl.cc index ab036ac..970c5bc 100644 --- a/chrome/browser/ui/app_list/search/search_controller_impl.cc +++ b/chrome/browser/ui/app_list/search/search_controller_impl.cc
@@ -314,14 +314,6 @@ std::vector<ChromeSearchResult*> all_results; for (const auto& type_results : results_) { for (const auto& result : type_results.second) { - // TODO(crbug.com/1385194): Category-based search combines apps into the - // results list, so redirect any kTile results to kList before updating - // the UI. Once SearchControllerImpl is the only search controller, - // this can be removed and all results can be created as kList. - if (result->display_type() == ash::SearchResultDisplayType::kTile) { - result->SetDisplayType(ash::SearchResultDisplayType::kList); - } - double score = result->scoring().FinalScore(); // Filter out results with negative relevance, which is the rankers'
diff --git a/chrome/browser/ui/app_list/search/search_metrics_manager.cc b/chrome/browser/ui/app_list/search/search_metrics_manager.cc index 13b652e3..fb0b1f7 100644 --- a/chrome/browser/ui/app_list/search/search_metrics_manager.cc +++ b/chrome/browser/ui/app_list/search/search_metrics_manager.cc
@@ -33,12 +33,8 @@ switch (location) { case Location::kList: return query.empty() ? "ListZeroState" : "ListSearch"; - case Location::kTile: - return query.empty() ? "AppsZeroState" : "AppsSearch"; case Location::kAnswerCard: return "AnswerCard"; - case Location::kChip: - return "Chip"; case Location::kRecentApps: return "RecentApps"; case Location::kContinue:
diff --git a/chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view.cc b/chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view.cc index 1cbd666a..c77b09e 100644 --- a/chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view.cc +++ b/chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view.cc
@@ -159,23 +159,12 @@ gfx::NativeWindow native_window, ::sharesheet::SharesheetServiceDelegator* delegator) : delegator_(delegator) { - CHECK(native_window); - CHECK(delegator); - SetID(SHARESHEET_BUBBLE_VIEW_ID); - // We set the dialog role because views::BubbleDialogDelegate defaults this to - // an alert dialog. This would make screen readers announce all of this dialog - // which is undesirable. - SetAccessibleRole(ax::mojom::Role::kDialog); - SetAccessibleTitle(l10n_util::GetStringUTF16(IDS_SHARESHEET_TITLE_LABEL)); - set_parent_window(native_window); - views::Widget* const widget = - views::Widget::GetWidgetForNativeWindow(native_window); - CHECK(widget); - parent_view_ = widget->GetRootView(); - CHECK(this); - parent_widget_observer_ = - std::make_unique<SharesheetParentWidgetObserver>(this, widget); - AddAccelerator(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE)); + PerformLoggingAndChecks(native_window); + + SetUpDialog(); + + SetUpParentWindow(native_window); + CreateBubble(); } @@ -474,6 +463,48 @@ CloseWidgetWithAnimateFadeOut(reason); } +// --- Added for debugging purposes. Remove after bug fixed. + +void SharesheetBubbleView::PerformLoggingAndChecks( + gfx::NativeWindow native_window) { + if (!native_window) { + LOG(ERROR) << "Native_window value is null"; + } + CHECK(native_window); + if (!delegator_) { + LOG(ERROR) << "Delegator value is null"; + } + CHECK(delegator_); +} + +void SharesheetBubbleView::SetUpDialog() { + SetID(SHARESHEET_BUBBLE_VIEW_ID); + // We set the dialog role because views::BubbleDialogDelegate defaults this to + // an alert dialog. This would make screen readers announce all of this dialog + // which is undesirable. + SetAccessibleRole(ax::mojom::Role::kDialog); + SetAccessibleTitle(l10n_util::GetStringUTF16(IDS_SHARESHEET_TITLE_LABEL)); + AddAccelerator(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE)); +} + +void SharesheetBubbleView::SetUpParentWindow(gfx::NativeWindow native_window) { + set_parent_window(native_window); + views::Widget* const widget = + views::Widget::GetWidgetForNativeWindow(native_window); + if (!widget) { + LOG(ERROR) << "Widget value is null"; + } + if (!widget->GetRootView()) { + LOG(ERROR) << "Widget RootView value is null"; + } + CHECK(widget); + parent_view_ = widget->GetRootView(); + parent_widget_observer_ = + std::make_unique<SharesheetParentWidgetObserver>(this, widget); +} + +// --- End of functions added for debugging. + bool SharesheetBubbleView::AcceleratorPressed( const ui::Accelerator& accelerator) { // We override this because when this is handled by the base class,
diff --git a/chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view.h b/chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view.h index 8c944fe..0315916 100644 --- a/chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view.h +++ b/chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view.h
@@ -7,6 +7,7 @@ #include <vector> +#include "ash/ash_export.h" #include "ash/public/cpp/tablet_mode.h" #include "ash/public/cpp/tablet_mode_observer.h" #include "chrome/browser/sharesheet/sharesheet_types.h" @@ -57,6 +58,14 @@ void ResizeBubble(const int& width, const int& height); void CloseBubble(views::Widget::ClosedReason reason); + // --- Added for debugging purposes. Remove after bug fixed. + + ASH_EXPORT void PerformLoggingAndChecks(gfx::NativeWindow native_window); + ASH_EXPORT void SetUpDialog(); + ASH_EXPORT void SetUpParentWindow(gfx::NativeWindow native_window); + + // --- End of functions added for debugging. + private: class SharesheetParentWidgetObserver;
diff --git a/chrome/browser/ui/profile_picker.cc b/chrome/browser/ui/profile_picker.cc index 7e248a24..bcabd50 100644 --- a/chrome/browser/ui/profile_picker.cc +++ b/chrome/browser/ui/profile_picker.cc
@@ -50,8 +50,7 @@ #if BUILDFLAG(IS_CHROMEOS_LACROS) NotifyAccountSelected(std::string()); NotifyFirstRunExited(FirstRunExitStatus::kQuitEarly, - FirstRunExitSource::kParamDestructor, - base::OnceClosure()); + FirstRunExitSource::kParamDestructor); #endif } @@ -114,12 +113,12 @@ return params; } -void ProfilePicker::Params::NotifyFirstRunExited( - FirstRunExitStatus exit_status, +void ProfilePicker::Params::NotifyFirstRunExited(FirstRunExitStatus exit_status #if BUILDFLAG(IS_CHROMEOS_LACROS) - FirstRunExitSource exit_source, + , + FirstRunExitSource exit_source #endif - base::OnceClosure maybe_callback) { +) { if (!first_run_exited_callback_) return; @@ -129,8 +128,7 @@ << " from source=" << static_cast<int>(exit_source); #endif - std::move(first_run_exited_callback_) - .Run(exit_status, std::move(maybe_callback)); + std::move(first_run_exited_callback_).Run(exit_status); } bool ProfilePicker::Params::CanReusePickerWindow(const Params& other) const {
diff --git a/chrome/browser/ui/profile_picker.h b/chrome/browser/ui/profile_picker.h index 9d23557c9..f2faf24 100644 --- a/chrome/browser/ui/profile_picker.h +++ b/chrome/browser/ui/profile_picker.h
@@ -39,8 +39,7 @@ kQuitEarly = 2, }; using FirstRunExitedCallback = - base::OnceCallback<void(FirstRunExitStatus status, - base::OnceClosure callback)>; + base::OnceCallback<void(FirstRunExitStatus status)>; #if BUILDFLAG(IS_CHROMEOS_LACROS) // Added for bug investigation purposes. @@ -53,8 +52,7 @@ }; using DebugFirstRunExitedCallback = base::OnceCallback<void(FirstRunExitStatus status, - FirstRunExitSource source, - base::OnceClosure callback)>; + FirstRunExitSource source)>; #endif // Only work when passed as the argument 'on_select_profile_target_url' to @@ -150,23 +148,22 @@ // expect it to be the main profile path. // `first_run_exited_callback` is called when the first run experience is // exited, with a `FirstRunExitStatus` indicating how the user responded to - // it, and an optional callback that must be run if the user has proceeded - // to the browser after the FRE. + // it. static Params ForFirstRun(const base::FilePath& profile_path, FirstRunExitedCallback first_run_exited_callback); - // Calls `first_run_exited_callback_`, forwarding `exit_status` and - // `maybe_callback`. See `ForFirstRun()` for more - // details. + // Calls `first_run_exited_callback_`, forwarding `exit_status`.See + // `ForFirstRun()` for more details. // // If this method is not called by the time this `Param` is destroyed, an // intent to quit will be assumed and `first_run_exited_callback_` will be // called by the destructor with quit-related arguments. - void NotifyFirstRunExited(FirstRunExitStatus exit_status, + void NotifyFirstRunExited(FirstRunExitStatus exit_status #if BUILDFLAG(IS_CHROMEOS_LACROS) - FirstRunExitSource exit_source, + , + FirstRunExitSource exit_source #endif - base::OnceClosure maybe_callback); + ); // Returns whether the current profile picker window can be reused for // different parameters. If this returns false, the picker cannot be reused
diff --git a/chrome/browser/ui/profile_picker_unittest.cc b/chrome/browser/ui/profile_picker_unittest.cc index 541146a..2b81212 100644 --- a/chrome/browser/ui/profile_picker_unittest.cc +++ b/chrome/browser/ui/profile_picker_unittest.cc
@@ -214,8 +214,8 @@ } TEST_F(ProfilePickerParamsTest, ForFirstRun_Exit) { - testing::StrictMock<base::MockOnceCallback<void( - ProfilePicker::FirstRunExitStatus, base::OnceClosure)>> + testing::StrictMock< + base::MockOnceCallback<void(ProfilePicker::FirstRunExitStatus)>> callback; { ProfilePicker::Params params = ProfilePicker::Params::ForFirstRun( @@ -223,25 +223,23 @@ EXPECT_EQ(base::FilePath::FromASCII(chrome::kInitialProfile), params.profile_path().BaseName()); // The callback is called at destruction. - EXPECT_CALL(callback, Run(ProfilePicker::FirstRunExitStatus::kQuitEarly, - ::testing::_)); + EXPECT_CALL(callback, Run(ProfilePicker::FirstRunExitStatus::kQuitEarly)); } } TEST_F(ProfilePickerParamsTest, ForFirstRun_Notify) { - testing::StrictMock<base::MockOnceCallback<void( - ProfilePicker::FirstRunExitStatus, base::OnceClosure)>> + testing::StrictMock< + base::MockOnceCallback<void(ProfilePicker::FirstRunExitStatus)>> callback; { ProfilePicker::Params params = ProfilePicker::Params::ForFirstRun( ProfileManager::GetPrimaryUserProfilePath(), callback.Get()); EXPECT_EQ(base::FilePath::FromASCII(chrome::kInitialProfile), params.profile_path().BaseName()); - EXPECT_CALL(callback, Run(ProfilePicker::FirstRunExitStatus::kCompleted, - ::testing::_)); + EXPECT_CALL(callback, Run(ProfilePicker::FirstRunExitStatus::kCompleted)); params.NotifyFirstRunExited( ProfilePicker::FirstRunExitStatus::kCompleted, - ProfilePicker::FirstRunExitSource::kFlowFinished, base::DoNothing()); + ProfilePicker::FirstRunExitSource::kFlowFinished); } } #endif
diff --git a/chrome/browser/ui/startup/first_run_service.cc b/chrome/browser/ui/startup/first_run_service.cc index 2b51065a..38d3377 100644 --- a/chrome/browser/ui/startup/first_run_service.cc +++ b/chrome/browser/ui/startup/first_run_service.cc
@@ -85,12 +85,9 @@ // they were trying to do before they stopped to show the FRE. If the FRE's // `status` is not `ProfilePicker::FirstRunExitStatus::kCompleted`, that // `original_intent_callback` will be called with `proceed` set to false, -// otherwise it will be called with true. `post_first_run_callback` will be -// executed for completed flows, to perform tasks that the FRE requires after -// the interrupted task is resumed. +// otherwise it will be called with true. void OnFirstRunHasExited(ResumeTaskCallback original_intent_callback, - ProfilePicker::FirstRunExitStatus status, - base::OnceClosure post_first_run_callback) { + ProfilePicker::FirstRunExitStatus status) { if (status != ProfilePicker::FirstRunExitStatus::kQuitEarly) { // The user got to the last step, we can mark the FRE as finished, whether // we eventually proceed with the original intent or not. @@ -101,11 +98,6 @@ LOG_IF(ERROR, !proceed) << "Not proceeding FirstRun: " << static_cast<int>(status); std::move(original_intent_callback).Run(proceed); - - if (proceed) { - DCHECK(post_first_run_callback); - std::move(post_first_run_callback).Run(); - } } } // namespace
diff --git a/chrome/browser/ui/startup/startup_browser_creator_impl.cc b/chrome/browser/ui/startup/startup_browser_creator_impl.cc index 8cae23d..6d143c95 100644 --- a/chrome/browser/ui/startup/startup_browser_creator_impl.cc +++ b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
@@ -73,8 +73,10 @@ #if BUILDFLAG(IS_MAC) #include "base/mac/mac_util.h" +#if BUILDFLAG(ENABLE_UPDATER) #include "chrome/browser/ui/cocoa/keystone_infobar_delegate.h" #endif +#endif // BUILDFLAG(IS_MAC) #if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING) #include "chrome/browser/win/conflicts/incompatible_applications_updater.h" @@ -204,7 +206,7 @@ web_app::MaybeInstallAppFromCommandLine(*command_line_, *profile); -#if BUILDFLAG(IS_MAC) +#if BUILDFLAG(IS_MAC) && BUILDFLAG(ENABLE_UPDATER) if (process_startup == chrome::startup::IsProcessStartup::kYes) { // Check whether the auto-update system needs to be promoted from user // to system.
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc index 3a5f4760..fcfeeffc 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc
@@ -46,6 +46,10 @@ #include "ui/views/widget/widget.h" #include "url/gurl.h" +#if !BUILDFLAG(IS_MAC) +#include "ui/aura/window.h" +#endif // !BUILDFLAG(IS_MAC) + using bookmarks::BookmarkExpandedStateTracker; using bookmarks::BookmarkModel; using bookmarks::BookmarkNode;
diff --git a/chrome/browser/ui/views/profiles/first_run_flow_controller_dice.cc b/chrome/browser/ui/views/profiles/first_run_flow_controller_dice.cc index 971f488..6a5f91c 100644 --- a/chrome/browser/ui/views/profiles/first_run_flow_controller_dice.cc +++ b/chrome/browser/ui/views/profiles/first_run_flow_controller_dice.cc
@@ -156,16 +156,23 @@ /*enable_animations=*/true)); } -FirstRunFlowControllerDice::~FirstRunFlowControllerDice() = default; +FirstRunFlowControllerDice::~FirstRunFlowControllerDice() { + if (first_run_exited_callback_) { + std::move(first_run_exited_callback_) + .Run(ProfilePicker::FirstRunExitStatus::kQuitAtEnd); + } +} + +bool FirstRunFlowControllerDice::PreFinishWithBrowser() { + DCHECK(first_run_exited_callback_); + std::move(first_run_exited_callback_) + .Run(ProfilePicker::FirstRunExitStatus::kCompleted); + return true; +} void FirstRunFlowControllerDice::HandleIntroSigninChoice(bool sign_in) { if (!sign_in) { - std::move(first_run_exited_callback_) - .Run(ProfilePicker::FirstRunExitStatus::kCompleted, - base::BindOnce( - &FirstRunFlowControllerDice::FinishFlowAndRunInBrowser, - weak_ptr_factory_.GetWeakPtr(), profile_, - PostHostClearedCallback())); + FinishFlowAndRunInBrowser(profile_, PostHostClearedCallback()); return; }
diff --git a/chrome/browser/ui/views/profiles/first_run_flow_controller_dice.h b/chrome/browser/ui/views/profiles/first_run_flow_controller_dice.h index 21c561f1..047c429b 100644 --- a/chrome/browser/ui/views/profiles/first_run_flow_controller_dice.h +++ b/chrome/browser/ui/views/profiles/first_run_flow_controller_dice.h
@@ -33,6 +33,10 @@ ProfilePicker::FirstRunExitedCallback first_run_exited_callback); ~FirstRunFlowControllerDice() override; + protected: + // ProfileManagementFlowController: + bool PreFinishWithBrowser() override; + private: void HandleIntroSigninChoice(bool sign_in);
diff --git a/chrome/browser/ui/views/profiles/first_run_flow_controller_lacros.cc b/chrome/browser/ui/views/profiles/first_run_flow_controller_lacros.cc index 29241ea..0372600 100644 --- a/chrome/browser/ui/views/profiles/first_run_flow_controller_lacros.cc +++ b/chrome/browser/ui/views/profiles/first_run_flow_controller_lacros.cc
@@ -143,7 +143,7 @@ // the `this` will own and outlive. base::Unretained(this)); auto finish_flow_callback = FinishFlowCallback( - base::BindOnce(&FirstRunFlowControllerLacros::ExitFlowAndRun, + base::BindOnce(&FirstRunFlowControllerLacros::FinishFlowAndRunInBrowser, // Unretained ok: the callback is passed to a step that // the `this` will own and outlive. base::Unretained(this), @@ -169,34 +169,17 @@ .Run(sync_confirmation_seen_ ? ProfilePicker::FirstRunExitStatus::kQuitAtEnd : ProfilePicker::FirstRunExitStatus::kQuitEarly, - ProfilePicker::FirstRunExitSource::kControllerDestructor, - // Since the flow is exited already, we don't have anything to - // close or finish setting up, and the callback won't be executed - // anyway. - /*maybe_callback=*/base::OnceClosure()); + ProfilePicker::FirstRunExitSource::kControllerDestructor); + // Since the flow is exited already, we don't have anything to close or + // finish setting up. } } -void FirstRunFlowControllerLacros::ExitFlowAndRun( - Profile* profile, - PostHostClearedCallback callback) { - // We don't call `FinishFlowAndRunInBrowser()` directly, as - // `first_run_exited_callback_` should make a browser window available when - // it runs. If there is no browser, then we will create it as a fallback. - // TODO(crbug.com/1383969): Races with Ash to open a window. Find another way. - auto finish_flow_callback = - base::BindOnce(&FirstRunFlowControllerLacros::FinishFlowAndRunInBrowser, - // Unretained ok: the flow will be closed when we run - // `finish_flow_callback`, so `this` will still be alive. - base::Unretained(this), - // Unretained ok: the flow keeps the profile alive and - // `first_run_exited_callback_` will open a browser for it. - base::Unretained(profile), std::move(callback)); - +bool FirstRunFlowControllerLacros::PreFinishWithBrowser() { std::move(first_run_exited_callback_) .Run(ProfilePicker::FirstRunExitStatus::kCompleted, - ProfilePicker::FirstRunExitSource::kFlowFinished, - std::move(finish_flow_callback)); + ProfilePicker::FirstRunExitSource::kFlowFinished); + return true; } void FirstRunFlowControllerLacros::MarkSyncConfirmationSeen() {
diff --git a/chrome/browser/ui/views/profiles/first_run_flow_controller_lacros.h b/chrome/browser/ui/views/profiles/first_run_flow_controller_lacros.h index 2033e6f..f40e9112 100644 --- a/chrome/browser/ui/views/profiles/first_run_flow_controller_lacros.h +++ b/chrome/browser/ui/views/profiles/first_run_flow_controller_lacros.h
@@ -26,8 +26,11 @@ ~FirstRunFlowControllerLacros() override; + protected: + // ProfileManagementFlowController: + bool PreFinishWithBrowser() override; + private: - void ExitFlowAndRun(Profile* profile, PostHostClearedCallback callback); void MarkSyncConfirmationSeen(); // Captures the operation that the user expected to run at the time we chose
diff --git a/chrome/browser/ui/views/profiles/profile_management_flow_controller.cc b/chrome/browser/ui/views/profiles/profile_management_flow_controller.cc index 188f74c..352797e9 100644 --- a/chrome/browser/ui/views/profiles/profile_management_flow_controller.cc +++ b/chrome/browser/ui/views/profiles/profile_management_flow_controller.cc
@@ -85,11 +85,19 @@ std::move(clear_host_callback_.value()).Run(); } +bool ProfileManagementFlowController::PreFinishWithBrowser() { + return false; +} + void ProfileManagementFlowController::FinishFlowAndRunInBrowser( Profile* profile, PostHostClearedCallback post_host_cleared_callback) { DCHECK(clear_host_callback_.value()); // The host shouldn't be cleared yet. + // TODO(crbug.com/1383969): Handle the return value and don't open a browser + // if it is already going to be opened. + PreFinishWithBrowser(); + base::OnceCallback<void(Profile*)> post_browser_open_callback = base::IgnoreArgs<Profile*>(std::move(clear_host_callback_.value())); if (!post_host_cleared_callback->is_null()) {
diff --git a/chrome/browser/ui/views/profiles/profile_management_flow_controller.h b/chrome/browser/ui/views/profiles/profile_management_flow_controller.h index 6289a81..888c796 100644 --- a/chrome/browser/ui/views/profiles/profile_management_flow_controller.h +++ b/chrome/browser/ui/views/profiles/profile_management_flow_controller.h
@@ -105,6 +105,14 @@ void FinishFlowAndRunInBrowser(Profile* profile, PostHostClearedCallback callback); + // Will be called at the beginning of `FinishFlowAndRunInBrowser`. + // + // Subclasses should override it if they want to perform some additional + // operations when the flow is closing. If they are going to open a browser + // themselves, they should return `true`. The default implementation does + // nothing and returns `false`. + virtual bool PreFinishWithBrowser(); + Step current_step() const { return current_step_; } Step initial_step() const { return initial_step_; }
diff --git a/chrome/browser/ui/views/profiles/profile_picker_view.cc b/chrome/browser/ui/views/profiles/profile_picker_view.cc index f74b67d..0923cbd 100644 --- a/chrome/browser/ui/views/profiles/profile_picker_view.cc +++ b/chrome/browser/ui/views/profiles/profile_picker_view.cc
@@ -372,7 +372,7 @@ params_.NotifyAccountSelected(std::string()); params_.NotifyFirstRunExited( ProfilePicker::FirstRunExitStatus::kQuitEarly, - ProfilePicker::FirstRunExitSource::kReusingWindow, base::OnceClosure()); + ProfilePicker::FirstRunExitSource::kReusingWindow); #endif params_ = std::move(params);
diff --git a/chrome/browser/ui/views/toolbar/chrome_labs_view_controller.cc b/chrome/browser/ui/views/toolbar/chrome_labs_view_controller.cc index a97471d..867b7a3e 100644 --- a/chrome/browser/ui/views/toolbar/chrome_labs_view_controller.cc +++ b/chrome/browser/ui/views/toolbar/chrome_labs_view_controller.cc
@@ -29,6 +29,7 @@ #include "chrome/common/buildflags.h" #include "components/flags_ui/feature_entry.h" #include "components/flags_ui/flags_state.h" +#include "components/flags_ui/flags_storage.h" #include "components/prefs/scoped_user_pref_update.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac.cc b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac.cc index 4144d136..f37b013 100644 --- a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac.cc +++ b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac.cc
@@ -376,81 +376,5 @@ helper_.CheckWindowNotCreated(); } -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_29FileHandlerWindowed_118FileHandlerFoo_118FileHandlerBar) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_29FileHandlerBrowser_118FileHandlerFoo_118FileHandlerBar) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kBrowser); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_32FileHandlerWithShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut, - WindowOptions::kWindowed, InstallMode::kWebApp); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_32FileHandlerWithShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut, - WindowOptions::kBrowser, InstallMode::kWebApp); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_32FileHandlerNoShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut, - WindowOptions::kWindowed, InstallMode::kWebApp); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_32FileHandlerNoShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut, - WindowOptions::kBrowser, InstallMode::kWebApp); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); -} - } // namespace } // namespace web_app::integration_tests
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac_win_linux.cc b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac_win_linux.cc index ffad6f58..1787af9 100644 --- a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac_win_linux.cc +++ b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac_win_linux.cc
@@ -64,6 +64,29 @@ helper_.CheckSiteNotHandlesFile(Site::kStandalone, FileExtension::kBar); } +IN_PROC_BROWSER_TEST_F(WebAppIntegration, CheckLaunchFileExpectDialog) { + helper_.InstallMenuOption(InstallableSite::kFileHandler); + helper_.ClosePwa(); + helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, + AllowDenyOptions::kAllow, + AskAgainOptions::kAskAgain); + helper_.CheckWindowCreated(); +} + +IN_PROC_BROWSER_TEST_F(WebAppIntegration, CheckLaunchFileExpectNoDialog_Allow) { + helper_.InstallOmniboxIcon(InstallableSite::kFileHandler); + helper_.ClosePwa(); + // Open the file and set AskAgainOption to kRemember. + helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, + AllowDenyOptions::kAllow, + AskAgainOptions::kRemember); + helper_.ClosePwa(); + // Open the file again. + helper_.LaunchFileExpectNoDialog(Site::kFileHandler, + FilesOptions::kOneFooFile); + helper_.CheckWindowCreated(); +} + IN_PROC_BROWSER_TEST_F(WebAppIntegration, CheckLaunchFileExpectNoDialog_Deny) { helper_.InstallOmniboxIcon(InstallableSite::kFileHandler); helper_.ClosePwa(); @@ -1468,6 +1491,82 @@ IN_PROC_BROWSER_TEST_F( WebAppIntegration, + WAI_29FileHandlerBrowser_118FileHandlerFoo_118FileHandlerBar) { + // Test contents are generated by script. Please do not modify! + // See `docs/webapps/why-is-this-test-failing.md` or + // `docs/webapps/integration-testing-framework` for more info. + // Sheriffs: Disabling this test is supported. + helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kBrowser); + helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); + helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); +} + +IN_PROC_BROWSER_TEST_F( + WebAppIntegration, + WAI_32FileHandlerWithShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar) { + // Test contents are generated by script. Please do not modify! + // See `docs/webapps/why-is-this-test-failing.md` or + // `docs/webapps/integration-testing-framework` for more info. + // Sheriffs: Disabling this test is supported. + helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut, + WindowOptions::kWindowed, InstallMode::kWebApp); + helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); + helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); +} + +IN_PROC_BROWSER_TEST_F( + WebAppIntegration, + WAI_32FileHandlerWithShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar) { + // Test contents are generated by script. Please do not modify! + // See `docs/webapps/why-is-this-test-failing.md` or + // `docs/webapps/integration-testing-framework` for more info. + // Sheriffs: Disabling this test is supported. + helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut, + WindowOptions::kBrowser, InstallMode::kWebApp); + helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); + helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); +} + +IN_PROC_BROWSER_TEST_F( + WebAppIntegration, + WAI_32FileHandlerNoShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar) { + // Test contents are generated by script. Please do not modify! + // See `docs/webapps/why-is-this-test-failing.md` or + // `docs/webapps/integration-testing-framework` for more info. + // Sheriffs: Disabling this test is supported. + helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut, + WindowOptions::kWindowed, InstallMode::kWebApp); + helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); + helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); +} + +IN_PROC_BROWSER_TEST_F( + WebAppIntegration, + WAI_32FileHandlerNoShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar) { + // Test contents are generated by script. Please do not modify! + // See `docs/webapps/why-is-this-test-failing.md` or + // `docs/webapps/integration-testing-framework` for more info. + // Sheriffs: Disabling this test is supported. + helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut, + WindowOptions::kBrowser, InstallMode::kWebApp); + helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); + helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); +} + +IN_PROC_BROWSER_TEST_F( + WebAppIntegration, + WAI_29FileHandlerWindowed_118FileHandlerFoo_118FileHandlerBar) { + // Test contents are generated by script. Please do not modify! + // See `docs/webapps/why-is-this-test-failing.md` or + // `docs/webapps/integration-testing-framework` for more info. + // Sheriffs: Disabling this test is supported. + helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed); + helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); + helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); +} + +IN_PROC_BROWSER_TEST_F( + WebAppIntegration, WAI_32StandaloneNoShortcutWindowedWebApp_12Standalone_101Standalone_111Standalone) { // Test contents are generated by script. Please do not modify! // See `docs/webapps/why-is-this-test-failing.md` or
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_win_linux.cc b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_win_linux.cc index b4dcd7f..b7e2cfb 100644 --- a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_win_linux.cc +++ b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_win_linux.cc
@@ -11,28 +11,6 @@ using WebAppIntegration = WebAppIntegrationTest; // Manual tests: -IN_PROC_BROWSER_TEST_F(WebAppIntegration, CheckLaunchFileExpectDialog) { - helper_.InstallMenuOption(InstallableSite::kFileHandler); - helper_.ClosePwa(); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kAllow, - AskAgainOptions::kAskAgain); - helper_.CheckWindowCreated(); -} - -IN_PROC_BROWSER_TEST_F(WebAppIntegration, CheckLaunchFileExpectNoDialog_Allow) { - helper_.InstallOmniboxIcon(InstallableSite::kFileHandler); - helper_.ClosePwa(); - // Open the file and set AskAgainOption to kRemember. - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kAllow, - AskAgainOptions::kRemember); - helper_.CheckWindowCreated(); - // Open the file again. - helper_.LaunchFileExpectNoDialog(Site::kFileHandler, - FilesOptions::kOneFooFile); - helper_.CheckWindowCreated(); -} // Generated tests: @@ -341,747 +319,5 @@ helper_.CheckWindowCreated(); } -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_29FileHandlerWindowed_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain_120FileHandlerOneFooFileAllowAskAgain) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kAllow, - AskAgainOptions::kAskAgain); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kAllow, - AskAgainOptions::kAskAgain); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_29FileHandlerWindowed_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleFooFilesAllowAskAgain) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog( - Site::kFileHandler, FilesOptions::kMultipleFooFiles, - AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_29FileHandlerWindowed_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneBarFileAllowAskAgain) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneBarFile, - AllowDenyOptions::kAllow, - AskAgainOptions::kAskAgain); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_29FileHandlerWindowed_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleBarFilesAllowAskAgain) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog( - Site::kFileHandler, FilesOptions::kMultipleBarFiles, - AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_29FileHandlerWindowed_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowRemember_121FileHandlerOneFooFile) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kAllow, - AskAgainOptions::kRemember); - helper_.LaunchFileExpectNoDialog(Site::kFileHandler, - FilesOptions::kOneFooFile); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_29FileHandlerWindowed_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyAskAgain_127_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kDeny, - AskAgainOptions::kAskAgain); - helper_.CheckWindowNotCreated(); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kAllow, - AskAgainOptions::kAskAgain); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_29FileHandlerWindowed_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyRemember_127_122FileHandlerFoo_122FileHandlerBar) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kDeny, - AskAgainOptions::kRemember); - helper_.CheckWindowNotCreated(); - helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kBar); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_29FileHandlerBrowser_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain_120FileHandlerOneFooFileAllowAskAgain) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kBrowser); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kAllow, - AskAgainOptions::kAskAgain); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kAllow, - AskAgainOptions::kAskAgain); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_29FileHandlerBrowser_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleFooFilesAllowAskAgain) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kBrowser); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog( - Site::kFileHandler, FilesOptions::kMultipleFooFiles, - AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_29FileHandlerBrowser_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneBarFileAllowAskAgain) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kBrowser); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneBarFile, - AllowDenyOptions::kAllow, - AskAgainOptions::kAskAgain); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_29FileHandlerBrowser_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleBarFilesAllowAskAgain) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kBrowser); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog( - Site::kFileHandler, FilesOptions::kMultipleBarFiles, - AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_29FileHandlerBrowser_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowRemember_121FileHandlerOneFooFile) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kBrowser); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kAllow, - AskAgainOptions::kRemember); - helper_.LaunchFileExpectNoDialog(Site::kFileHandler, - FilesOptions::kOneFooFile); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_29FileHandlerBrowser_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyAskAgain_127_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kBrowser); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kDeny, - AskAgainOptions::kAskAgain); - helper_.CheckWindowNotCreated(); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kAllow, - AskAgainOptions::kAskAgain); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_29FileHandlerBrowser_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyRemember_127_122FileHandlerFoo_122FileHandlerBar) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kBrowser); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kDeny, - AskAgainOptions::kRemember); - helper_.CheckWindowNotCreated(); - helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kBar); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_32FileHandlerWithShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain_120FileHandlerOneFooFileAllowAskAgain) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut, - WindowOptions::kWindowed, InstallMode::kWebApp); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kAllow, - AskAgainOptions::kAskAgain); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kAllow, - AskAgainOptions::kAskAgain); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_32FileHandlerWithShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleFooFilesAllowAskAgain) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut, - WindowOptions::kWindowed, InstallMode::kWebApp); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog( - Site::kFileHandler, FilesOptions::kMultipleFooFiles, - AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_32FileHandlerWithShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneBarFileAllowAskAgain) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut, - WindowOptions::kWindowed, InstallMode::kWebApp); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneBarFile, - AllowDenyOptions::kAllow, - AskAgainOptions::kAskAgain); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_32FileHandlerWithShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleBarFilesAllowAskAgain) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut, - WindowOptions::kWindowed, InstallMode::kWebApp); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog( - Site::kFileHandler, FilesOptions::kMultipleBarFiles, - AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_32FileHandlerWithShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowRemember_121FileHandlerOneFooFile) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut, - WindowOptions::kWindowed, InstallMode::kWebApp); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kAllow, - AskAgainOptions::kRemember); - helper_.LaunchFileExpectNoDialog(Site::kFileHandler, - FilesOptions::kOneFooFile); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_32FileHandlerWithShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyAskAgain_127_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut, - WindowOptions::kWindowed, InstallMode::kWebApp); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kDeny, - AskAgainOptions::kAskAgain); - helper_.CheckWindowNotCreated(); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kAllow, - AskAgainOptions::kAskAgain); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_32FileHandlerWithShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyRemember_127_122FileHandlerFoo_122FileHandlerBar) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut, - WindowOptions::kWindowed, InstallMode::kWebApp); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kDeny, - AskAgainOptions::kRemember); - helper_.CheckWindowNotCreated(); - helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kBar); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_32FileHandlerWithShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain_120FileHandlerOneFooFileAllowAskAgain) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut, - WindowOptions::kBrowser, InstallMode::kWebApp); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kAllow, - AskAgainOptions::kAskAgain); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kAllow, - AskAgainOptions::kAskAgain); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_32FileHandlerWithShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleFooFilesAllowAskAgain) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut, - WindowOptions::kBrowser, InstallMode::kWebApp); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog( - Site::kFileHandler, FilesOptions::kMultipleFooFiles, - AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_32FileHandlerWithShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneBarFileAllowAskAgain) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut, - WindowOptions::kBrowser, InstallMode::kWebApp); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneBarFile, - AllowDenyOptions::kAllow, - AskAgainOptions::kAskAgain); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_32FileHandlerWithShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleBarFilesAllowAskAgain) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut, - WindowOptions::kBrowser, InstallMode::kWebApp); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog( - Site::kFileHandler, FilesOptions::kMultipleBarFiles, - AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_32FileHandlerWithShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowRemember_121FileHandlerOneFooFile) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut, - WindowOptions::kBrowser, InstallMode::kWebApp); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kAllow, - AskAgainOptions::kRemember); - helper_.LaunchFileExpectNoDialog(Site::kFileHandler, - FilesOptions::kOneFooFile); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_32FileHandlerWithShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyAskAgain_127_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut, - WindowOptions::kBrowser, InstallMode::kWebApp); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kDeny, - AskAgainOptions::kAskAgain); - helper_.CheckWindowNotCreated(); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kAllow, - AskAgainOptions::kAskAgain); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_32FileHandlerWithShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyRemember_127_122FileHandlerFoo_122FileHandlerBar) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut, - WindowOptions::kBrowser, InstallMode::kWebApp); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kDeny, - AskAgainOptions::kRemember); - helper_.CheckWindowNotCreated(); - helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kBar); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_32FileHandlerNoShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain_120FileHandlerOneFooFileAllowAskAgain) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut, - WindowOptions::kWindowed, InstallMode::kWebApp); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kAllow, - AskAgainOptions::kAskAgain); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kAllow, - AskAgainOptions::kAskAgain); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_32FileHandlerNoShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleFooFilesAllowAskAgain) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut, - WindowOptions::kWindowed, InstallMode::kWebApp); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog( - Site::kFileHandler, FilesOptions::kMultipleFooFiles, - AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_32FileHandlerNoShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneBarFileAllowAskAgain) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut, - WindowOptions::kWindowed, InstallMode::kWebApp); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneBarFile, - AllowDenyOptions::kAllow, - AskAgainOptions::kAskAgain); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_32FileHandlerNoShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleBarFilesAllowAskAgain) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut, - WindowOptions::kWindowed, InstallMode::kWebApp); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog( - Site::kFileHandler, FilesOptions::kMultipleBarFiles, - AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_32FileHandlerNoShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowRemember_121FileHandlerOneFooFile) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut, - WindowOptions::kWindowed, InstallMode::kWebApp); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kAllow, - AskAgainOptions::kRemember); - helper_.LaunchFileExpectNoDialog(Site::kFileHandler, - FilesOptions::kOneFooFile); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_32FileHandlerNoShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyAskAgain_127_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut, - WindowOptions::kWindowed, InstallMode::kWebApp); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kDeny, - AskAgainOptions::kAskAgain); - helper_.CheckWindowNotCreated(); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kAllow, - AskAgainOptions::kAskAgain); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_32FileHandlerNoShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyRemember_127_122FileHandlerFoo_122FileHandlerBar) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut, - WindowOptions::kWindowed, InstallMode::kWebApp); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kDeny, - AskAgainOptions::kRemember); - helper_.CheckWindowNotCreated(); - helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kBar); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_32FileHandlerNoShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain_120FileHandlerOneFooFileAllowAskAgain) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut, - WindowOptions::kBrowser, InstallMode::kWebApp); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kAllow, - AskAgainOptions::kAskAgain); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kAllow, - AskAgainOptions::kAskAgain); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_32FileHandlerNoShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleFooFilesAllowAskAgain) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut, - WindowOptions::kBrowser, InstallMode::kWebApp); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog( - Site::kFileHandler, FilesOptions::kMultipleFooFiles, - AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_32FileHandlerNoShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneBarFileAllowAskAgain) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut, - WindowOptions::kBrowser, InstallMode::kWebApp); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneBarFile, - AllowDenyOptions::kAllow, - AskAgainOptions::kAskAgain); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_32FileHandlerNoShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleBarFilesAllowAskAgain) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut, - WindowOptions::kBrowser, InstallMode::kWebApp); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog( - Site::kFileHandler, FilesOptions::kMultipleBarFiles, - AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_32FileHandlerNoShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowRemember_121FileHandlerOneFooFile) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut, - WindowOptions::kBrowser, InstallMode::kWebApp); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kAllow, - AskAgainOptions::kRemember); - helper_.LaunchFileExpectNoDialog(Site::kFileHandler, - FilesOptions::kOneFooFile); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_32FileHandlerNoShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyAskAgain_127_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut, - WindowOptions::kBrowser, InstallMode::kWebApp); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kDeny, - AskAgainOptions::kAskAgain); - helper_.CheckWindowNotCreated(); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kAllow, - AskAgainOptions::kAskAgain); -} - -IN_PROC_BROWSER_TEST_F( - WebAppIntegration, - WAI_32FileHandlerNoShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyRemember_127_122FileHandlerFoo_122FileHandlerBar) { - // Test contents are generated by script. Please do not modify! - // See `docs/webapps/why-is-this-test-failing.md` or - // `docs/webapps/integration-testing-framework` for more info. - // Sheriffs: Disabling this test is supported. - helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut, - WindowOptions::kBrowser, InstallMode::kWebApp); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar); - helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile, - AllowDenyOptions::kDeny, - AskAgainOptions::kRemember); - helper_.CheckWindowNotCreated(); - helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kFoo); - helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kBar); -} - } // namespace } // namespace web_app::integration_tests
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc index 073a55a..ed367f1 100644 --- a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc +++ b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
@@ -274,9 +274,7 @@ .relative_manifest_id = "webapps_integration/file_handler/basic.html", .app_name = "File Handler", .wco_not_enabled_title = u"File Handler", - .icon_color = SK_ColorBLACK, - .alternate_titles = {"File Handler - Text Handler", - "File Handler - Image Handler"}}}, + .icon_color = SK_ColorBLACK}}, {Site::kNoServiceWorker, {.relative_url = "/webapps_integration/site_no_service_worker/basic.html", .relative_manifest_id = @@ -1186,10 +1184,10 @@ FileHandlerLaunchDialogView::SetDefaultRememberSelectionForTesting( ask_again == AskAgainOptions::kRemember); - base::RunLoop run_loop; - web_app::startup::SetStartupDoneCallbackForTesting(run_loop.QuitClosure()); LaunchFile(site, files_options); + BrowserAddedWaiter browser_added_waiter; + // Check the file handling dialog shows up. views::Widget* widget = waiter.WaitIfNeededAndGet(); ASSERT_TRUE(widget != nullptr); @@ -1208,7 +1206,12 @@ widget->CloseWithReason(close_reason); destroyed_waiter.Wait(); - run_loop.Run(); + if (allow_deny == AllowDenyOptions::kAllow) { + browser_added_waiter.Wait(); + app_browser_ = browser_added_waiter.browser_added(); + ActivateBrowserAndWait(app_browser_); + EXPECT_EQ(app_browser()->app_controller()->app_id(), app_id); + } AfterStateChangeAction(); } @@ -1217,15 +1220,17 @@ FilesOptions files_options) { BeforeStateChangeAction(__FUNCTION__); AppId app_id = GetAppIdBySiteMode(site); - base::RunLoop run_loop; - web_app::startup::SetStartupDoneCallbackForTesting(run_loop.QuitClosure()); + BrowserAddedWaiter browser_added_waiter; LaunchFile(site, files_options); // If the user previously denied access to open files with this app, a window // is still opened for the app. The only difference is that no files would // have been passed to the app. Either way, we should always wait for a - // window / browser to be added. - run_loop.Run(); + // browser to be added. + browser_added_waiter.Wait(); + app_browser_ = browser_added_waiter.browser_added(); + ActivateBrowserAndWait(app_browser_); + EXPECT_EQ(app_browser()->app_controller()->app_id(), app_id); AfterStateChangeAction(); }
diff --git a/chrome/browser/ui/webui/app_home/app_home.mojom b/chrome/browser/ui/webui/app_home/app_home.mojom index 5d3fb2c..d551dd0 100644 --- a/chrome/browser/ui/webui/app_home/app_home.mojom +++ b/chrome/browser/ui/webui/app_home/app_home.mojom
@@ -29,6 +29,8 @@ UninstallApp(string app_id); // Open app’s site setting page. ShowAppSettings(string app_id); + // Create shortcut link for app. + CreateAppShortcut(string app_id) => (); }; // The `Page` interface is used for sending mojom action messsage
diff --git a/chrome/browser/ui/webui/app_home/app_home_page_handler.cc b/chrome/browser/ui/webui/app_home/app_home_page_handler.cc index 7fb56f99..761ab30 100644 --- a/chrome/browser/ui/webui/app_home/app_home_page_handler.cc +++ b/chrome/browser/ui/webui/app_home/app_home_page_handler.cc
@@ -3,11 +3,16 @@ // found in the LICENSE file. #include "chrome/browser/ui/webui/app_home/app_home_page_handler.h" +#include "base/bind.h" +#include "base/callback_helpers.h" +#include "base/functional/callback_helpers.h" +#include "base/metrics/histogram_functions.h" #include "chrome/browser/apps/app_service/app_icon/app_icon_source.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_ui_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/apps/app_info_dialog.h" +#include "chrome/browser/ui/browser_dialogs.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/chrome_pages.h" @@ -84,6 +89,35 @@ base::DoNothing()); } +void AppHomePageHandler::CreateWebAppShortcut(const std::string& app_id, + base::OnceClosure done) { + Browser* browser = GetCurrentBrowser(); + chrome::ShowCreateChromeAppShortcutsDialog( + browser->window()->GetNativeWindow(), browser->profile(), app_id, + base::BindOnce( + [](base::OnceClosure done, bool success) { + base::UmaHistogramBoolean( + "Apps.AppInfoDialog.CreateWebAppShortcutSuccess", success); + std::move(done).Run(); + }, + std::move(done))); +} + +void AppHomePageHandler::CreateExtensionAppShortcut( + const extensions::Extension* extension, + base::OnceClosure done) { + Browser* browser = GetCurrentBrowser(); + chrome::ShowCreateChromeAppShortcutsDialog( + browser->window()->GetNativeWindow(), browser->profile(), extension, + base::BindOnce( + [](base::OnceClosure done, bool success) { + base::UmaHistogramBoolean( + "Apps.AppInfoDialog.CreateExtensionShortcutSuccess", success); + std::move(done).Run(); + }, + std::move(done))); +} + app_home::mojom::AppInfoPtr AppHomePageHandler::CreateAppInfoPtrFromWebApp( const web_app::AppId& app_id) { auto& registrar = web_app_provider_->registrar(); @@ -290,4 +324,22 @@ } } +void AppHomePageHandler::CreateAppShortcut(const std::string& app_id, + CreateAppShortcutCallback callback) { + if (web_app_provider_->registrar().IsInstalled(app_id) && + !IsYoutubeExtension(app_id)) { + CreateWebAppShortcut(app_id, std::move(callback)); + return; + } + + const Extension* extension = + extensions::ExtensionRegistry::Get(extension_service_->profile()) + ->GetExtensionById(app_id, + extensions::ExtensionRegistry::ENABLED | + extensions::ExtensionRegistry::DISABLED | + extensions::ExtensionRegistry::TERMINATED); + if (extension) + CreateExtensionAppShortcut(extension, std::move(callback)); +} + } // namespace webapps
diff --git a/chrome/browser/ui/webui/app_home/app_home_page_handler.h b/chrome/browser/ui/webui/app_home/app_home_page_handler.h index 301aefc40..a5d5303 100644 --- a/chrome/browser/ui/webui/app_home/app_home_page_handler.h +++ b/chrome/browser/ui/webui/app_home/app_home_page_handler.h
@@ -66,6 +66,8 @@ void GetApps(GetAppsCallback callback) override; void UninstallApp(const std::string& app_id) override; void ShowAppSettings(const std::string& app_id) override; + void CreateAppShortcut(const std::string& app_id, + CreateAppShortcutCallback callback) override; private: Browser* GetCurrentBrowser(); @@ -83,6 +85,9 @@ void ShowWebAppSettings(const std::string& app_id); void ShowExtensionAppSettings(const extensions::Extension* extension); + void CreateWebAppShortcut(const std::string& app_id, base::OnceClosure done); + void CreateExtensionAppShortcut(const extensions::Extension* extension, + base::OnceClosure done); void UninstallWebApp(const std::string& web_app_id); void UninstallExtensionApp(const extensions::Extension* extension); void FillWebAppInfoList(std::vector<app_home::mojom::AppInfoPtr>* result);
diff --git a/chrome/browser/ui/webui/app_home/app_home_page_handler_browsertest.cc b/chrome/browser/ui/webui/app_home/app_home_page_handler_browsertest.cc index 1dfe6ab..c0330b5 100644 --- a/chrome/browser/ui/webui/app_home/app_home_page_handler_browsertest.cc +++ b/chrome/browser/ui/webui/app_home/app_home_page_handler_browsertest.cc
@@ -12,15 +12,20 @@ #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/webui/app_home/app_home.mojom.h" #include "chrome/browser/ui/webui/app_home/mock_app_home_page.h" +#include "chrome/browser/web_applications/os_integration/web_app_shortcut.h" #include "chrome/browser/web_applications/test/web_app_install_test_utils.h" #include "chrome/common/webui_url_constants.h" #include "chrome/test/base/in_process_browser_test.h" +#include "content/public/browser/browser_task_traits.h" #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test.h" #include "content/public/test/test_web_ui.h" #include "extensions/browser/extension_dialog_auto_confirm.h" #include "extensions/common/extension_builder.h" #include "testing/gmock/include/gmock/gmock.h" +#include "ui/views/test/dialog_test.h" +#include "ui/views/widget/any_widget_observer.h" +#include "ui/views/widget/widget.h" using web_app::AppId; using GetAppsCallback = @@ -34,6 +39,30 @@ constexpr char kTestManifestUrl[] = "https://www.example.com/manifest.json"; constexpr char kTestAppName[] = "Test App"; +#if !BUILDFLAG(IS_MAC) +void FlushShortcutTasks() { + // Execute the UI thread task runner before and after the shortcut task runner + // to ensure that tasks get to the shortcut runner, and then any scheduled + // replies on the UI thread get run. + { + base::RunLoop loop; + content::GetUIThreadTaskRunner({})->PostTask(FROM_HERE, loop.QuitClosure()); + loop.Run(); + } + { + base::RunLoop loop; + web_app::internals::GetShortcutIOTaskRunner()->PostTask(FROM_HERE, + loop.QuitClosure()); + loop.Run(); + } + { + base::RunLoop loop; + content::GetUIThreadTaskRunner({})->PostTask(FROM_HERE, loop.QuitClosure()); + loop.Run(); + } +} +#endif + class TestAppHomePageHandler : public AppHomePageHandler { public: TestAppHomePageHandler(content::WebUI* web_ui, @@ -329,4 +358,54 @@ GURL url = browser()->tab_strip_model()->GetActiveWebContents()->GetURL(); EXPECT_EQ(url, GURL(chrome::kChromeUIWebAppSettingsURL + installed_app_id)); } + +IN_PROC_BROWSER_TEST_F(AppHomePageHandlerTest, CreateWebAppShortcut) { + std::unique_ptr<TestAppHomePageHandler> page_handler = + GetAppHomePageHandler(); + + // First, install a test web app for test. + EXPECT_CALL(page_, AddApp(MatchAppName(kTestAppName))); + AppId installed_app_id = InstallTestWebApp(); + page_handler->Wait(); + +#if BUILDFLAG(IS_MAC) + base::RunLoop loop; + page_handler->CreateAppShortcut(installed_app_id, loop.QuitClosure()); + loop.Run(); +#else + views::NamedWidgetShownWaiter waiter(views::test::AnyWidgetTestPasskey{}, + "CreateChromeApplicationShortcutView"); + page_handler->CreateAppShortcut(installed_app_id, base::DoNothing()); + FlushShortcutTasks(); + views::Widget* widget = waiter.WaitIfNeededAndGet(); + ASSERT_TRUE(widget != nullptr); + views::test::AcceptDialog(widget); +#endif +} + +IN_PROC_BROWSER_TEST_F(AppHomePageHandlerTest, CreateExtensionAppShortcut) { + std::unique_ptr<TestAppHomePageHandler> page_handler = + GetAppHomePageHandler(); + + // First, install a test extension app for test. + EXPECT_CALL(page_, AddApp(MatchAppName(kTestAppName))); + scoped_refptr<const extensions::Extension> extension = + InstallTestExtensionApp(); + page_handler->Wait(); + +#if BUILDFLAG(IS_MAC) + base::RunLoop loop; + page_handler->CreateAppShortcut(extension->id(), loop.QuitClosure()); + loop.Run(); +#else + views::NamedWidgetShownWaiter waiter(views::test::AnyWidgetTestPasskey{}, + "CreateChromeApplicationShortcutView"); + page_handler->CreateAppShortcut(extension->id(), base::DoNothing()); + FlushShortcutTasks(); + views::Widget* widget = waiter.WaitIfNeededAndGet(); + ASSERT_TRUE(widget != nullptr); + views::test::AcceptDialog(widget); +#endif +} + } // namespace webapps
diff --git a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload.mojom b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload.mojom index 3b03743..c8cbc0e 100644 --- a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload.mojom +++ b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload.mojom
@@ -11,6 +11,8 @@ kSetUpOneDrive, kUploadToGoogleDrive, kUploadToOneDrive, + kConfirmOrUploadToGoogleDrive, + kConfirmOrUploadToOneDrive, }; // Options for which sub-page/flow we want to show. @@ -21,6 +23,10 @@ kOneDriveSetup, // Set up Google Drive (one-page confirmation screen). kGoogleDriveSetup, + // Confirm that the user wants to move the file to OneDrive. + kMoveConfirmationOneDrive, + // Confirm that the user wants to move the file to Google Drive. + kMoveConfirmationGoogleDrive, }; // Contains the arguments used to set up the dialog. @@ -55,4 +61,8 @@ // Set Office as the default file handler for office files and mark the // setup as complete so that it does not need to be started again. SetOfficeAsDefaultHandler(); + + // Set the preference for whether we should always move office files without + // asking the user first. + SetAlwaysMoveOfficeFiles(bool always_move); };
diff --git a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog.cc b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog.cc index 1db5928..81bf8c7 100644 --- a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog.cc +++ b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog.cc
@@ -78,6 +78,23 @@ } } +void ConfirmMoveOrStartUpload( + Profile* profile, + const std::vector<storage::FileSystemURL>& file_urls, + const CloudProvider cloud_provider) { + if (file_manager::file_tasks::AlwaysMoveOfficeFiles(profile)) { + return StartUpload(profile, file_urls, cloud_provider); + } + + if (cloud_provider == CloudProvider::kGoogleDrive) { + CloudUploadDialog::Show(profile, file_urls, + mojom::DialogPage::kMoveConfirmationGoogleDrive); + } else if (cloud_provider == CloudProvider::kOneDrive) { + CloudUploadDialog::Show(profile, file_urls, + mojom::DialogPage::kMoveConfirmationOneDrive); + } +} + void OnDialogComplete(Profile* profile, const std::vector<storage::FileSystemURL>& file_urls, const std::string& action) { @@ -86,7 +103,7 @@ using file_manager::file_tasks::SetPowerPointFileHandler; using file_manager::file_tasks::SetWordFileHandler; - if (action == kUserActionUploadToGoogleDrive) { + if (action == kUserActionConfirmOrUploadToGoogleDrive) { SetWordFileHandler(profile, file_manager::file_tasks::kActionIdWebDriveOfficeWord); SetExcelFileHandler(profile, @@ -94,9 +111,13 @@ SetPowerPointFileHandler( profile, file_manager::file_tasks::kActionIdWebDriveOfficePowerPoint); SetOfficeSetupComplete(profile); + ConfirmMoveOrStartUpload(profile, file_urls, CloudProvider::kGoogleDrive); + } else if (action == kUserActionConfirmOrUploadToOneDrive) { + // Default handlers have already been set by this point for Office/OneDrive. + ConfirmMoveOrStartUpload(profile, file_urls, CloudProvider::kOneDrive); + } else if (action == kUserActionUploadToGoogleDrive) { StartUpload(profile, file_urls, CloudProvider::kGoogleDrive); } else if (action == kUserActionUploadToOneDrive) { - // Default handlers have already been set by this point for Office/OneDrive. StartUpload(profile, file_urls, CloudProvider::kOneDrive); } else if (action == kUserActionSetUpGoogleDrive) { CloudUploadDialog::Show(profile, file_urls, @@ -126,7 +147,7 @@ if (empty_selection) { return false; } - StartUpload(profile, file_urls, cloud_provider); + ConfirmMoveOrStartUpload(profile, file_urls, cloud_provider); return true; } @@ -200,6 +221,9 @@ const int kDialogWidthForDriveSetup = 512; const int kDialogHeightForDriveSetup = 220; + +const int kDialogWidthForMoveConfirmation = 448; +const int kDialogHeightForMoveConfirmation = 228; } // namespace void CloudUploadDialog::GetDialogSize(gfx::Size* size) const { @@ -219,6 +243,12 @@ size->set_height(kDialogHeightForDriveSetup); return; } + case mojom::DialogPage::kMoveConfirmationGoogleDrive: + case mojom::DialogPage::kMoveConfirmationOneDrive: { + size->set_width(kDialogWidthForMoveConfirmation); + size->set_height(kDialogHeightForMoveConfirmation); + return; + } } }
diff --git a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog.h b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog.h index bee2ea6..eb8c354 100644 --- a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog.h +++ b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog.h
@@ -22,6 +22,10 @@ const char kUserActionSetUpOneDrive[] = "setup-onedrive"; const char kUserActionUploadToGoogleDrive[] = "upload-drive"; const char kUserActionUploadToOneDrive[] = "upload-onedrive"; +const char kUserActionConfirmOrUploadToGoogleDrive[] = + "confirm-or-upload-google-drive"; +const char kUserActionConfirmOrUploadToOneDrive[] = + "confirm-or-upload-onedrive"; // Either OneDrive for the Office PWA or Drive for Drive Web editing. enum class CloudProvider {
diff --git a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_page_handler.cc b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_page_handler.cc index d35ba59cd..0a5b085 100644 --- a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_page_handler.cc +++ b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_page_handler.cc
@@ -71,4 +71,8 @@ file_manager::file_tasks::SetOfficeSetupComplete(profile_); } +void CloudUploadPageHandler::SetAlwaysMoveOfficeFiles(bool always_move) { + file_manager::file_tasks::SetAlwaysMoveOfficeFiles(profile_, always_move); +} + } // namespace ash::cloud_upload
diff --git a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_page_handler.h b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_page_handler.h index 92f69a0..517e614 100644 --- a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_page_handler.h +++ b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_page_handler.h
@@ -43,6 +43,7 @@ void IsOfficePWAInstalled(IsOfficePWAInstalledCallback callback) override; void RespondAndClose(mojom::UserAction action) override; void SetOfficeAsDefaultHandler() override; + void SetAlwaysMoveOfficeFiles(bool always_move) override; private: Profile* profile_;
diff --git a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_ui.cc b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_ui.cc index 26d20db7..cd21bda 100644 --- a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_ui.cc +++ b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_ui.cc
@@ -79,6 +79,12 @@ case mojom::UserAction::kUploadToOneDrive: args.Append(kUserActionUploadToOneDrive); break; + case mojom::UserAction::kConfirmOrUploadToGoogleDrive: + args.Append(kUserActionConfirmOrUploadToGoogleDrive); + break; + case mojom::UserAction::kConfirmOrUploadToOneDrive: + args.Append(kUserActionConfirmOrUploadToOneDrive); + break; } ui::MojoWebDialogUI::CloseDialog(args); }
diff --git a/chrome/browser/ui/webui/ash/drive_internals_ui.cc b/chrome/browser/ui/webui/ash/drive_internals_ui.cc index af240d73..ab7133f 100644 --- a/chrome/browser/ui/webui/ash/drive_internals_ui.cc +++ b/chrome/browser/ui/webui/ash/drive_internals_ui.cc
@@ -291,6 +291,10 @@ weak_ptr_factory_.GetWeakPtr(), drivefs::mojom::MirrorPathStatus::kStop)); web_ui()->RegisterMessageCallback( + "setBulkPinningEnabled", + base::BindRepeating(&DriveInternalsWebUIHandler::SetBulkPinningEnabled, + weak_ptr_factory_.GetWeakPtr())); + web_ui()->RegisterMessageCallback( "enableTracing", base::BindRepeating(&DriveInternalsWebUIHandler::SetTracingEnabled, weak_ptr_factory_.GetWeakPtr(), true)); @@ -369,6 +373,7 @@ UpdateDriveDebugSection(); UpdateMirrorSyncSection(); + UpdateBulkPinningSection(); // When the drive-internals page is reloaded by the reload key, the page // content is recreated, but this WebUI object is not (instead, OnPageLoaded @@ -580,6 +585,19 @@ base::Value(drive::FileErrorToString(status))); } + void UpdateBulkPinningSection() { + if (!features::IsDriveFsBulkPinningEnabled()) { + SetSectionEnabled("bulk-pinning-section", false); + return; + } + + SetSectionEnabled("bulk-pinning-section", true); + + bool bulk_pinning_enabled = profile()->GetPrefs()->GetBoolean( + drive::prefs::kDriveFsBulkPinningEnabled); + MaybeCallJavascript("updateBulkPinning", base::Value(bulk_pinning_enabled)); + } + // Called when GetDeveloperMode() is complete. void OnGetDeveloperMode(bool enabled) { developer_mode_ = enabled; @@ -771,6 +789,21 @@ } } + void SetBulkPinningEnabled(const base::Value::List& args) { + AllowJavascript(); + drive::DriveIntegrationService* integration_service = + GetIntegrationService(); + if (!integration_service) { + return; + } + + if (args.size() == 1 && args[0].is_bool()) { + bool enabled = args[0].GetBool(); + profile()->GetPrefs()->SetBoolean( + drive::prefs::kDriveFsBulkPinningEnabled, enabled); + } + } + // Called when the "Startup Arguments" field on the page is submitted. void SetStartupArguments(const base::Value::List& args) { AllowJavascript();
diff --git a/chrome/browser/ui/webui/downloads/BUILD.gn b/chrome/browser/ui/webui/downloads/BUILD.gn index 279fd0ec..0bb8b1c 100644 --- a/chrome/browser/ui/webui/downloads/BUILD.gn +++ b/chrome/browser/ui/webui/downloads/BUILD.gn
@@ -9,4 +9,5 @@ mojom("mojo_bindings") { sources = [ "downloads.mojom" ] webui_module_path = "/" + use_typescript_sources = true }
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc index 0edb7b2..7c09a90 100644 --- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -2005,8 +2005,6 @@ IDS_SETTINGS_SAFETY_CHECK_EXTENSIONS_PRIMARY_LABEL}, {"safetyCheckExtensionsButtonAriaLabel", IDS_SETTINGS_SAFETY_CHECK_EXTENSIONS_BUTTON_ARIA_LABEL}, - {"safetyCheckNotificationPermissionReviewSecondaryLabel", - IDS_SETTINGS_SAFETY_CHECK_REVIEW_NOTIFICATION_PERMISSIONS_SECONDARY_LABEL}, {"safetyCheckNotificationPermissionReviewIgnoredToastLabel", IDS_SETTINGS_SAFETY_CHECK_NOTIFICATION_PERMISSION_REVIEW_IGNORED_TOAST_LABEL}, {"safetyCheckNotificationPermissionReviewBlockedToastLabel", @@ -2035,6 +2033,8 @@ IDS_SETTINGS_SAFETY_CHECK_NOTIFICATION_PERMISSION_REVIEW_BLOCK_ALL_LABEL}, {"safetyCheckUnusedSitePermissionsHeaderAriaLabel", IDS_SETTINGS_SAFETY_CHECK_UNUSED_SITE_PERMISSIONS_HEADER_ARIA_LABEL}, + {"safetyCheckNotificationPermissionReviewButtonAriaLabel", + IDS_SETTINGS_SAFETY_CHECK_NOTIFICATION_PERMISSIONS_REVIEW_BUTTON_ARIA_LABEL}, #if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING) {"safetyCheckChromeCleanerPrimaryLabel", IDS_SETTINGS_SAFETY_CHECK_CHROME_CLEANER_PRIMARY_LABEL},
diff --git a/chrome/browser/ui/webui/settings/settings_ui.cc b/chrome/browser/ui/webui/settings/settings_ui.cc index 3570e83..248787a7 100644 --- a/chrome/browser/ui/webui/settings/settings_ui.cc +++ b/chrome/browser/ui/webui/settings/settings_ui.cc
@@ -406,6 +406,9 @@ plural_string_handler->AddLocalizedString( "safetyCheckUnusedSitePermissionsHeaderLabel", IDS_SETTINGS_SAFETY_CHECK_UNUSED_SITE_PERMISSIONS_HEADER_LABEL); + plural_string_handler->AddLocalizedString( + "safetyCheckNotificationPermissionReviewSecondaryLabel", + IDS_SETTINGS_SAFETY_CHECK_REVIEW_NOTIFICATION_PERMISSIONS_SECONDARY_LABEL); web_ui->AddMessageHandler(std::move(plural_string_handler)); // Add the metrics handler to write uma stats.
diff --git a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_reader_registry.cc b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_reader_registry.cc index 943fd1f..c841b63 100644 --- a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_reader_registry.cc +++ b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_reader_registry.cc
@@ -143,13 +143,9 @@ return; } -#if BUILDFLAG(IS_CHROMEOS) - // On ChromeOS, we only verify integrity at install-time. On other OSes, - // we verify integrity once per session. - std::move(integrity_callback) - .Run(SignedWebBundleReader::SignatureVerificationAction:: - ContinueAndSkipSignatureVerification()); -#else + // TODO(crbug.com/1366309): On ChromeOS, we should only verify signatures at + // install-time. Until this is implemented, we will verify signatures on + // ChromeOS once per session. if (verified_files_.contains(web_bundle_path)) { // If we already verified the signatures of this Signed Web Bundle during // the current browser session, we trust that the Signed Web Bundle has not @@ -162,7 +158,6 @@ .Run(SignedWebBundleReader::SignatureVerificationAction:: ContinueAndVerifySignatures()); } -#endif } void IsolatedWebAppReaderRegistry::OnIntegrityBlockAndMetadataRead(
diff --git a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_reader_registry_unittest.cc b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_reader_registry_unittest.cc index 55893a5..cc980d8b 100644 --- a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_reader_registry_unittest.cc +++ b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_reader_registry_unittest.cc
@@ -355,11 +355,7 @@ EXPECT_EQ(result->head()->response_code, 200); } -#if BUILDFLAG(IS_CHROMEOS) - EXPECT_EQ(num_signature_verifications, 0ul); -#else EXPECT_EQ(num_signature_verifications, 1ul); -#endif // Verify that the cache cleanup timer has started. EXPECT_EQ(task_environment_.GetPendingMainThreadTaskCount(), 1ul) @@ -380,11 +376,7 @@ EXPECT_EQ(result->head()->response_code, 200); } -#if BUILDFLAG(IS_CHROMEOS) - EXPECT_EQ(num_signature_verifications, 0ul); -#else EXPECT_EQ(num_signature_verifications, 1ul); -#endif // Verify that the cache cleanup timer is still running. EXPECT_EQ(task_environment_.GetPendingMainThreadTaskCount(), 1ul) @@ -417,13 +409,9 @@ EXPECT_EQ(result->head()->response_code, 200); } -#if BUILDFLAG(IS_CHROMEOS) - EXPECT_EQ(num_signature_verifications, 0ul); -#else // Signatures should not have been verified again, since we only verify them // once per session per file path. EXPECT_EQ(num_signature_verifications, 1ul); -#endif // Verify that the cache cleanup timer has started again. EXPECT_EQ(task_environment_.GetPendingMainThreadTaskCount(), 1ul) @@ -543,23 +531,6 @@ FulfillIntegrityBlock(); -#if BUILDFLAG(IS_CHROMEOS) - // On ChromeOS, signatures are only verified at installation-time, thus the - // `FakeSignatureVerifier` set up above will never be called. - // TODO(crbug.com/1366309): Make sure signatures are actually verified during - // installation once installation is implemented. - FulfillMetadata(); - FulfillResponse(resource_request); - - ReadResult result = read_response_future.Take(); - ASSERT_TRUE(result.has_value()) << result.error().message; - - histogram_tester.ExpectBucketCount( - "WebApp.Isolated.ReadIntegrityBlockAndMetadataStatus", - IsolatedWebAppReaderRegistry::ReadIntegrityBlockAndMetadataStatus:: - kSuccess, - 1); -#else ReadResult result = read_response_future.Take(); ASSERT_FALSE(result.has_value()); EXPECT_EQ(result.error().type, @@ -573,7 +544,6 @@ IsolatedWebAppReaderRegistry::ReadIntegrityBlockAndMetadataStatus:: kSignatureVerificationError, 1); -#endif // BUILDFLAG(IS_CHROMEOS) } INSTANTIATE_TEST_SUITE_P(
diff --git a/chrome/browser/web_applications/web_app_icon_downloader_unittest.cc b/chrome/browser/web_applications/web_app_icon_downloader_unittest.cc index 2aaab132..8d1a913 100644 --- a/chrome/browser/web_applications/web_app_icon_downloader_unittest.cc +++ b/chrome/browser/web_applications/web_app_icon_downloader_unittest.cc
@@ -411,10 +411,9 @@ class WebAppIconDownloaderPrerenderTest : public WebAppIconDownloaderTest { public: WebAppIconDownloaderPrerenderTest() { - scoped_feature_list_.InitWithFeatures( - {blink::features::kPrerender2}, + scoped_feature_list_.InitAndDisableFeature( // This feature is to run test on any bot. - {blink::features::kPrerender2MemoryControls}); + blink::features::kPrerender2MemoryControls); } private:
diff --git a/chrome/browser/webauthn/authenticator_request_scheduler_unittest.cc b/chrome/browser/webauthn/authenticator_request_scheduler_unittest.cc index 2d82bdd..5e428607d 100644 --- a/chrome/browser/webauthn/authenticator_request_scheduler_unittest.cc +++ b/chrome/browser/webauthn/authenticator_request_scheduler_unittest.cc
@@ -86,11 +86,10 @@ : public AuthenticatorRequestSchedulerTest { public: AuthenticatorRequestSchedulerPrerenderTest() { - scoped_feature_list_.InitWithFeatures( - {blink::features::kPrerender2}, + scoped_feature_list_.InitAndDisableFeature( // Disable the memory requirement of Prerender2 so the test can run on // any bot. - {blink::features::kPrerender2MemoryControls}); + blink::features::kPrerender2MemoryControls); } ~AuthenticatorRequestSchedulerPrerenderTest() override = default;
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index ba0b400..a64800d 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-main-1669226354-3aba619386ea79bbf76dfcf352f4c07cc3e891b2.profdata +chrome-linux-main-1669269205-374bccde97d17507fb132bd7d2e1e6c948bbcec9.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index d929044..628c1933 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1669226354-a033b34198972286de177e47c7f34244d10f7533.profdata +chrome-mac-arm-main-1669269205-a70107538c807752a4af0982ab148bfe3fe0e9c2.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index 6e38fe6..017bfac 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-main-1669226354-d808bb044fa2957e0b8096006c2631ccb72a9d22.profdata +chrome-mac-main-1669288813-e77f895892d143c17ddb81e03bf475645e7d23c5.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index 381b74f..284b131 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1669215337-f8119f6a2c27dea3d944627c637d7a6359d27ba4.profdata +chrome-win32-main-1669288813-c6197658b6949a6abafcd9e81bd33a9d52f20571.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index 267f6d3a..2cf01ff2 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1669226354-2dc46fdc1f9ddcef2c0e19d351d1c4d52f1b0d50.profdata +chrome-win64-main-1669280396-20922a4e7dbdb60a960caeb9517c8a24c3f86f40.profdata
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn index e645c4b..9e21641 100644 --- a/chrome/common/BUILD.gn +++ b/chrome/common/BUILD.gn
@@ -51,6 +51,7 @@ "ENABLE_WEBUI_CERTIFICATE_VIEWER=$enable_webui_certificate_viewer", "ENABLE_WEBUI_TAB_STRIP=$enable_webui_tab_strip", "OPTIMIZE_WEBUI=$optimize_webui", + "ENABLE_BOUND_SESSION_CREDENTIALS=$enable_bound_session_credentials", ] }
diff --git a/chrome/common/extensions/api/extension.json b/chrome/common/extensions/api/extension.json index 4799d4c..a64ee51b 100644 --- a/chrome/common/extensions/api/extension.json +++ b/chrome/common/extensions/api/extension.json
@@ -89,7 +89,7 @@ "type": { "$ref": "ViewType", "optional": true, - "description": "The type of view to get. If omitted, returns all views (including background pages and tabs). Valid values: 'tab', 'notification', 'popup'." + "description": "The type of view to get. If omitted, returns all views (including background pages and tabs)." }, "windowId": { "type": "integer",
diff --git a/chrome/common/extensions/api/input_method_private.json b/chrome/common/extensions/api/input_method_private.json index f1b6baa3..6d7ebdf 100644 --- a/chrome/common/extensions/api/input_method_private.json +++ b/chrome/common/extensions/api/input_method_private.json
@@ -314,22 +314,6 @@ } ] }, { - "name": "notifyImeMenuItemActivated", - "type": "function", - "description": "Fires the input.ime.onMenuItemActivated event.", - "parameters": [ - { - "name": "engineID", - "type": "string", - "description": "ID of the engine to use." - }, - { - "name": "name", - "type": "string", - "description": "Name of the MenuItem which was activated" - } - ] - }, { "name": "showInputView", "type": "function", "description": "Shows the input view window. If the input view window is already shown, this function will do nothing.",
diff --git a/chrome/common/features.gni b/chrome/common/features.gni index 1c172ac..7aa0949 100644 --- a/chrome/common/features.gni +++ b/chrome/common/features.gni
@@ -72,6 +72,10 @@ # Enables the webui certificate viewer dialog. enable_webui_certificate_viewer = toolkit_views + # Compile time flag for bound session Credentials. + # Warning: This must not be enabled in official builds. + enable_bound_session_credentials = false + # optimize_webui was moved to ui/base/ui_features.gni }
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index dde9ee2fa..49ba1092 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc
@@ -1942,6 +1942,9 @@ // Whether the office files setup flow has ever been completed by the user. const char kOfficeSetupComplete[] = "filebrowser.office.setup_complete"; + +// Whether we should always move office files without prompting the user first. +const char kOfficeFilesAlwaysMove[] = "filebrowser.office.always_move"; #endif // A flag to enable/disable the Shared Clipboard feature which enables users to
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index 77bceeb..10760b1 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h
@@ -637,6 +637,7 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) extern const char kDefaultHandlersForFileExtensions[]; extern const char kOfficeSetupComplete[]; +extern const char kOfficeFilesAlwaysMove[]; #endif extern const char kSharedClipboardEnabled[];
diff --git a/chrome/common/profiler/unwind_util.cc b/chrome/common/profiler/unwind_util.cc index 0add095..a42ae1f 100644 --- a/chrome/common/profiler/unwind_util.cc +++ b/chrome/common/profiler/unwind_util.cc
@@ -5,6 +5,7 @@ #include "chrome/common/profiler/unwind_util.h" #include <memory> +#include <type_traits> #include <vector> #include "base/android/library_loader/anchor_functions.h" @@ -30,24 +31,41 @@ #define ANDROID_ARM32_UNWINDING_SUPPORTED 0 #endif +#if BUILDFLAG(IS_ANDROID) && defined(ARCH_CPU_ARM64) && \ + BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS) +#define ANDROID_ARM64_UNWINDING_SUPPORTED 1 +#else +#define ANDROID_ARM64_UNWINDING_SUPPORTED 0 +#endif + +#if ANDROID_ARM32_UNWINDING_SUPPORTED || ANDROID_ARM64_UNWINDING_SUPPORTED +#define ANDROID_UNWINDING_SUPPORTED 1 +#else +#define ANDROID_UNWINDING_SUPPORTED 0 +#endif + +#if ANDROID_UNWINDING_SUPPORTED +#include "chrome/android/modules/stack_unwinder/public/module.h" +#endif // ANDROID_UNWINDING_SUPPORTED + #if ANDROID_ARM32_UNWINDING_SUPPORTED #include "base/android/apk_assets.h" #include "base/files/memory_mapped_file.h" #include "base/profiler/arm_cfi_table.h" -#include "chrome/android/modules/stack_unwinder/public/module.h" - -#if BUILDFLAG(USE_ANDROID_UNWINDER_V2) #include "base/profiler/chrome_unwinder_android_v2.h" -#else -#include "base/profiler/chrome_unwinder_android.h" -#endif +#endif // ANDROID_ARM32_UNWINDING_SUPPORTED +#if ANDROID_ARM64_UNWINDING_SUPPORTED +#include "base/profiler/frame_pointer_unwinder.h" +#endif // ANDROID_ARM64_UNWINDING_SUPPORTED + +#if ANDROID_UNWINDING_SUPPORTED extern "C" { // The address of |__executable_start| is the base address of the executable or // shared library. extern char __executable_start; } -#endif // ANDROID_ARM32_UNWINDING_SUPPORTED +#endif // ANDROID_UNWINDING_SUPPORTED // See `RequestUnwindPrerequisitesInstallation` below. BASE_FEATURE(kInstallAndroidUnwindDfm, @@ -56,8 +74,8 @@ namespace { +// Encapsulates the setup required to create the Chrome unwinder on Android. #if ANDROID_ARM32_UNWINDING_SUPPORTED -#if BUILDFLAG(USE_ANDROID_UNWINDER_V2) class ChromeUnwinderCreator { public: ChromeUnwinderCreator() { @@ -86,40 +104,25 @@ private: base::MemoryMappedFile chrome_cfi_file_; }; -#else // BUILDFLAG(USE_ANDROID_UNWINDER_V2) -// Encapsulates the setup required to create the Chrome unwinder on Android. +#elif ANDROID_ARM64_UNWINDING_SUPPORTED // ANDROID_ARM32_UNWINDING_SUPPORTED class ChromeUnwinderCreator { public: - ChromeUnwinderCreator() { - constexpr char kCfiFileName[] = "assets/unwind_cfi_32"; - constexpr char kSplitName[] = "stack_unwinder"; - - base::MemoryMappedFile::Region cfi_region; - int fd = base::android::OpenApkAsset(kCfiFileName, kSplitName, &cfi_region); - DCHECK_GE(fd, 0); - bool mapped_file_ok = - chrome_cfi_file_.Initialize(base::File(fd), cfi_region); - DCHECK(mapped_file_ok); - chrome_cfi_table_ = base::ArmCFITable::Parse( - {chrome_cfi_file_.data(), chrome_cfi_file_.length()}); - DCHECK(chrome_cfi_table_); - } - - ChromeUnwinderCreator(const ChromeUnwinderCreator&) = delete; - ChromeUnwinderCreator& operator=(const ChromeUnwinderCreator&) = delete; - std::unique_ptr<base::Unwinder> Create() { - return std::make_unique<base::ChromeUnwinderAndroid>( - chrome_cfi_table_.get(), - reinterpret_cast<uintptr_t>(&__executable_start)); + return std::make_unique<base::FramePointerUnwinder>(); } - private: - base::MemoryMappedFile chrome_cfi_file_; - std::unique_ptr<base::ArmCFITable> chrome_cfi_table_; + // Since this class is trivially destructible, it cannot be wrapped in + // `base::NoDestructor`. However, other versions of this class *are* wrapped + // in `base::NoDestructor`. These overloads allow consistently calling member + // functions, regardless of whether a version of this class is wrapped in + // `base::NoDestructor` or not (please see `CreateCoreUnwinders` below for + // more context). + const ChromeUnwinderCreator* operator->() const { return this; } + ChromeUnwinderCreator* operator->() { return this; } }; -#endif // BUILDFLAG(USE_ANDROID_UNWINDER_V2) +#endif // ANDROID_ARM32_UNWINDING_SUPPORTED +#if ANDROID_UNWINDING_SUPPORTED // Encapsulates the setup required to create the Android native unwinder. class NativeUnwinderCreator { public: @@ -146,7 +149,10 @@ static base::NoDestructor<NativeUnwinderCreator> native_unwinder_creator( stack_unwinder_module); - static base::NoDestructor<ChromeUnwinderCreator> chrome_unwinder_creator; + static std::conditional< + std::is_trivially_destructible_v<ChromeUnwinderCreator>, + ChromeUnwinderCreator, base::NoDestructor<ChromeUnwinderCreator>>::type + chrome_unwinder_creator; // Note order matters: the more general unwinder must appear first in the // vector. @@ -176,7 +182,7 @@ return stack_unwinder::Module::IsInstalled(); } }; -#endif // ANDROID_ARM32_UNWINDING_SUPPORTED +#endif // ANDROID_UNWINDING_SUPPORTED } // namespace @@ -188,7 +194,7 @@ if (AreUnwindPrerequisitesAvailable(channel, prerequites_delegate)) { return; } -#if ANDROID_ARM32_UNWINDING_SUPPORTED && defined(OFFICIAL_BUILD) && \ +#if (ANDROID_UNWINDING_SUPPORTED) && defined(OFFICIAL_BUILD) && \ BUILDFLAG(GOOGLE_CHROME_BRANDING) ModuleUnwindPrerequisitesDelegate default_delegate; if (prerequites_delegate == nullptr) { @@ -224,7 +230,7 @@ // prerequisites are always considered to be available for non-Android // platforms. #if BUILDFLAG(IS_ANDROID) -#if ANDROID_ARM32_UNWINDING_SUPPORTED +#if ANDROID_UNWINDING_SUPPORTED #if defined(OFFICIAL_BUILD) && BUILDFLAG(GOOGLE_CHROME_BRANDING) // Sometimes, DFMs can be installed even if not requested by Chrome // explicitly (for instance, in some app stores). Therefore, even if the @@ -241,32 +247,32 @@ prerequites_delegate = &default_delegate; } return prerequites_delegate->AreAvailable(channel); -#else // ANDROID_ARM32_UNWINDING_SUPPORTED +#else // ANDROID_UNWINDING_SUPPORTED return false; -#endif // ANDROID_ARM32_UNWINDING_SUPPORTED +#endif // ANDROID_UNWINDING_SUPPORTED #else // BUILDFLAG(IS_ANDROID) return true; #endif // BUILDFLAG(IS_ANDROID) } -#if ANDROID_ARM32_UNWINDING_SUPPORTED +#if ANDROID_UNWINDING_SUPPORTED stack_unwinder::Module* GetOrLoadModule() { DCHECK(AreUnwindPrerequisitesAvailable(chrome::GetChannel())); static base::NoDestructor<std::unique_ptr<stack_unwinder::Module>> stack_unwinder_module(stack_unwinder::Module::Load()); return stack_unwinder_module.get()->get(); } -#endif // ANDROID_ARM32_UNWINDING_SUPPORTED +#endif // ANDROID_UNWINDING_SUPPORTED base::StackSamplingProfiler::UnwindersFactory CreateCoreUnwindersFactory() { if (!AreUnwindPrerequisitesAvailable(chrome::GetChannel())) { return base::StackSamplingProfiler::UnwindersFactory(); } -#if ANDROID_ARM32_UNWINDING_SUPPORTED +#if ANDROID_UNWINDING_SUPPORTED return base::BindOnce(CreateCoreUnwinders, GetOrLoadModule()); -#else // ANDROID_ARM32_UNWINDING_SUPPORTED +#else // ANDROID_UNWINDING_SUPPORTED return base::StackSamplingProfiler::UnwindersFactory(); -#endif // ANDROID_ARM32_UNWINDING_SUPPORTED +#endif // ANDROID_UNWINDING_SUPPORTED } base::StackSamplingProfiler::UnwindersFactory @@ -274,9 +280,9 @@ if (!AreUnwindPrerequisitesAvailable(chrome::GetChannel())) { return base::StackSamplingProfiler::UnwindersFactory(); } -#if ANDROID_ARM32_UNWINDING_SUPPORTED +#if ANDROID_UNWINDING_SUPPORTED return base::BindOnce(CreateLibunwindstackUnwinders, GetOrLoadModule()); -#else // ANDROID_ARM32_UNWINDING_SUPPORTED +#else // ANDROID_UNWINDING_SUPPORTED return base::StackSamplingProfiler::UnwindersFactory(); -#endif // ANDROID_ARM32_UNWINDING_SUPPORTED +#endif // ANDROID_UNWINDING_SUPPORTED }
diff --git a/chrome/common/profiler/unwind_util_unittest.cc b/chrome/common/profiler/unwind_util_unittest.cc index c1fa0b2..19c8542 100644 --- a/chrome/common/profiler/unwind_util_unittest.cc +++ b/chrome/common/profiler/unwind_util_unittest.cc
@@ -17,6 +17,14 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#if BUILDFLAG(IS_ANDROID) && \ + ((defined(ARCH_CPU_ARMEL) && BUILDFLAG(ENABLE_ARM_CFI_TABLE)) || \ + defined(ARCH_CPU_ARM64)) +#define ANDROID_UNWINDING_SUPPORTED 1 +#else +#define ANDROID_UNWINDING_SUPPORTED 0 +#endif + namespace { using ::testing::_; @@ -110,7 +118,7 @@ {version_info::Channel::STABLE, &false_mock_delegate, false}, {version_info::Channel::UNKNOWN, &false_mock_delegate, false}, -#if defined(ARCH_CPU_ARMEL) && BUILDFLAG(ENABLE_ARM_CFI_TABLE) +#if ANDROID_UNWINDING_SUPPORTED {version_info::Channel::CANARY, &true_mock_delegate, true}, {version_info::Channel::DEV, &true_mock_delegate, true}, {version_info::Channel::BETA, &true_mock_delegate, true}, @@ -125,14 +133,14 @@ {version_info::Channel::STABLE, &true_mock_delegate, true}, {version_info::Channel::UNKNOWN, &true_mock_delegate, true}, #endif // defined(OFFICIAL_BUILD) && BUILDFLAG(GOOGLE_CHROME_BRANDING) -#else // defined(ARCH_CPU_ARMEL) && BUILDFLAG(ENABLE_ARM_CFI_TABLE) - // Unwinding on non-ARM32 platforms is not currently supported for Android. +#else // ANDROID_UNWINDING_SUPPORTED + // Unwinding on any other platforms is not currently supported for Android. {version_info::Channel::CANARY, &true_mock_delegate, false}, {version_info::Channel::DEV, &true_mock_delegate, false}, {version_info::Channel::BETA, &true_mock_delegate, false}, {version_info::Channel::STABLE, &true_mock_delegate, false}, {version_info::Channel::UNKNOWN, &true_mock_delegate, false}, -#endif // defined(ARCH_CPU_ARMEL) && BUILDFLAG(ENABLE_ARM_CFI_TABLE) +#endif // ANDROID_UNWINDING_SUPPORTED #else // BUILDFLAG(IS_ANDROID) // Non-Android platforms' unwinders do not need any specific prerequisites // beyond what is already bundled and available with Chrome. Therefore,
diff --git a/chrome/install_static/BUILD.gn b/chrome/install_static/BUILD.gn index 4a0c972a..1de210a 100644 --- a/chrome/install_static/BUILD.gn +++ b/chrome/install_static/BUILD.gn
@@ -28,6 +28,7 @@ public_deps = [ ":buildflags", "//build:branding_buildflags", + "//chrome/browser/chrome_for_testing:buildflags", "//chrome/chrome_elf:nt_registry", ] @@ -58,6 +59,11 @@ "google_chrome_install_modes.cc", "google_chrome_install_modes.h", ] + } else if (is_chrome_for_testing_branded) { + sources += [ + "google_chrome_for_testing_install_modes.cc", + "google_chrome_for_testing_install_modes.h", + ] } else { sources += [ "chromium_install_modes.cc",
diff --git a/chrome/install_static/DEPS b/chrome/install_static/DEPS index 1a9c8e8..d0c776c 100644 --- a/chrome/install_static/DEPS +++ b/chrome/install_static/DEPS
@@ -8,6 +8,8 @@ "+base/win/windows_types.h", # Nothing from chrome. "-chrome", + # Except Chrome for Testing. + "+chrome/browser/chrome_for_testing/buildflags.h", # For the app icon resource identifiers. "+chrome/app/chrome_dll_resource.h", # All registry access should go through nt_registry.
diff --git a/chrome/install_static/chromium_install_modes.cc b/chrome/install_static/chromium_install_modes.cc index 38740b5..b3d7a13 100644 --- a/chrome/install_static/chromium_install_modes.cc +++ b/chrome/install_static/chromium_install_modes.cc
@@ -33,7 +33,7 @@ L"", // Empty install_suffix for the primary install mode. .logo_suffix = L"", // No logo suffix for the primary install mode. .app_guid = - L"", // Empty app_guid since no integraion with Google Update. + L"", // Empty app_guid since no integration with Google Update. .base_app_name = L"Chromium", // A distinct base_app_name. .base_app_id = L"Chromium", // A distinct base_app_id. .prog_id_prefix = L"ChromiumHTM", // ProgID prefix.
diff --git a/chrome/install_static/google_chrome_for_testing_install_modes.cc b/chrome/install_static/google_chrome_for_testing_install_modes.cc new file mode 100644 index 0000000..02290bd --- /dev/null +++ b/chrome/install_static/google_chrome_for_testing_install_modes.cc
@@ -0,0 +1,86 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Brand-specific constants and install modes for Google Chrome for Testing. + +#include "chrome/install_static/google_chrome_for_testing_install_modes.h" + +#include <stdlib.h> + +#include "chrome/app/chrome_dll_resource.h" +#include "chrome/common/chrome_icon_resources_win.h" +#include "chrome/install_static/install_modes.h" + +namespace install_static { + +const wchar_t kCompanyPathName[] = L"Google"; + +const wchar_t kProductPathName[] = L"Chrome for Testing"; + +const size_t kProductPathNameLength = _countof(kProductPathName) - 1; + +const char kSafeBrowsingName[] = "googlechromefortesting"; + +const InstallConstants kInstallModes[] = { + // The primary install mode for stable Google Chrome. + { + .size = sizeof(kInstallModes[0]), + .index = GOOGLE_CHROME_FOR_TESTING_INDEX, // The one and only mode for + // Google Chrome for Testing. + .install_switch = + "", // No install switch for the primary install mode. + .install_suffix = + L"", // Empty install_suffix for the primary install mode. + .logo_suffix = L"", // No logo suffix for the primary install mode. + .app_guid = + L"", // Empty app_guid since no integration with Google Update. + .base_app_name = + L"Google Chrome for Testing", // A distinct base_app_name. + .base_app_id = L"ChromeforTesting", // A distinct base_app_id. + .prog_id_prefix = L"CfTHTML", // ProgID prefix. + .prog_id_description = + L"Chrome for Testing HTML Document", // ProgID description. + .active_setup_guid = + L"{E25CFD4E-D9D4-4123-936A-286FBB19BA5B}", // Active Setup GUID. + .legacy_command_execute_clsid = L"", // CommandExecuteImpl CLSID. + .toast_activator_clsid = {0x77ED8F9B, + 0xE27A, + 0x499F, + {0x8E, 0x2F, 0xD7, 0xC0, 0x41, 0x57, 0xCF, + 0x64}}, // Toast Activator CLSID. + // {77ED8F9B-E27A-499F-8E2F-D7C04157CF64} + .elevator_clsid = {0x724349BF, + 0xE1CF, + 0x4481, + {0xA6, 0x4D, 0x8C, 0xD1, 0x01, 0x83, 0xCA, + 0x03}}, // Elevator CLSID. + // {724349BF-E1CF-4481-A64D-8CD10183CA03} + .elevator_iid = {0x3DC48E97, + 0x47D0, + 0x476F, + {0x8F, 0x89, 0x07, 0x92, 0xFC, 0x61, 0x15, + 0x67}}, // IElevator IID and TypeLib + // {3DC48E97-47D0-476F-8F89-0792FC611567} + .default_channel_name = + L"", // Empty default channel name since no update integration. + .channel_strategy = ChannelStrategy::UNSUPPORTED, + .supports_system_level = + false, // Does not support system-level installs. + .supports_set_as_default_browser = + false, // Does not support in-product set as default browser UX. + .supports_retention_experiments = + false, // Does not support retention experiments. + .app_icon_resource_index = + icon_resources::kApplicationIndex, // App icon resource index. + .app_icon_resource_id = IDR_MAINFRAME, // App icon resource id. + .sandbox_sid_prefix = + L"S-1-15-2-3251537155-1984446955-2931258699-841473695-1938553385-" + L"924012153-", // App container sid prefix for sandbox. + }, +}; + +static_assert(_countof(kInstallModes) == NUM_INSTALL_MODES, + "Imbalance between kInstallModes and InstallConstantIndex"); + +} // namespace install_static
diff --git a/chrome/install_static/google_chrome_for_testing_install_modes.h b/chrome/install_static/google_chrome_for_testing_install_modes.h new file mode 100644 index 0000000..fb77d4c --- /dev/null +++ b/chrome/install_static/google_chrome_for_testing_install_modes.h
@@ -0,0 +1,21 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Brand-specific types and constants for Google Chrome for Testing + +#ifndef CHROME_INSTALL_STATIC_GOOGLE_CHROME_FOR_TESTING_INSTALL_MODES_H_ +#define CHROME_INSTALL_STATIC_GOOGLE_CHROME_FOR_TESTING_INSTALL_MODES_H_ + +namespace install_static { + +// Note: This list of indices must be kept in sync with the brand-specific +// resource strings in chrome/installer/util/prebuild/create_string_rc. +enum InstallConstantIndex { + GOOGLE_CHROME_FOR_TESTING_INDEX, + NUM_INSTALL_MODES, +}; + +} // namespace install_static + +#endif // CHROME_INSTALL_STATIC_GOOGLE_CHROME_FOR_TESTING_INSTALL_MODES_H_
diff --git a/chrome/install_static/install_modes.h b/chrome/install_static/install_modes.h index 53cbe32..d4c95bee 100644 --- a/chrome/install_static/install_modes.h +++ b/chrome/install_static/install_modes.h
@@ -31,6 +31,7 @@ #include <string> #include "build/branding_buildflags.h" +#include "chrome/browser/chrome_for_testing/buildflags.h" #include "chrome/install_static/install_constants.h" // Include the brand-specific values. Each of these must define: @@ -40,6 +41,8 @@ // kInstallModes. #if BUILDFLAG(GOOGLE_CHROME_BRANDING) #include "chrome/install_static/google_chrome_install_modes.h" +#elif BUILDFLAG(GOOGLE_CHROME_FOR_TESTING_BRANDING) +#include "chrome/install_static/google_chrome_for_testing_install_modes.h" #else #include "chrome/install_static/chromium_install_modes.h" #endif
diff --git a/chrome/install_static/install_util_unittest.cc b/chrome/install_static/install_util_unittest.cc index 6181720..1f08ae7 100644 --- a/chrome/install_static/install_util_unittest.cc +++ b/chrome/install_static/install_util_unittest.cc
@@ -12,6 +12,7 @@ #include "base/test/test_reg_util_win.h" #include "base/win/win_util.h" #include "build/branding_buildflags.h" +#include "chrome/browser/chrome_for_testing/buildflags.h" #include "chrome/chrome_elf/nt_registry/nt_registry.h" #include "chrome/install_static/buildflags.h" #include "chrome/install_static/install_details.h" @@ -741,6 +742,13 @@ InstallStaticUtilTest, testing::Combine(testing::Values(CANARY_INDEX), testing::Values("user"))); +#elif BUILDFLAG(GOOGLE_CHROME_FOR_TESTING_BRANDING) +// Chrome for Testing is only at user level. +INSTANTIATE_TEST_SUITE_P( + ChromeForTesting, + InstallStaticUtilTest, + testing::Combine(testing::Values(GOOGLE_CHROME_FOR_TESTING_INDEX), + testing::Values("user"))); #else // BUILDFLAG(GOOGLE_CHROME_BRANDING) // Chromium supports user and system levels. INSTANTIATE_TEST_SUITE_P(Chromium,
diff --git a/chrome/install_static/product_install_details_unittest.cc b/chrome/install_static/product_install_details_unittest.cc index 6273e1b..5e46301e 100644 --- a/chrome/install_static/product_install_details_unittest.cc +++ b/chrome/install_static/product_install_details_unittest.cc
@@ -14,6 +14,7 @@ #include "base/win/registry.h" #include "base/win/windows_version.h" #include "build/branding_buildflags.h" +#include "chrome/browser/chrome_for_testing/buildflags.h" #include "chrome/chrome_elf/nt_registry/nt_registry.h" #include "chrome/install_static/buildflags.h" #include "chrome/install_static/install_constants.h" @@ -185,6 +186,16 @@ L"canary", }, }; +#elif BUILDFLAG(GOOGLE_CHROME_FOR_TESTING_BRANDING) +constexpr TestData kTestData[] = { + { + L"C:\\Users\\user\\AppData\\Local\\Google\\Chrome for " + L"Testing\\Application\\chrome.exe", + GOOGLE_CHROME_FOR_TESTING_INDEX, + false, + L"", + }, +}; #else // BUILDFLAG(GOOGLE_CHROME_BRANDING) constexpr TestData kTestData[] = { {
diff --git a/chrome/installer/setup/DEPS b/chrome/installer/setup/DEPS index a3e1542e..5eed5289 100644 --- a/chrome/installer/setup/DEPS +++ b/chrome/installer/setup/DEPS
@@ -1,4 +1,5 @@ include_rules = [ + "+chrome/browser/chrome_for_testing/buildflags.h", "+chrome/browser/enterprise/connectors/device_trust/key_management/installer/key_rotation_manager.h", "+chrome/browser/enterprise/connectors/device_trust/key_management/installer/management_service/rotate_util.h", "+chrome/browser/enterprise/connectors/device_trust/key_management/core/network/win_key_network_delegate.h",
diff --git a/chrome/installer/setup/install_unittest.cc b/chrome/installer/setup/install_unittest.cc index 8738aff9..7e945f3 100644 --- a/chrome/installer/setup/install_unittest.cc +++ b/chrome/installer/setup/install_unittest.cc
@@ -24,6 +24,7 @@ #include "base/win/scoped_com_initializer.h" #include "base/win/shortcut.h" #include "build/branding_buildflags.h" +#include "chrome/browser/chrome_for_testing/buildflags.h" #include "chrome/install_static/install_details.h" #include "chrome/install_static/install_modes.h" #include "chrome/install_static/test/scoped_install_details.h" @@ -197,6 +198,13 @@ CreateVisualElementsManifestTest, testing::Combine(testing::Values(install_static::CANARY_INDEX), testing::Values(kExpectedCanaryManifest))); +#elif BUILDFLAG(GOOGLE_CHROME_FOR_TESTING_BRANDING) +INSTANTIATE_TEST_SUITE_P( + ChromeForTesting, + CreateVisualElementsManifestTest, + testing::Combine( + testing::Values(install_static::GOOGLE_CHROME_FOR_TESTING_INDEX), + testing::Values(kExpectedPrimaryManifest))); #else INSTANTIATE_TEST_SUITE_P( Chromium,
diff --git a/chrome/installer/setup/install_worker_unittest.cc b/chrome/installer/setup/install_worker_unittest.cc index 3940cde..e33e315 100644 --- a/chrome/installer/setup/install_worker_unittest.cc +++ b/chrome/installer/setup/install_worker_unittest.cc
@@ -15,6 +15,7 @@ #include "base/win/registry.h" #include "base/win/win_util.h" #include "base/win/windows_version.h" +#include "chrome/browser/chrome_for_testing/buildflags.h" #include "chrome/common/chrome_constants.h" #include "chrome/install_static/install_util.h" #include "chrome/install_static/test/scoped_install_details.h" @@ -271,6 +272,8 @@ // Tests //------------------------------------------------------------------------------ +// Chrome for Testing does not support system-level installations. +#if !BUILDFLAG(GOOGLE_CHROME_FOR_TESTING_BRANDING) TEST_F(InstallWorkerTest, TestInstallChromeSystem) { const bool system_level = true; NiceMock<MockWorkItemList> work_item_list; @@ -318,6 +321,7 @@ AddInstallWorkItems(install_params, &work_item_list); } +#endif // Tests for installer::AddUpdateBrandCodeWorkItem(). //------------------------------------------------------------------------------ @@ -519,7 +523,7 @@ value_name == path_with_another_dll.value()) { continue; } - FAIL() << "Invalid registry value encountered: " << value_name;; + FAIL() << "Invalid registry value encountered: " << value_name; } } }
diff --git a/chrome/installer/setup/setup_install_details_unittest.cc b/chrome/installer/setup/setup_install_details_unittest.cc index bc56916..76a69f0 100644 --- a/chrome/installer/setup/setup_install_details_unittest.cc +++ b/chrome/installer/setup/setup_install_details_unittest.cc
@@ -10,6 +10,7 @@ #include "base/memory/raw_ref.h" #include "base/test/test_reg_util_win.h" #include "build/branding_buildflags.h" +#include "chrome/browser/chrome_for_testing/buildflags.h" #include "chrome/chrome_elf/nt_registry/nt_registry.h" #include "chrome/install_static/buildflags.h" #include "chrome/install_static/install_details.h" @@ -431,6 +432,26 @@ L"extended", // Expect the channel override. }, }; +#elif BUILDFLAG(GOOGLE_CHROME_FOR_TESTING_BRANDING) +constexpr TestData kTestData[] = { + // User-level test cases. + { + L"setup.exe", // User-level, primary mode. + L"", // New install. + install_static::GOOGLE_CHROME_FOR_TESTING_INDEX, // Expect primary + // mode. + false, // Expect user-level. + L"", // Expect empty channel. + }, + { + L"setup.exe", // User-level, primary mode. + L"--uninstall", // Updating an existing install. + install_static::GOOGLE_CHROME_FOR_TESTING_INDEX, // Expect primary + // mode. + false, // Expect user-level. + L"", // Expect empty channel. + }, +}; #else // BUILDFLAG(GOOGLE_CHROME_BRANDING) constexpr TestData kTestData[] = { // User-level test cases.
diff --git a/chrome/installer/util/DEPS b/chrome/installer/util/DEPS index 3f2ad350..3feedd52 100644 --- a/chrome/installer/util/DEPS +++ b/chrome/installer/util/DEPS
@@ -1,4 +1,5 @@ include_rules = [ + "+chrome/browser/chrome_for_testing/buildflags.h", # This file is generated but otherwise would be excluded because of the # "-chrome" rule in a parent dir. "+chrome/grit/chromium_strings.h",
diff --git a/chrome/installer/util/beacons_unittest.cc b/chrome/installer/util/beacons_unittest.cc index 32c9e66..9af6ca71 100644 --- a/chrome/installer/util/beacons_unittest.cc +++ b/chrome/installer/util/beacons_unittest.cc
@@ -12,6 +12,7 @@ #include "base/win/registry.h" #include "base/win/win_util.h" #include "build/branding_buildflags.h" +#include "chrome/browser/chrome_for_testing/buildflags.h" #include "chrome/install_static/install_details.h" #include "chrome/install_static/install_modes.h" #include "chrome/install_static/test/scoped_install_details.h" @@ -248,6 +249,14 @@ DefaultBrowserBeaconTest, testing::Combine(testing::Values(install_static::CANARY_INDEX), testing::Values("user"))); +#elif BUILDFLAG(GOOGLE_CHROME_FOR_TESTING_BRANDING) +// Chrome for Testing is only at user level. +INSTANTIATE_TEST_SUITE_P( + ChromeForTesting, + DefaultBrowserBeaconTest, + testing::Combine( + testing::Values(install_static::GOOGLE_CHROME_FOR_TESTING_INDEX), + testing::Values("user"))); #else // BUILDFLAG(GOOGLE_CHROME_BRANDING) // Chromium supports user and system levels. INSTANTIATE_TEST_SUITE_P(
diff --git a/chrome/installer/util/prebuild/create_installer_string_rc.py b/chrome/installer/util/prebuild/create_installer_string_rc.py index 7c642731..9b174616 100755 --- a/chrome/installer/util/prebuild/create_installer_string_rc.py +++ b/chrome/installer/util/prebuild/create_installer_string_rc.py
@@ -50,6 +50,9 @@ 'IDS_APP_SHORTCUTS_SUBDIR_NAME_DEV', 'IDS_APP_SHORTCUTS_SUBDIR_NAME_CANARY', ], + 'google_chrome_for_testing': [ + 'IDS_APP_SHORTCUTS_SUBDIR_NAME', + ], 'chromium': [ 'IDS_APP_SHORTCUTS_SUBDIR_NAME', ], @@ -61,6 +64,9 @@ 'IDS_INBOUND_MDNS_RULE_DESCRIPTION_DEV', 'IDS_INBOUND_MDNS_RULE_DESCRIPTION_CANARY', ], + 'google_chrome_for_testing': [ + 'IDS_INBOUND_MDNS_RULE_DESCRIPTION', + ], 'chromium': [ 'IDS_INBOUND_MDNS_RULE_DESCRIPTION', ], @@ -72,6 +78,9 @@ 'IDS_INBOUND_MDNS_RULE_NAME_DEV', 'IDS_INBOUND_MDNS_RULE_NAME_CANARY', ], + 'google_chrome_for_testing': [ + 'IDS_INBOUND_MDNS_RULE_NAME', + ], 'chromium': [ 'IDS_INBOUND_MDNS_RULE_NAME', ], @@ -87,6 +96,9 @@ 'IDS_SHORTCUT_NAME_DEV', 'IDS_SXS_SHORTCUT_NAME', ], + 'google_chrome_for_testing': [ + 'IDS_PRODUCT_NAME', + ], 'chromium': [ 'IDS_PRODUCT_NAME', ],
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index b00cfbb..f680b4e 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -6392,6 +6392,10 @@ ] } + if (enable_bound_session_credentials) { + sources += [ "../browser/signin/bound_session_credentials/bound_session_cookie_fetcher_unittest.cc" ] + } + if (enable_offline_pages) { sources += [ "../browser/offline_pages/background_loader_offliner_unittest.cc",
diff --git a/chrome/test/data/extensions/api_test/input_method/ime_menu2/background.js b/chrome/test/data/extensions/api_test/input_method/ime_menu2/background.js index 44627a2..24fe763 100644 --- a/chrome/test/data/extensions/api_test/input_method/ime_menu2/background.js +++ b/chrome/test/data/extensions/api_test/input_method/ime_menu2/background.js
@@ -100,24 +100,5 @@ engineID: 'test', items: menuItemsUpdate }); - }, - function testNotifyMenuItems() { - var onMenuItemActivatedCount = 0; - chrome.input.ime.onMenuItemActivated.addListener( - function(engineID, name) { - chrome.test.assertEq('test', engineID); - if (onMenuItemActivatedCount == 0) { - chrome.test.assertEq('menu_a', name); - ++onMenuItemActivatedCount; - } - else { - chrome.test.assertEq('menu_b', name); - chrome.test.sendMessage('get_menu_activated'); - chrome.test.succeed(); - } - } - ); - chrome.inputMethodPrivate.notifyImeMenuItemActivated('test', 'menu_a'); - chrome.inputMethodPrivate.notifyImeMenuItemActivated('test', 'menu_b'); } ]);
diff --git a/chrome/test/data/webapps_integration/file_handler/bar_handler.html b/chrome/test/data/webapps_integration/file_handler/image_handler.html similarity index 100% rename from chrome/test/data/webapps_integration/file_handler/bar_handler.html rename to chrome/test/data/webapps_integration/file_handler/image_handler.html
diff --git a/chrome/test/data/webapps_integration/file_handler/foo_handler.html b/chrome/test/data/webapps_integration/file_handler/text_handler.html similarity index 100% rename from chrome/test/data/webapps_integration/file_handler/foo_handler.html rename to chrome/test/data/webapps_integration/file_handler/text_handler.html
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn index 5f629dc..1935f46 100644 --- a/chrome/test/data/webui/BUILD.gn +++ b/chrome/test/data/webui/BUILD.gn
@@ -230,6 +230,7 @@ "chromeos/crostini_upgrader_browsertest.js", "chromeos/diagnostics/diagnostics_browsertest.js", "chromeos/firmware_update/firmware_update_browsertest.js", + "chromeos/office_fallback/office_fallback_browsertest.js", "chromeos/os_feedback_ui/os_feedback_browsertest.js", "chromeos/scanning/scanning_app_browsertest.js", "chromeos/shimless_rma/shimless_rma_browsertest.js", @@ -599,6 +600,7 @@ "chromeos/ash_common:build_grdp", "chromeos/cloud_upload:build_grdp", "chromeos/manage_mirrorsync:build_grdp", + "chromeos/office_fallback:build_grdp", "chromeos/personalization_app:build_grdp", "chromeos/print_management:build_grdp", "chromeos/shortcut_customization:build_grdp", @@ -611,6 +613,7 @@ grdp_files += [ "$target_gen_dir/chromeos/ash_common/resources.grdp", "$target_gen_dir/chromeos/cloud_upload/resources.grdp", + "$target_gen_dir/chromeos/office_fallback/resources.grdp", "$target_gen_dir/chromeos/personalization_app/resources.grdp", "$target_gen_dir/chromeos/shortcut_customization/resources.grdp", "$target_gen_dir/chromeos/print_management/resources.grdp",
diff --git a/chrome/test/data/webui/app_home/test_app_home_browser_proxy.ts b/chrome/test/data/webui/app_home/test_app_home_browser_proxy.ts index 883b1cbd..4da0133 100644 --- a/chrome/test/data/webui/app_home/test_app_home_browser_proxy.ts +++ b/chrome/test/data/webui/app_home/test_app_home_browser_proxy.ts
@@ -23,6 +23,10 @@ uninstallApp(_appId: string) {} showAppSettings(_appId: string) {} + + createAppShortcut(_appId: string) { + return Promise.resolve(); + } } export class TestAppHomeBrowserProxy implements BrowserProxy {
diff --git a/chrome/test/data/webui/chromeos/cloud_upload/cloud_upload_app_test.ts b/chrome/test/data/webui/chromeos/cloud_upload/cloud_upload_app_test.ts index 9286277..4c4e6d2d 100644 --- a/chrome/test/data/webui/chromeos/cloud_upload/cloud_upload_app_test.ts +++ b/chrome/test/data/webui/chromeos/cloud_upload/cloud_upload_app_test.ts
@@ -216,7 +216,7 @@ await testProxy.handler.whenCalled('respondAndClose'); assertEquals(1, testProxy.handler.getCallCount('respondAndClose')); assertDeepEquals( - [UserAction.kUploadToOneDrive], + [UserAction.kConfirmOrUploadToOneDrive], testProxy.handler.getArgs('respondAndClose')); });
diff --git a/chrome/test/data/webui/chromeos/office_fallback/.gitignore b/chrome/test/data/webui/chromeos/office_fallback/.gitignore new file mode 100644 index 0000000..ec7fda7 --- /dev/null +++ b/chrome/test/data/webui/chromeos/office_fallback/.gitignore
@@ -0,0 +1,2 @@ +# Generated from ash/webui/personalization_app/tools/gen_tsconfig.py +tsconfig.json
diff --git a/chrome/test/data/webui/chromeos/office_fallback/BUILD.gn b/chrome/test/data/webui/chromeos/office_fallback/BUILD.gn new file mode 100644 index 0000000..4cc43e5 --- /dev/null +++ b/chrome/test/data/webui/chromeos/office_fallback/BUILD.gn
@@ -0,0 +1,36 @@ +# Copyright 2022 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//tools/typescript/ts_library.gni") +import("//ui/webui/resources/tools/generate_grd.gni") + +ts_library("build_ts") { + root_dir = "." + out_dir = "$target_gen_dir/tsc" + tsconfig_base = "tsconfig_base.json" + in_files = [ "office_fallback_app_test.ts" ] + path_mappings = [ + "chrome://office-fallback/*|" + + rebase_path( + "$root_gen_dir/ash/webui/common/resources/office_fallback/tsc/*", + target_gen_dir), + "chrome://webui-test/*|" + + rebase_path("$root_gen_dir/chrome/test/data/webui/tsc/*", + target_gen_dir), + ] + deps = [ + "../..:build_ts", + "//ash/webui/common/resources/office_fallback:build_ts", + ] +} + +generate_grd("build_grdp") { + grd_prefix = "webui_chromeos_office_fallback" + out_grd = "$target_gen_dir/resources.grdp" + + deps = [ ":build_ts" ] + manifest_files = + filter_include(get_target_outputs(":build_ts"), [ "*.manifest" ]) + resource_path_prefix = "chromeos/office_fallback" +}
diff --git a/chrome/test/data/webui/chromeos/office_fallback/DIR_METADATA b/chrome/test/data/webui/chromeos/office_fallback/DIR_METADATA new file mode 100644 index 0000000..e9400b87 --- /dev/null +++ b/chrome/test/data/webui/chromeos/office_fallback/DIR_METADATA
@@ -0,0 +1 @@ +mixins: "//ui/file_manager/COMMON_METADATA"
diff --git a/chrome/test/data/webui/chromeos/office_fallback/OWNERS b/chrome/test/data/webui/chromeos/office_fallback/OWNERS new file mode 100644 index 0000000..73220a8 --- /dev/null +++ b/chrome/test/data/webui/chromeos/office_fallback/OWNERS
@@ -0,0 +1 @@ +file://ui/file_manager/OWNERS
diff --git a/chrome/test/data/webui/chromeos/office_fallback/office_fallback_app_test.ts b/chrome/test/data/webui/chromeos/office_fallback/office_fallback_app_test.ts new file mode 100644 index 0000000..64e502a2 --- /dev/null +++ b/chrome/test/data/webui/chromeos/office_fallback/office_fallback_app_test.ts
@@ -0,0 +1,161 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'chrome://office-fallback/office_fallback_dialog.js'; + +import {DialogChoice, PageHandlerRemote} from 'chrome://office-fallback/office_fallback.mojom-webui.js'; +import {OfficeFallbackBrowserProxy} from 'chrome://office-fallback/office_fallback_browser_proxy.js'; +import type {OfficeFallbackElement} from 'chrome://office-fallback/office_fallback_dialog.js'; +import {assertDeepEquals, assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js'; +import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js'; + +interface ProxyOptions { + fileNames?: string[]; + taskTitle: string; + // The string will be converted to enum FallbackReason from + // office_fallback_dialog.ts in the mapping in + // OfficeFallbackElement.stringToFailureReason. + fallbackReason: string; +} + +/** + * A test OfficeFallbackBrowserProxy implementation that enables to mock various + * mojo responses. + */ +class OfficeFallbackTestBrowserProxy implements OfficeFallbackBrowserProxy { + handler: PageHandlerRemote&TestBrowserProxy; + dialogArgs: string; + + constructor(options: ProxyOptions) { + this.handler = TestBrowserProxy.fromClass(PageHandlerRemote); + // Creating JSON string as in OfficeFallbackDialog::GetDialogArgs(). + const args = { + 'fileNames': options.fileNames, + 'fallbackReason': options.fallbackReason, + 'taskTitle': options.taskTitle, + }; + this.dialogArgs = JSON.stringify(args); + } + + // JSON-encoded dialog arguments. + getDialogArguments(): string { + return this.dialogArgs; + } +} + +suite('<office-fallback>', () => { + // Holds the <cloud-upload> app. + let container: HTMLDivElement; + // The <office-fallback> app. + let officeFallbackApp: OfficeFallbackElement; + // The BrowserProxy element to make assertions on when mojo methods are + // called. + let testProxy: OfficeFallbackTestBrowserProxy; + + const setUp = async (options: ProxyOptions) => { + testProxy = new OfficeFallbackTestBrowserProxy(options); + OfficeFallbackBrowserProxy.setInstance(testProxy); + + // Creates and attaches the <office-fallback> element to the DOM tree. + officeFallbackApp = document.createElement('office-fallback'); + container.appendChild(officeFallbackApp); + }; + + /** + * Runs prior to all the tests running, attaches a div to enable isolated + * clearing and attaching of the web component. + */ + suiteSetup(() => { + container = document.createElement('div'); + document.body.appendChild(container); + }); + + + /** + * Runs after each test. Removes all elements from the <div> that holds + * the <cloud-upload> component. + */ + teardown(() => { + container.innerHTML = ''; + testProxy.handler.reset(); + }); + + /** + * Tests that clicking the "quick office" button triggers the right `close` + * mojo request. + */ + test('Open in offline editor button', async () => { + await setUp({ + fileNames: ['file.docx'], + taskTitle: 'testTitle', + fallbackReason: 'Offline', + }); + + officeFallbackApp.$('#quick-office-button').click(); + await testProxy.handler.whenCalled('close'); + assertEquals(1, testProxy.handler.getCallCount('close')); + assertDeepEquals( + [DialogChoice.kQuickOffice], testProxy.handler.getArgs('close')); + }); + + /** + * Tests that clicking the "try again" button triggers the right `close` + * mojo request. + */ + test('Try again button', async () => { + await setUp({ + fileNames: ['file.docx'], + taskTitle: 'testTitle', + fallbackReason: 'Drive Unavailable', + }); + + officeFallbackApp.$('#try-again-button').click(); + await testProxy.handler.whenCalled('close'); + assertEquals(1, testProxy.handler.getCallCount('close')); + assertDeepEquals( + [DialogChoice.kTryAgain], testProxy.handler.getArgs('close')); + }); + + /** + * Tests that clicking the "close" button triggers the right `close` + * mojo request. + */ + test('Close button', async () => { + await setUp({ + fileNames: ['file.docx'], + taskTitle: 'testTitle', + fallbackReason: 'OneDrive Unavailable', + }); + + officeFallbackApp.$('#cancel-button').click(); + await testProxy.handler.whenCalled('close'); + assertEquals(1, testProxy.handler.getCallCount('close')); + assertDeepEquals( + [DialogChoice.kCancel], testProxy.handler.getArgs('close')); + }); + + + /** + * Tests that the fileNames are displayed correctly in the title. + */ + test('fileNames', async () => { + let fileName = `file1.docx`; + const fileNames = [fileName]; + for (let i = 2; i < 12; i++) { + fileName = `file${i}.docx`; + fileNames.push(fileName); + } + + await setUp({ + fileNames: fileNames, + taskTitle: 'testTitle', + fallbackReason: 'Offline', + }); + + const title = officeFallbackApp.$('#title').innerText; + fileNames.forEach((fileName) => { + assertTrue(title.includes(fileName)); + }); + }); +}); \ No newline at end of file
diff --git a/chrome/test/data/webui/chromeos/office_fallback/office_fallback_browsertest.js b/chrome/test/data/webui/chromeos/office_fallback/office_fallback_browsertest.js new file mode 100644 index 0000000..4ddebf9 --- /dev/null +++ b/chrome/test/data/webui/chromeos/office_fallback/office_fallback_browsertest.js
@@ -0,0 +1,26 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview Test suite for chrome://office-fallback. Tests the entire page + * instead of individual components. + */ + +GEN_INCLUDE(['//chrome/test/data/webui/polymer_browser_test_base.js']); + +GEN('#include "ash/constants/ash_features.h"'); +GEN('#include "content/public/test/browser_test.h"'); + +var OfficeFallbackAppBrowserTest = class extends PolymerTest { + get browsePreload() { + return 'chrome://office-fallback/test_loader.html?module=chromeos/' + + 'office_fallback/office_fallback_app_test.js'; + } + + get featureList() { + return {enabled: ['ash::features::kUploadOfficeToCloud']}; + } +}; + +TEST_F('OfficeFallbackAppBrowserTest', 'All', () => mocha.run()); \ No newline at end of file
diff --git a/chrome/test/data/webui/chromeos/office_fallback/tsconfig_base.json b/chrome/test/data/webui/chromeos/office_fallback/tsconfig_base.json new file mode 100644 index 0000000..c11d0a444 --- /dev/null +++ b/chrome/test/data/webui/chromeos/office_fallback/tsconfig_base.json
@@ -0,0 +1,10 @@ +{ + "extends": "../../../../../../tools/typescript/tsconfig_base.json", + "compilerOptions": { + "allowJs": true, + "typeRoots": [ + "../../../../../../third_party/node/node_modules/@types" + ], + "types": ["mocha", "trusted-types"] + } +}
diff --git a/chrome/test/data/webui/settings/review_notification_permissions_test.ts b/chrome/test/data/webui/settings/review_notification_permissions_test.ts index ac767d5..dbbcb52 100644 --- a/chrome/test/data/webui/settings/review_notification_permissions_test.ts +++ b/chrome/test/data/webui/settings/review_notification_permissions_test.ts
@@ -465,9 +465,6 @@ }); /** - * TODO(crbug/1374908): Re-enable the commented parts. This is failing on - * buildbots. - * * Tests whether header string updated based on the notification permission * list size for plural and singular case. */ @@ -480,11 +477,13 @@ assertEquals(2, entries.length); const headerElement = - testElement.shadowRoot!.querySelector('#expandButton h2'); + testElement.shadowRoot!.querySelector('#review-header h2'); assertTrue(headerElement !== null); - // assertEquals( - // 'Review 2 sites that recently sent a lot of notifications', - // headerElement.textContent!.trim()); + + const headerStringTwo = + await PluralStringProxyImpl.getInstance().getPluralString( + 'safetyCheckNotificationPermissionReviewPrimaryLabel', 2); + assertEquals(headerStringTwo, headerElement.textContent!.trim()); // Check header string for singular case. webUIListenerCallback( @@ -497,8 +496,9 @@ entries = getEntries(); assertEquals(1, entries.length); - // assertEquals( - // 'Review 1 site that recently sent a lot of notifications', - // headerElement.textContent!.trim()); + const headerStringOne = + await PluralStringProxyImpl.getInstance().getPluralString( + 'safetyCheckNotificationPermissionReviewPrimaryLabel', 1); + assertEquals(headerStringOne, headerElement.textContent!.trim()); }); });
diff --git a/chrome/test/data/webui/settings/safety_check_permissions_test.ts b/chrome/test/data/webui/settings/safety_check_permissions_test.ts index 9f498f7..3efdd83 100644 --- a/chrome/test/data/webui/settings/safety_check_permissions_test.ts +++ b/chrome/test/data/webui/settings/safety_check_permissions_test.ts
@@ -137,8 +137,7 @@ iconStatus: SafetyCheckIconStatus.NOTIFICATION_PERMISSIONS, label: 'Review <b>2 sites</b> that recently sent a lot of notifications', buttonLabel: 'Review', - buttonAriaLabel: - 'Review 2 sites that recently sent a lot of notifications', + buttonAriaLabel: 'Review notification permissions', }); // User clicks review button. @@ -174,8 +173,7 @@ iconStatus: SafetyCheckIconStatus.NOTIFICATION_PERMISSIONS, label: 'Review <b>1 site</b> that recently sent a lot of notifications', buttonLabel: 'Review', - buttonAriaLabel: - 'Review 1 site that recently sent a lot of notifications', + buttonAriaLabel: 'Review notification permissions', }); // User clicks review button.
diff --git a/chrome/test/webapps/coverage/coverage_linux.tsv b/chrome/test/webapps/coverage/coverage_linux.tsv index 10e9698..564e7282 100644 --- a/chrome/test/webapps/coverage/coverage_linux.tsv +++ b/chrome/test/webapps/coverage/coverage_linux.tsv
@@ -1,5 +1,5 @@ # This is a generated file. -# Full coverage: 66%, with partial coverage: 89% +# Full coverage: 62%, with partial coverage: 85% create_shortcut_Standalone_Windowed🌕 launch_from_menu_option_Standalone🌕 check_app_title_Standalone_StandaloneOriginal🌑 create_shortcut_Standalone_Windowed🌕 launch_from_launch_icon_Standalone🌕 check_app_title_Standalone_StandaloneOriginal🌑 create_shortcut_Standalone_Windowed🌕 launch_from_chrome_apps_Standalone🌓 check_app_title_Standalone_StandaloneOriginal🌑 @@ -1168,136 +1168,136 @@ install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 check_site_handles_file_FileHandler_Foo🌕 check_site_handles_file_FileHandler_Bar🌕 install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 check_site_handles_file_FileHandler_Foo🌕 check_site_handles_file_FileHandler_Bar🌕 install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 check_site_handles_file_FileHandler_Foo🌕 check_site_handles_file_FileHandler_Bar🌕 -create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 -create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 -create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 -create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 -create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 -create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 -create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 -create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 -create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 -create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 -create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 -create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 -create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 -create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 -create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕 launch_file_expect_no_dialog_FileHandler_OneFooFile🌕 check_pwa_window_created_FileHandler_One🌑 -create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕 launch_file_expect_no_dialog_FileHandler_OneFooFile🌕 check_pwa_window_created_FileHandler_One🌑 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕 launch_file_expect_no_dialog_FileHandler_OneFooFile🌕 check_pwa_window_created_FileHandler_One🌑 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕 launch_file_expect_no_dialog_FileHandler_OneFooFile🌕 check_pwa_window_created_FileHandler_One🌑 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕 launch_file_expect_no_dialog_FileHandler_OneFooFile🌕 check_pwa_window_created_FileHandler_One🌑 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕 launch_file_expect_no_dialog_FileHandler_OneFooFile🌕 check_pwa_window_created_FileHandler_One🌑 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕 launch_file_expect_no_dialog_FileHandler_OneFooFile🌕 check_pwa_window_created_FileHandler_One🌑 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕 launch_file_expect_no_dialog_FileHandler_OneFooFile🌕 check_pwa_window_created_FileHandler_One🌑 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕 launch_file_expect_no_dialog_FileHandler_OneFooFile🌕 check_pwa_window_created_FileHandler_One🌑 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕 launch_file_expect_no_dialog_FileHandler_OneFooFile🌕 check_pwa_window_created_FileHandler_One🌑 -create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 check_window_not_created🌕 check_site_handles_file_FileHandler_Foo🌕 check_site_handles_file_FileHandler_Bar🌕 -create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 check_window_not_created🌕 check_site_handles_file_FileHandler_Foo🌕 check_site_handles_file_FileHandler_Bar🌕 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 check_window_not_created🌕 check_site_handles_file_FileHandler_Foo🌕 check_site_handles_file_FileHandler_Bar🌕 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 check_window_not_created🌕 check_site_handles_file_FileHandler_Foo🌕 check_site_handles_file_FileHandler_Bar🌕 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 check_window_not_created🌕 check_site_handles_file_FileHandler_Foo🌕 check_site_handles_file_FileHandler_Bar🌕 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 check_window_not_created🌕 check_site_handles_file_FileHandler_Foo🌕 check_site_handles_file_FileHandler_Bar🌕 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 check_window_not_created🌕 check_site_handles_file_FileHandler_Foo🌕 check_site_handles_file_FileHandler_Bar🌕 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 check_window_not_created🌕 check_site_handles_file_FileHandler_Foo🌕 check_site_handles_file_FileHandler_Bar🌕 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 check_window_not_created🌕 check_site_handles_file_FileHandler_Foo🌕 check_site_handles_file_FileHandler_Bar🌕 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 check_window_not_created🌕 check_site_handles_file_FileHandler_Foo🌕 check_site_handles_file_FileHandler_Bar🌕 -create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕 check_window_not_created🌕 check_site_not_handles_file_FileHandler_Foo🌕 check_site_not_handles_file_FileHandler_Bar🌕 -create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕 check_window_not_created🌕 check_site_not_handles_file_FileHandler_Foo🌕 check_site_not_handles_file_FileHandler_Bar🌕 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕 check_window_not_created🌕 check_site_not_handles_file_FileHandler_Foo🌕 check_site_not_handles_file_FileHandler_Bar🌕 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕 check_window_not_created🌕 check_site_not_handles_file_FileHandler_Foo🌕 check_site_not_handles_file_FileHandler_Bar🌕 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕 check_window_not_created🌕 check_site_not_handles_file_FileHandler_Foo🌕 check_site_not_handles_file_FileHandler_Bar🌕 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕 check_window_not_created🌕 check_site_not_handles_file_FileHandler_Foo🌕 check_site_not_handles_file_FileHandler_Bar🌕 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕 check_window_not_created🌕 check_site_not_handles_file_FileHandler_Foo🌕 check_site_not_handles_file_FileHandler_Bar🌕 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕 check_window_not_created🌕 check_site_not_handles_file_FileHandler_Foo🌕 check_site_not_handles_file_FileHandler_Bar🌕 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕 check_window_not_created🌕 check_site_not_handles_file_FileHandler_Foo🌕 check_site_not_handles_file_FileHandler_Bar🌕 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕 check_window_not_created🌕 check_site_not_handles_file_FileHandler_Foo🌕 check_site_not_handles_file_FileHandler_Bar🌕 +create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 +create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 +create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 +create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 +create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 +create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 +create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 +create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 +create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 +create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 +create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 +create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 +create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 +create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 +create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑 launch_file_expect_no_dialog_FileHandler_OneFooFile🌑 check_pwa_window_created_FileHandler_One🌑 +create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑 launch_file_expect_no_dialog_FileHandler_OneFooFile🌑 check_pwa_window_created_FileHandler_One🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑 launch_file_expect_no_dialog_FileHandler_OneFooFile🌑 check_pwa_window_created_FileHandler_One🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑 launch_file_expect_no_dialog_FileHandler_OneFooFile🌑 check_pwa_window_created_FileHandler_One🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑 launch_file_expect_no_dialog_FileHandler_OneFooFile🌑 check_pwa_window_created_FileHandler_One🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑 launch_file_expect_no_dialog_FileHandler_OneFooFile🌑 check_pwa_window_created_FileHandler_One🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑 launch_file_expect_no_dialog_FileHandler_OneFooFile🌑 check_pwa_window_created_FileHandler_One🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑 launch_file_expect_no_dialog_FileHandler_OneFooFile🌑 check_pwa_window_created_FileHandler_One🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑 launch_file_expect_no_dialog_FileHandler_OneFooFile🌑 check_pwa_window_created_FileHandler_One🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑 launch_file_expect_no_dialog_FileHandler_OneFooFile🌑 check_pwa_window_created_FileHandler_One🌑 +create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 check_window_not_created🌑 check_site_handles_file_FileHandler_Foo🌑 check_site_handles_file_FileHandler_Bar🌑 +create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 check_window_not_created🌑 check_site_handles_file_FileHandler_Foo🌑 check_site_handles_file_FileHandler_Bar🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 check_window_not_created🌑 check_site_handles_file_FileHandler_Foo🌑 check_site_handles_file_FileHandler_Bar🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 check_window_not_created🌑 check_site_handles_file_FileHandler_Foo🌑 check_site_handles_file_FileHandler_Bar🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 check_window_not_created🌑 check_site_handles_file_FileHandler_Foo🌑 check_site_handles_file_FileHandler_Bar🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 check_window_not_created🌑 check_site_handles_file_FileHandler_Foo🌑 check_site_handles_file_FileHandler_Bar🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 check_window_not_created🌑 check_site_handles_file_FileHandler_Foo🌑 check_site_handles_file_FileHandler_Bar🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 check_window_not_created🌑 check_site_handles_file_FileHandler_Foo🌑 check_site_handles_file_FileHandler_Bar🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 check_window_not_created🌑 check_site_handles_file_FileHandler_Foo🌑 check_site_handles_file_FileHandler_Bar🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 check_window_not_created🌑 check_site_handles_file_FileHandler_Foo🌑 check_site_handles_file_FileHandler_Bar🌑 +create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑 check_window_not_created🌑 check_site_not_handles_file_FileHandler_Foo🌑 check_site_not_handles_file_FileHandler_Bar🌑 +create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑 check_window_not_created🌑 check_site_not_handles_file_FileHandler_Foo🌑 check_site_not_handles_file_FileHandler_Bar🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑 check_window_not_created🌑 check_site_not_handles_file_FileHandler_Foo🌑 check_site_not_handles_file_FileHandler_Bar🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑 check_window_not_created🌑 check_site_not_handles_file_FileHandler_Foo🌑 check_site_not_handles_file_FileHandler_Bar🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑 check_window_not_created🌑 check_site_not_handles_file_FileHandler_Foo🌑 check_site_not_handles_file_FileHandler_Bar🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑 check_window_not_created🌑 check_site_not_handles_file_FileHandler_Foo🌑 check_site_not_handles_file_FileHandler_Bar🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑 check_window_not_created🌑 check_site_not_handles_file_FileHandler_Foo🌑 check_site_not_handles_file_FileHandler_Bar🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑 check_window_not_created🌑 check_site_not_handles_file_FileHandler_Foo🌑 check_site_not_handles_file_FileHandler_Bar🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑 check_window_not_created🌑 check_site_not_handles_file_FileHandler_Foo🌑 check_site_not_handles_file_FileHandler_Bar🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑 check_window_not_created🌑 check_site_not_handles_file_FileHandler_Foo🌑 check_site_not_handles_file_FileHandler_Bar🌑 create_shortcut_FileHandler_Windowed🌕 add_file_handling_policy_approval_FileHandler🌑 launch_file_expect_no_dialog_FileHandler_OneFooFile🌑 check_pwa_window_created_FileHandler_One🌑 create_shortcut_FileHandler_Browser🌕 add_file_handling_policy_approval_FileHandler🌑 launch_file_expect_no_dialog_FileHandler_OneFooFile🌑 check_pwa_window_created_FileHandler_One🌑 install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 add_file_handling_policy_approval_FileHandler🌑 launch_file_expect_no_dialog_FileHandler_OneFooFile🌑 check_pwa_window_created_FileHandler_One🌑
diff --git a/chrome/test/webapps/coverage/coverage_win.tsv b/chrome/test/webapps/coverage/coverage_win.tsv index 2e83db7..eb76fe2 100644 --- a/chrome/test/webapps/coverage/coverage_win.tsv +++ b/chrome/test/webapps/coverage/coverage_win.tsv
@@ -1,5 +1,5 @@ # This is a generated file. -# Full coverage: 68%, with partial coverage: 91% +# Full coverage: 63%, with partial coverage: 87% create_shortcut_Standalone_Windowed🌕 launch_from_menu_option_Standalone🌕 check_app_title_Standalone_StandaloneOriginal🌑 create_shortcut_Standalone_Windowed🌕 launch_from_launch_icon_Standalone🌕 check_app_title_Standalone_StandaloneOriginal🌑 create_shortcut_Standalone_Windowed🌕 launch_from_chrome_apps_Standalone🌓 check_app_title_Standalone_StandaloneOriginal🌑 @@ -1168,136 +1168,136 @@ install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 check_site_handles_file_FileHandler_Foo🌕 check_site_handles_file_FileHandler_Bar🌕 install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 check_site_handles_file_FileHandler_Foo🌕 check_site_handles_file_FileHandler_Bar🌕 install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 check_site_handles_file_FileHandler_Foo🌕 check_site_handles_file_FileHandler_Bar🌕 -create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 -create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 -create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 -create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 -create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 -create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 -create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 -create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 -create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 -create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 -create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 -create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 -create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 -create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 -create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕 launch_file_expect_no_dialog_FileHandler_OneFooFile🌕 check_pwa_window_created_FileHandler_One🌑 -create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕 launch_file_expect_no_dialog_FileHandler_OneFooFile🌕 check_pwa_window_created_FileHandler_One🌑 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕 launch_file_expect_no_dialog_FileHandler_OneFooFile🌕 check_pwa_window_created_FileHandler_One🌑 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕 launch_file_expect_no_dialog_FileHandler_OneFooFile🌕 check_pwa_window_created_FileHandler_One🌑 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕 launch_file_expect_no_dialog_FileHandler_OneFooFile🌕 check_pwa_window_created_FileHandler_One🌑 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕 launch_file_expect_no_dialog_FileHandler_OneFooFile🌕 check_pwa_window_created_FileHandler_One🌑 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕 launch_file_expect_no_dialog_FileHandler_OneFooFile🌕 check_pwa_window_created_FileHandler_One🌑 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕 launch_file_expect_no_dialog_FileHandler_OneFooFile🌕 check_pwa_window_created_FileHandler_One🌑 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕 launch_file_expect_no_dialog_FileHandler_OneFooFile🌕 check_pwa_window_created_FileHandler_One🌑 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕 launch_file_expect_no_dialog_FileHandler_OneFooFile🌕 check_pwa_window_created_FileHandler_One🌑 -create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 check_window_not_created🌕 check_site_handles_file_FileHandler_Foo🌕 check_site_handles_file_FileHandler_Bar🌕 -create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 check_window_not_created🌕 check_site_handles_file_FileHandler_Foo🌕 check_site_handles_file_FileHandler_Bar🌕 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 check_window_not_created🌕 check_site_handles_file_FileHandler_Foo🌕 check_site_handles_file_FileHandler_Bar🌕 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 check_window_not_created🌕 check_site_handles_file_FileHandler_Foo🌕 check_site_handles_file_FileHandler_Bar🌕 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 check_window_not_created🌕 check_site_handles_file_FileHandler_Foo🌕 check_site_handles_file_FileHandler_Bar🌕 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 check_window_not_created🌕 check_site_handles_file_FileHandler_Foo🌕 check_site_handles_file_FileHandler_Bar🌕 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 check_window_not_created🌕 check_site_handles_file_FileHandler_Foo🌕 check_site_handles_file_FileHandler_Bar🌕 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 check_window_not_created🌕 check_site_handles_file_FileHandler_Foo🌕 check_site_handles_file_FileHandler_Bar🌕 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 check_window_not_created🌕 check_site_handles_file_FileHandler_Foo🌕 check_site_handles_file_FileHandler_Bar🌕 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 check_window_not_created🌕 check_site_handles_file_FileHandler_Foo🌕 check_site_handles_file_FileHandler_Bar🌕 -create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕 -create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕 check_window_not_created🌕 check_site_not_handles_file_FileHandler_Foo🌕 check_site_not_handles_file_FileHandler_Bar🌕 -create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕 check_window_not_created🌕 check_site_not_handles_file_FileHandler_Foo🌕 check_site_not_handles_file_FileHandler_Bar🌕 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕 check_window_not_created🌕 check_site_not_handles_file_FileHandler_Foo🌕 check_site_not_handles_file_FileHandler_Bar🌕 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕 check_window_not_created🌕 check_site_not_handles_file_FileHandler_Foo🌕 check_site_not_handles_file_FileHandler_Bar🌕 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕 check_window_not_created🌕 check_site_not_handles_file_FileHandler_Foo🌕 check_site_not_handles_file_FileHandler_Bar🌕 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕 check_window_not_created🌕 check_site_not_handles_file_FileHandler_Foo🌕 check_site_not_handles_file_FileHandler_Bar🌕 -install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕 check_window_not_created🌕 check_site_not_handles_file_FileHandler_Foo🌕 check_site_not_handles_file_FileHandler_Bar🌕 -install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕 check_window_not_created🌕 check_site_not_handles_file_FileHandler_Foo🌕 check_site_not_handles_file_FileHandler_Bar🌕 -install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕 check_window_not_created🌕 check_site_not_handles_file_FileHandler_Foo🌕 check_site_not_handles_file_FileHandler_Bar🌕 -install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕 check_window_not_created🌕 check_site_not_handles_file_FileHandler_Foo🌕 check_site_not_handles_file_FileHandler_Bar🌕 +create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 +create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneFooFile🌑 +create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 +create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 +create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 +create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑 +create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 +create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 +create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 +create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_One🌑 check_files_loaded_in_site_FileHandler_OneBarFile🌑 +create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 +create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 +create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 +create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑 check_pwa_window_created_FileHandler_Two🌑 check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑 +create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑 launch_file_expect_no_dialog_FileHandler_OneFooFile🌑 check_pwa_window_created_FileHandler_One🌑 +create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑 launch_file_expect_no_dialog_FileHandler_OneFooFile🌑 check_pwa_window_created_FileHandler_One🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑 launch_file_expect_no_dialog_FileHandler_OneFooFile🌑 check_pwa_window_created_FileHandler_One🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑 launch_file_expect_no_dialog_FileHandler_OneFooFile🌑 check_pwa_window_created_FileHandler_One🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑 launch_file_expect_no_dialog_FileHandler_OneFooFile🌑 check_pwa_window_created_FileHandler_One🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑 launch_file_expect_no_dialog_FileHandler_OneFooFile🌑 check_pwa_window_created_FileHandler_One🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑 launch_file_expect_no_dialog_FileHandler_OneFooFile🌑 check_pwa_window_created_FileHandler_One🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑 launch_file_expect_no_dialog_FileHandler_OneFooFile🌑 check_pwa_window_created_FileHandler_One🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑 launch_file_expect_no_dialog_FileHandler_OneFooFile🌑 check_pwa_window_created_FileHandler_One🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑 launch_file_expect_no_dialog_FileHandler_OneFooFile🌑 check_pwa_window_created_FileHandler_One🌑 +create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 check_window_not_created🌑 check_site_handles_file_FileHandler_Foo🌑 check_site_handles_file_FileHandler_Bar🌑 +create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 check_window_not_created🌑 check_site_handles_file_FileHandler_Foo🌑 check_site_handles_file_FileHandler_Bar🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 check_window_not_created🌑 check_site_handles_file_FileHandler_Foo🌑 check_site_handles_file_FileHandler_Bar🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 check_window_not_created🌑 check_site_handles_file_FileHandler_Foo🌑 check_site_handles_file_FileHandler_Bar🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 check_window_not_created🌑 check_site_handles_file_FileHandler_Foo🌑 check_site_handles_file_FileHandler_Bar🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 check_window_not_created🌑 check_site_handles_file_FileHandler_Foo🌑 check_site_handles_file_FileHandler_Bar🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 check_window_not_created🌑 check_site_handles_file_FileHandler_Foo🌑 check_site_handles_file_FileHandler_Bar🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 check_window_not_created🌑 check_site_handles_file_FileHandler_Foo🌑 check_site_handles_file_FileHandler_Bar🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 check_window_not_created🌑 check_site_handles_file_FileHandler_Foo🌑 check_site_handles_file_FileHandler_Bar🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 check_window_not_created🌑 check_site_handles_file_FileHandler_Foo🌑 check_site_handles_file_FileHandler_Bar🌑 +create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑 launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑 +create_shortcut_FileHandler_Windowed🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑 check_window_not_created🌑 check_site_not_handles_file_FileHandler_Foo🌑 check_site_not_handles_file_FileHandler_Bar🌑 +create_shortcut_FileHandler_Browser🌕 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑 check_window_not_created🌑 check_site_not_handles_file_FileHandler_Foo🌑 check_site_not_handles_file_FileHandler_Bar🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑 check_window_not_created🌑 check_site_not_handles_file_FileHandler_Foo🌑 check_site_not_handles_file_FileHandler_Bar🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑 check_window_not_created🌑 check_site_not_handles_file_FileHandler_Foo🌑 check_site_not_handles_file_FileHandler_Bar🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑 check_window_not_created🌑 check_site_not_handles_file_FileHandler_Foo🌑 check_site_not_handles_file_FileHandler_Bar🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑 check_window_not_created🌑 check_site_not_handles_file_FileHandler_Foo🌑 check_site_not_handles_file_FileHandler_Bar🌑 +install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑 check_window_not_created🌑 check_site_not_handles_file_FileHandler_Foo🌑 check_site_not_handles_file_FileHandler_Bar🌑 +install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑 check_window_not_created🌑 check_site_not_handles_file_FileHandler_Foo🌑 check_site_not_handles_file_FileHandler_Bar🌑 +install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑 check_window_not_created🌑 check_site_not_handles_file_FileHandler_Foo🌑 check_site_not_handles_file_FileHandler_Bar🌑 +install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓 launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑 check_window_not_created🌑 check_site_not_handles_file_FileHandler_Foo🌑 check_site_not_handles_file_FileHandler_Bar🌑 create_shortcut_FileHandler_Windowed🌕 add_file_handling_policy_approval_FileHandler🌑 launch_file_expect_no_dialog_FileHandler_OneFooFile🌑 check_pwa_window_created_FileHandler_One🌑 create_shortcut_FileHandler_Browser🌕 add_file_handling_policy_approval_FileHandler🌑 launch_file_expect_no_dialog_FileHandler_OneFooFile🌑 check_pwa_window_created_FileHandler_One🌑 install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓 add_file_handling_policy_approval_FileHandler🌑 launch_file_expect_no_dialog_FileHandler_OneFooFile🌑 check_pwa_window_created_FileHandler_One🌑
diff --git a/chrome/test/webapps/data/framework_supported_actions.csv b/chrome/test/webapps/data/framework_supported_actions.csv index f410897c..f35e27e9 100644 --- a/chrome/test/webapps/data/framework_supported_actions.csv +++ b/chrome/test/webapps/data/framework_supported_actions.csv
@@ -37,8 +37,6 @@ install_menu_option, 🌕, 🌕, 🌕, 🌕, install_omnibox_icon, 🌕, 🌕, 🌕, 🌕, install_policy_app, 🌓, 🌓, 🌓, 🌓, -launch_file_expect_dialog, 🌑, 🌕, 🌕, 🌑, -launch_file_expect_no_dialog, 🌑, 🌕, 🌕, 🌑, launch_from_chrome_apps, 🌓, 🌓, 🌓, 🌓, launch_from_launch_icon, 🌕, 🌕, 🌕, 🌕, launch_from_menu_option, 🌕, 🌕, 🌕, 🌕,
diff --git a/chrome/updater/BUILD.gn b/chrome/updater/BUILD.gn index bcc2580..59c8d37 100644 --- a/chrome/updater/BUILD.gn +++ b/chrome/updater/BUILD.gn
@@ -753,6 +753,7 @@ ] data += [ + "test/data/ProcmonConfiguration.pmc", "test/data/signed.exe.gz", "test/data/tagged_encode_utf8.exe", "test/data/tagged_magic_utf16.exe",
diff --git a/chrome/updater/test/data/ProcmonConfiguration.pmc b/chrome/updater/test/data/ProcmonConfiguration.pmc new file mode 100644 index 0000000..9cda674 --- /dev/null +++ b/chrome/updater/test/data/ProcmonConfiguration.pmc Binary files differ
diff --git a/chrome/updater/unittest_util.cc b/chrome/updater/unittest_util.cc index fd80c9da..3c24d065 100644 --- a/chrome/updater/unittest_util.cc +++ b/chrome/updater/unittest_util.cc
@@ -174,6 +174,15 @@ return {}; } + base::FilePath source_path; + CHECK(base::PathService::Get(base::DIR_SOURCE_ROOT, &source_path)); + const base::FilePath pmc_path(source_path.Append(L"chrome") + .Append(L"updater") + .Append(L"test") + .Append(L"data") + .Append(L"ProcmonConfiguration.pmc")); + CHECK(base::PathExists(pmc_path)); + base::Time::Exploded start_time; base::Time::Now().LocalExplode(&start_time); const base::FilePath pml_file(dest_dir.Append(base::StringPrintf( @@ -181,9 +190,9 @@ start_time.day_of_month, start_time.hour, start_time.minute, start_time.second))); - const std::wstring& cmdline = - base::StrCat({kProcmonPath, L" /AcceptEula /BackingFile \"", - pml_file.value(), L"\" /Nofilter /Quiet /externalcapture"}); + const std::wstring& cmdline = base::StrCat( + {kProcmonPath, L" /AcceptEula /LoadConfig \"", pmc_path.value(), + L"\" /BackingFile \"", pml_file.value(), L"\" /Quiet /externalcapture"}); base::LaunchOptions options; options.start_hidden = true; VLOG(1) << __func__ << ": running: " << cmdline;
diff --git a/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.cc b/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.cc index dca9e22..374c909 100644 --- a/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.cc +++ b/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.cc
@@ -1612,6 +1612,13 @@ ReturnProtobufMethodCallback(reply, std::move(callback)); } +void FakeUserDataAuthClient::GetAuthFactorExtendedInfo( + const ::user_data_auth::GetAuthFactorExtendedInfoRequest& request, + GetAuthFactorExtendedInfoCallback callback) { + ::user_data_auth::GetAuthFactorExtendedInfoReply reply; + ReplyOnReturn auto_reply(&reply, std::move(callback)); +} + void FakeUserDataAuthClient::GetRecoveryRequest( const ::user_data_auth::GetRecoveryRequestRequest& request, GetRecoveryRequestCallback callback) {
diff --git a/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h b/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h index 86acd8d9..7c15503f 100644 --- a/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h +++ b/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h
@@ -259,6 +259,9 @@ RemoveAuthFactorCallback callback) override; void ListAuthFactors(const ::user_data_auth::ListAuthFactorsRequest& request, ListAuthFactorsCallback callback) override; + void GetAuthFactorExtendedInfo( + const ::user_data_auth::GetAuthFactorExtendedInfoRequest& request, + GetAuthFactorExtendedInfoCallback callback) override; void GetRecoveryRequest( const ::user_data_auth::GetRecoveryRequestRequest& request, GetRecoveryRequestCallback callback) override;
diff --git a/chromeos/ash/components/dbus/userdataauth/mock_userdataauth_client.h b/chromeos/ash/components/dbus/userdataauth/mock_userdataauth_client.h index b5f2035..06865ef 100644 --- a/chromeos/ash/components/dbus/userdataauth/mock_userdataauth_client.h +++ b/chromeos/ash/components/dbus/userdataauth/mock_userdataauth_client.h
@@ -183,6 +183,12 @@ (const ::user_data_auth::ListAuthFactorsRequest& request, ListAuthFactorsCallback callback), (override)); + MOCK_METHOD( + void, + GetAuthFactorExtendedInfo, + (const ::user_data_auth::GetAuthFactorExtendedInfoRequest& request, + GetAuthFactorExtendedInfoCallback callback), + (override)); MOCK_METHOD(void, RemoveAuthFactor, (const ::user_data_auth::RemoveAuthFactorRequest& request,
diff --git a/chromeos/ash/components/dbus/userdataauth/userdataauth_client.cc b/chromeos/ash/components/dbus/userdataauth/userdataauth_client.cc index 01119fea..71dad6d 100644 --- a/chromeos/ash/components/dbus/userdataauth/userdataauth_client.cc +++ b/chromeos/ash/components/dbus/userdataauth/userdataauth_client.cc
@@ -346,6 +346,14 @@ std::move(callback)); } + void GetAuthFactorExtendedInfo( + const ::user_data_auth::GetAuthFactorExtendedInfoRequest& request, + GetAuthFactorExtendedInfoCallback callback) override { + CallProtoMethod(::user_data_auth::kGetAuthFactorExtendedInfo, + ::user_data_auth::kUserDataAuthInterface, request, + std::move(callback)); + } + void GetRecoveryRequest( const ::user_data_auth::GetRecoveryRequestRequest& request, GetRecoveryRequestCallback callback) override {
diff --git a/chromeos/ash/components/dbus/userdataauth/userdataauth_client.h b/chromeos/ash/components/dbus/userdataauth/userdataauth_client.h index 5283805..d1ea1ed0 100644 --- a/chromeos/ash/components/dbus/userdataauth/userdataauth_client.h +++ b/chromeos/ash/components/dbus/userdataauth/userdataauth_client.h
@@ -116,6 +116,8 @@ chromeos::DBusMethodCallback<::user_data_auth::RemoveAuthFactorReply>; using ListAuthFactorsCallback = chromeos::DBusMethodCallback<::user_data_auth::ListAuthFactorsReply>; + using GetAuthFactorExtendedInfoCallback = chromeos::DBusMethodCallback< + ::user_data_auth::GetAuthFactorExtendedInfoReply>; using GetRecoveryRequestCallback = chromeos::DBusMethodCallback<::user_data_auth::GetRecoveryRequestReply>; using GetAuthSessionStatusCallback = @@ -333,6 +335,12 @@ const ::user_data_auth::ListAuthFactorsRequest& request, ListAuthFactorsCallback callback) = 0; + // This is called to get AuthFactor for given label along with optional + // extended info. + virtual void GetAuthFactorExtendedInfo( + const ::user_data_auth::GetAuthFactorExtendedInfoRequest& request, + GetAuthFactorExtendedInfoCallback callback) = 0; + // This is called when a user authenticates with recovery to obtain the // request to be sent to the recovery service. virtual void GetRecoveryRequest(
diff --git a/chromeos/ash/services/ime/public/mojom/input_method.mojom b/chromeos/ash/services/ime/public/mojom/input_method.mojom index 650e30e..6eab2c8 100644 --- a/chromeos/ash/services/ime/public/mojom/input_method.mojom +++ b/chromeos/ash/services/ime/public/mojom/input_method.mojom
@@ -6,7 +6,7 @@ // the Chromium repo. This file should be updated first, before syncing in the // other repos. -// Next MinVersion: 14 +// Next MinVersion: 15 module ash.ime.mojom; @@ -264,12 +264,13 @@ // TODO(crbug.com/1261313): Note that this type must be marked [Extensible] in // all deployed versions before new ordinals can be introduced, and [Extensible] // requires specifying a [Default] field. -[Stable, RenamedFrom="chromeos.ime.mojom.InputMethodSettings"] +[Stable, Extensible, RenamedFrom="chromeos.ime.mojom.InputMethodSettings"] union InputMethodSettings { KoreanSettings korean_settings@0; LatinSettings latin_settings@1; PinyinSettings pinyin_settings@2; ZhuyinSettings zhuyin_settings@3; + [MinVersion=14, Default] bool null_settings@4; }; // Next ordinal: 9
diff --git a/chromeos/ash/services/ime/public/mojom/japanese_settings.mojom b/chromeos/ash/services/ime/public/mojom/japanese_settings.mojom index 5dc2ab9..db7ee54 100644 --- a/chromeos/ash/services/ime/public/mojom/japanese_settings.mojom +++ b/chromeos/ash/services/ime/public/mojom/japanese_settings.mojom
@@ -6,7 +6,7 @@ // the Chromium repo. This file should be updated first, before syncing in the // other repos. -// Next MinVersion: 2 +// Next MinVersion: 3 module ash.ime.mojom; @@ -58,7 +58,8 @@ kMsIme = 2, kKotoeri = 3, kMobile = 4, - kChromeOs = 5 + kChromeOs = 5, + [MinVersion=2] kNone = 6 }; [Stable, Extensible]
diff --git a/chromeos/tast_control.gni b/chromeos/tast_control.gni index 2b1ba6c2..b8cc769 100644 --- a/chromeos/tast_control.gni +++ b/chromeos/tast_control.gni
@@ -240,6 +240,10 @@ "dlp.DataLeakPreventionRulesListScreenshot.ash_allowed", "dlp.DataLeakPreventionRulesListScreenshot.ash_blocked", + # https://crbug.com/1364721 + "inputs.VirtualKeyboardHandwriting.docked", + "inputs.VirtualKeyboardHandwriting.floating", + # https://crbug.com/1365284 "crostini.RestartApp.clamshell_stable",
diff --git a/chromeos/ui/base/BUILD.gn b/chromeos/ui/base/BUILD.gn index 44e094b1..afe739d 100644 --- a/chromeos/ui/base/BUILD.gn +++ b/chromeos/ui/base/BUILD.gn
@@ -42,6 +42,10 @@ "//ui/gfx", "//ui/gfx/geometry", ] + + if (is_chromeos_lacros) { + deps += [ "//chromeos/startup" ] + } } source_set("unit_tests") {
diff --git a/chromeos/ui/base/tablet_state.cc b/chromeos/ui/base/tablet_state.cc index 70f7fb4f..408e3d0 100644 --- a/chromeos/ui/base/tablet_state.cc +++ b/chromeos/ui/base/tablet_state.cc
@@ -5,10 +5,10 @@ #include "chromeos/ui/base/tablet_state.h" #include "base/check_op.h" -#include "build/chromeos_buildflags.h" #include "ui/display/screen.h" #if BUILDFLAG(IS_CHROMEOS_LACROS) +#include "chromeos/startup/browser_params_proxy.h" #include "ui/base/pointer/touch_ui_controller.h" #include "ui/display/screen.h" #endif @@ -61,4 +61,16 @@ #endif } +#if BUILDFLAG(IS_CHROMEOS_LACROS) +void TabletState::EnableTabletModeForTesting(bool enable) { + // Do not use this method in case where crosapi is enabled since it implies + // Ash server is available. + DCHECK(chromeos::BrowserParamsProxy::Get() + ->DisableCrosapiForTesting()); // IN-TEST + display::Screen::GetScreen()->OverrideTabletStateForTesting( // IN-TEST + enable ? display::TabletState::kInTabletMode + : display::TabletState::kInClamshellMode); +} +#endif + } // namespace chromeos
diff --git a/chromeos/ui/base/tablet_state.h b/chromeos/ui/base/tablet_state.h index 6ef5123..6e25ec20 100644 --- a/chromeos/ui/base/tablet_state.h +++ b/chromeos/ui/base/tablet_state.h
@@ -6,6 +6,7 @@ #define CHROMEOS_UI_BASE_TABLET_STATE_H_ #include "base/component_export.h" +#include "build/chromeos_buildflags.h" #include "ui/display/display_observer.h" #include "ui/display/tablet_state.h" @@ -34,6 +35,17 @@ // display::DisplayObserver: void OnDisplayTabletStateChanged(display::TabletState state) override; +#if BUILDFLAG(IS_CHROMEOS_LACROS) + // Enables/disables tablet mode on client side. Not thet this does not modify + // server side tablet state. + // + // DO NOT use this for integration tests such as browser tests. Use this only + // on unit-testing. + // Use TestController crosapi EnterTabletMode/ExitTabletMode if Ash server is + // available since the test may depend on server side behavior. + void EnableTabletModeForTesting(bool enable); +#endif + private: display::ScopedDisplayObserver display_observer_{this};
diff --git a/chromeos/ui/frame/non_client_frame_view_base.cc b/chromeos/ui/frame/non_client_frame_view_base.cc index 5bec3046..2d66b2a 100644 --- a/chromeos/ui/frame/non_client_frame_view_base.cc +++ b/chromeos/ui/frame/non_client_frame_view_base.cc
@@ -4,6 +4,7 @@ #include "chromeos/ui/frame/non_client_frame_view_base.h" +#include "chromeos/ui/base/tablet_state.h" #include "chromeos/ui/base/window_properties.h" #include "chromeos/ui/frame/default_frame_header.h" #include "chromeos/ui/frame/frame_utils.h" @@ -80,9 +81,12 @@ int NonClientFrameViewBase::NonClientTopBorderHeight() const { // The frame should not occupy the window area when it's in fullscreen, - // not visible or disabled. + // not visible, disabled, in immersive mode or in tablet mode. + // TODO(crbug.com/1385920): Support NonClientFrameViewAshImmersiveHelper on + // Lacros so that we can remove InTabletMode() && IsMaximized() condition. if (frame_->IsFullscreen() || !GetFrameEnabled() || - header_view_->in_immersive_mode()) { + header_view_->in_immersive_mode() || + (chromeos::TabletState::Get()->InTabletMode() && frame_->IsMaximized())) { return 0; } return header_view_->GetPreferredHeight();
diff --git a/components/autofill/core/browser/form_parsing/credit_card_field.cc b/components/autofill/core/browser/form_parsing/credit_card_field.cc index 4a82ddf..dcb7fbf9 100644 --- a/components/autofill/core/browser/form_parsing/credit_card_field.cc +++ b/components/autofill/core/browser/form_parsing/credit_card_field.cc
@@ -20,6 +20,7 @@ #include "components/autofill/core/browser/form_parsing/autofill_scanner.h" #include "components/autofill/core/browser/form_parsing/form_field.h" #include "components/autofill/core/browser/form_parsing/regex_patterns.h" +#include "components/autofill/core/browser/logging/log_manager.h" #include "components/autofill/core/common/autofill_clock.h" #include "components/autofill/core/common/autofill_features.h" #include "components/autofill/core/common/autofill_regex_constants.h"
diff --git a/components/autofill/core/browser/touch_to_fill_delegate_impl.cc b/components/autofill/core/browser/touch_to_fill_delegate_impl.cc index 1853ac4..ebdf2133 100644 --- a/components/autofill/core/browser/touch_to_fill_delegate_impl.cc +++ b/components/autofill/core/browser/touch_to_fill_delegate_impl.cc
@@ -7,6 +7,7 @@ #include "components/autofill/core/browser/autofill_browser_util.h" #include "components/autofill/core/browser/autofill_driver.h" #include "components/autofill/core/browser/browser_autofill_manager.h" +#include "components/autofill/core/browser/data_model/credit_card.h" #include "components/autofill/core/common/autofill_clock.h" #include "components/autofill/core/common/autofill_util.h" @@ -27,6 +28,12 @@ bool TouchToFillDelegateImpl::TryToShowTouchToFill(int query_id, const FormData& form, const FormFieldData& field) { + // TODO(crbug.com/1386143): store only FormGlobalId and FieldGlobalId instead + // to avoid that FormData and FormFieldData may become obsolete during the + // bottomsheet being open. + query_id_ = query_id; + query_form_ = form; + query_field_ = field; // Trigger only for a credit card field/form. // TODO(crbug.com/1247698): Clarify field/form requirements. if (manager_->GetPopupType(form, field) != PopupType::kCreditCards) @@ -91,6 +98,24 @@ return manager_->driver(); } +bool TouchToFillDelegateImpl::ShouldShowScanCreditCard() { + if (!manager_->client()->HasCreditCardScanFeature()) + return false; + + return !IsFormOrClientNonSecure(manager_->client(), query_form_); +} + +void TouchToFillDelegateImpl::ScanCreditCard() { + manager_->client()->ScanCreditCard(base::BindOnce( + &TouchToFillDelegateImpl::OnCreditCardScanned, GetWeakPtr())); +} + +void TouchToFillDelegateImpl::OnCreditCardScanned(const CreditCard& card) { + HideTouchToFill(); + manager_->FillCreditCardFormImpl(query_form_, query_field_, card, + std::u16string(), query_id_); +} + base::WeakPtr<TouchToFillDelegateImpl> TouchToFillDelegateImpl::GetWeakPtr() { return weak_ptr_factory_.GetWeakPtr(); }
diff --git a/components/autofill/core/browser/touch_to_fill_delegate_impl.h b/components/autofill/core/browser/touch_to_fill_delegate_impl.h index f355df3..8063106 100644 --- a/components/autofill/core/browser/touch_to_fill_delegate_impl.h +++ b/components/autofill/core/browser/touch_to_fill_delegate_impl.h
@@ -6,6 +6,7 @@ #define COMPONENTS_AUTOFILL_CORE_BROWSER_TOUCH_TO_FILL_DELEGATE_IMPL_H_ #include "base/memory/weak_ptr.h" +#include "components/autofill/core/browser/data_model/credit_card.h" #include "components/autofill/core/browser/ui/touch_to_fill_delegate.h" #include "components/autofill/core/common/form_data.h" #include "components/autofill/core/common/form_field_data.h" @@ -51,6 +52,9 @@ // TouchToFillDelegate: AutofillDriver* GetDriver() override; + bool ShouldShowScanCreditCard() override; + void ScanCreditCard() override; + void OnCreditCardScanned(const CreditCard& card) override; private: base::WeakPtr<TouchToFillDelegateImpl> GetWeakPtr(); @@ -64,6 +68,9 @@ TouchToFillState ttf_credit_card_state_ = TouchToFillState::kShouldShow; const raw_ptr<BrowserAutofillManager> manager_; + int query_id_; + FormData query_form_; + FormFieldData query_field_; base::WeakPtrFactory<TouchToFillDelegateImpl> weak_ptr_factory_{this}; };
diff --git a/components/autofill/core/browser/touch_to_fill_delegate_impl_unittest.cc b/components/autofill/core/browser/touch_to_fill_delegate_impl_unittest.cc index 0aa3af6..6a99a6bc 100644 --- a/components/autofill/core/browser/touch_to_fill_delegate_impl_unittest.cc +++ b/components/autofill/core/browser/touch_to_fill_delegate_impl_unittest.cc
@@ -44,6 +44,10 @@ MockAutofillClient& operator=(const MockAutofillClient&) = delete; ~MockAutofillClient() override = default; + MOCK_METHOD(void, + ScanCreditCard, + (CreditCardScanCallback callback), + (override)); MOCK_METHOD(bool, IsTouchToFillCreditCardSupported, (), (override)); MOCK_METHOD(bool, ShowTouchToFillCreditCard, @@ -84,6 +88,14 @@ GetPopupType, (const FormData& form, const FormFieldData& field), (override)); + MOCK_METHOD(void, + FillCreditCardFormImpl, + (const FormData& form, + const FormFieldData& field, + const CreditCard& credit_card, + const std::u16string& cvc, + int query_id), + (override)); }; } // namespace @@ -361,4 +373,14 @@ browser_autofill_manager_.reset(); } +TEST_F(TouchToFillDelegateImplUnitTest, ScanCreditCardIsCalled) { + TryToShowTouchToFill(/*expected_success=*/true); + EXPECT_CALL(autofill_client_, ScanCreditCard); + touch_to_fill_delegate_->ScanCreditCard(); + + CreditCard credit_card = autofill::test::GetCreditCard(); + EXPECT_CALL(*browser_autofill_manager_, FillCreditCardFormImpl); + touch_to_fill_delegate_->OnCreditCardScanned(credit_card); +} + } // namespace autofill
diff --git a/components/autofill/core/browser/ui/touch_to_fill_delegate.h b/components/autofill/core/browser/ui/touch_to_fill_delegate.h index 05bfd02..9e71e2a 100644 --- a/components/autofill/core/browser/ui/touch_to_fill_delegate.h +++ b/components/autofill/core/browser/ui/touch_to_fill_delegate.h
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "components/autofill/core/browser/data_model/credit_card.h" + #ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_UI_TOUCH_TO_FILL_DELEGATE_H_ #define COMPONENTS_AUTOFILL_CORE_BROWSER_UI_TOUCH_TO_FILL_DELEGATE_H_ @@ -14,10 +16,14 @@ // data to show and will be notified of events by the controller. class TouchToFillDelegate { public: + virtual ~TouchToFillDelegate() = default; + // TODO(crbug.com/1247698): Define the API. virtual AutofillDriver* GetDriver() = 0; - virtual ~TouchToFillDelegate() = default; + virtual bool ShouldShowScanCreditCard() = 0; + virtual void ScanCreditCard() = 0; + virtual void OnCreditCardScanned(const CreditCard& card) = 0; }; } // namespace autofill
diff --git a/components/content_settings/core/browser/BUILD.gn b/components/content_settings/core/browser/BUILD.gn index 5ee4720..815fabf 100644 --- a/components/content_settings/core/browser/BUILD.gn +++ b/components/content_settings/core/browser/BUILD.gn
@@ -61,10 +61,6 @@ "//url", ] - if (is_android) { - deps += [ "//media" ] - } - if (!is_ios) { sources += [ "cookie_settings_policy_handler.cc",
diff --git a/components/content_settings/core/browser/DEPS b/components/content_settings/core/browser/DEPS index d24d478..ad2435f 100644 --- a/components/content_settings/core/browser/DEPS +++ b/components/content_settings/core/browser/DEPS
@@ -8,7 +8,6 @@ "+components/sync_preferences", "+components/url_formatter", "+extensions/buildflags", - "+media/base/android", "+net/base", "+net/cookies", "+ppapi/buildflags",
diff --git a/components/content_settings/core/browser/content_settings_pref.cc b/components/content_settings/core/browser/content_settings_pref.cc index bcb3e1f..38669575 100644 --- a/components/content_settings/core/browser/content_settings_pref.cc +++ b/components/content_settings/core/browser/content_settings_pref.cc
@@ -383,7 +383,7 @@ if (!found && !value.is_none()) { settings_dictionary = pattern_pairs_settings->SetDictionaryWithoutPathExpansion( - pattern_str, std::make_unique<base::DictionaryValue>()); + pattern_str, base::Value::Dict()); } if (settings_dictionary) {
diff --git a/components/content_settings/core/browser/content_settings_registry.cc b/components/content_settings/core/browser/content_settings_registry.cc index d9ca68a..f3a629d 100644 --- a/components/content_settings/core/browser/content_settings_registry.cc +++ b/components/content_settings/core/browser/content_settings_registry.cc
@@ -16,10 +16,6 @@ #include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/features.h" -#if BUILDFLAG(IS_ANDROID) -#include "media/base/android/media_drm_bridge.h" -#endif - namespace content_settings { namespace {
diff --git a/components/crash/core/browser/resources/BUILD.gn b/components/crash/core/browser/resources/BUILD.gn new file mode 100644 index 0000000..e9a4d26 --- /dev/null +++ b/components/crash/core/browser/resources/BUILD.gn
@@ -0,0 +1,21 @@ +# Copyright 2022 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//tools/grit/preprocess_if_expr.gni") +import("//tools/typescript/ts_library.gni") + +preprocess_if_expr("preprocess") { + in_folder = "." + out_folder = target_gen_dir + in_files = [ "crashes.ts" ] +} + +ts_library("build_ts") { + root_dir = target_gen_dir + out_dir = "$target_gen_dir/tsc" + in_files = [ "crashes.ts" ] + definitions = [ "//tools/typescript/definitions/chrome_send.d.ts" ] + deps = [ "//ui/webui/resources:library" ] + extra_deps = [ ":preprocess" ] +}
diff --git a/components/crash/core/browser/resources/crashes.js b/components/crash/core/browser/resources/crashes.js deleted file mode 100644 index ab7a89c..0000000 --- a/components/crash/core/browser/resources/crashes.js +++ /dev/null
@@ -1,221 +0,0 @@ -// Copyright 2012 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// <if expr="is_ios"> -import 'chrome://resources/js/ios/web_ui.js'; -// </if> - -import 'chrome://resources/js/action_link.js'; -import './strings.m.js'; - -import {addWebUiListener} from 'chrome://resources/js/cr.js'; -import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; -import {$, appendParam} from 'chrome://resources/js/util.js'; - -/* Id for tracking automatic refresh of crash list. */ -let refreshCrashListId = undefined; - -/** - * Requests the list of crashes from the backend. - */ -function requestCrashes() { - chrome.send('requestCrashList'); -} - -/** - * Callback from backend with the list of crashes. Builds the UI. - * @param {!{enabled: boolean, - * dynamicBackend: boolean, - * manualUploads: boolean, - * crashes: !Array, - * version: string, - * os: string, - * isGoogleAccount: boolean, - * }} result - */ -function updateCrashList({ - enabled, - dynamicBackend, - manualUploads, - crashes, - version, - os, - isGoogleAccount, -}) { - $('crashesCount').textContent = loadTimeData.getStringF( - 'crashCountFormat', crashes.length.toLocaleString()); - - const crashList = $('crashList'); - - $('disabledMode').hidden = enabled; - $('crashUploadStatus').hidden = !enabled || !dynamicBackend; - - const template = crashList.getElementsByTagName('template')[0]; - - // Clear any previous list. - crashList.querySelectorAll('.crash-row').forEach((elm) => elm.remove()); - - const productName = loadTimeData.getString('shortProductName'); - - for (let i = 0; i < crashes.length; i++) { - const crash = crashes[i]; - if (crash.local_id === '') { - crash.local_id = productName; - } - - const crashRow = template.content.cloneNode(true); - if (crash.state !== 'uploaded') { - crashRow.querySelector('.crash-row').classList.add('not-uploaded'); - } - - const uploaded = crash.state === 'uploaded'; - - // Some clients do not distinguish between capture time and upload time, - // so use the latter if the former is not available. - crashRow.querySelector('.capture-time').textContent = - loadTimeData.getStringF( - 'crashCaptureTimeFormat', - crash.capture_time || crash.upload_time || ''); - crashRow.querySelector('.local-id .value').textContent = crash.local_id; - - let stateText = ''; - switch (crash.state) { - case 'not_uploaded': - stateText = loadTimeData.getString('crashStatusNotUploaded'); - break; - case 'pending': - stateText = loadTimeData.getString('crashStatusPending'); - break; - case 'pending_user_requested': - stateText = loadTimeData.getString('crashStatusPendingUserRequested'); - break; - case 'uploaded': - stateText = loadTimeData.getString('crashStatusUploaded'); - break; - default: - continue; // Unknown state. - } - crashRow.querySelector('.status .value').textContent = stateText; - - const uploadId = crashRow.querySelector('.upload-id'); - const uploadTime = crashRow.querySelector('.upload-time'); - const sendNowButton = crashRow.querySelector('.send-now'); - const fileBugButton = crashRow.querySelector('.file-bug'); - if (uploaded) { - const uploadIdValue = uploadId.querySelector('.value'); - if (isGoogleAccount) { - const crashLink = document.createElement('a'); - crashLink.href = `https://goto.google.com/crash/${crash.id}`; - crashLink.target = '_blank'; - crashLink.textContent = crash.id; - uploadIdValue.appendChild(crashLink); - } else { - uploadIdValue.textContent = crash.id; - } - - uploadTime.querySelector('.value').textContent = crash.upload_time; - - sendNowButton.remove(); - fileBugButton.onclick = () => fileBug(crash.id, os, version); - } else { - uploadId.remove(); - uploadTime.remove(); - fileBugButton.remove(); - // Do not allow crash submission if the Chromium build does not support - // it, or if the user already requested it. - if (!manualUploads || crash.state === 'pending_user_requested') { - sendNowButton.remove(); - } - sendNowButton.onclick = (e) => { - e.target.disabled = true; - chrome.send('requestSingleCrashUpload', [crash.local_id]); - }; - } - - const fileSize = crashRow.querySelector('.file-size'); - if (crash.file_size === '') { - fileSize.remove(); - } else { - fileSize.querySelector('.value').textContent = crash.file_size; - } - - crashList.appendChild(crashRow); - } - - $('noCrashes').hidden = crashes.length !== 0; -} - -/** - * Opens a new tab/window to report the crash to crbug. - * @param {string} The crash report ID. - * @param {string} The OS name. - * @param {string} The product version. - */ -function fileBug(crashId, os, version) { - const commentLines = [ - 'IMPORTANT: Your crash has already been automatically reported ' + - 'to our crash system. Please file this bug only if you can provide ' + - 'more information about it.', - '', - '', - 'Chrome Version: ' + version, - 'Operating System: ' + os, - '', - 'URL (if applicable) where crash occurred:', - '', - 'Can you reproduce this crash?', - '', - 'What steps will reproduce this crash? (If it\'s not ' + - 'reproducible, what were you doing just before the crash?)', - '1.', - '2.', - '3.', - '', - '****DO NOT CHANGE BELOW THIS LINE****', - 'Crash ID: crash/' + crashId, - ]; - const params = { - template: 'Crash Report', - comment: commentLines.join('\n'), - // TODO(scottmg): Use add_labels to add 'User-Submitted' rather than - // duplicating the template's labels (the first two) once - // https://bugs.chromium.org/p/monorail/issues/detail?id=1488 is done. - labels: 'Restrict-View-EditIssue,Stability-Crash,User-Submitted,Pri-3,Type-Bug', - }; - let href = 'https://bugs.chromium.org/p/chromium/issues/entry'; - for (const param in params) { - href = appendParam(href, param, params[param]); - } - - window.open(href); -} - -/** - * Request crashes get uploaded in the background. - */ -function requestCrashUpload() { - // Don't need locking with this call because the system crash reporter - // has locking built into itself. - chrome.send('requestCrashUpload'); - - // Trigger a refresh in 5 seconds. Clear any previous requests. - clearTimeout(refreshCrashListId); - refreshCrashListId = setTimeout(requestCrashes, 5000); -} - -/** - * Toggles hiding/showing the developer details of a crash report, depending - * on the value of the check box. - * @param {Event} The DOM event for onclick. - */ -function toggleDevDetails(e) { - $('crashList').classList.toggle('showing-dev-details', e.target.checked); -} - -document.addEventListener('DOMContentLoaded', function() { - addWebUiListener('update-crash-list', updateCrashList); - $('uploadCrashes').onclick = requestCrashUpload; - $('showDevDetails').onclick = toggleDevDetails; - requestCrashes(); -});
diff --git a/components/crash/core/browser/resources/crashes.ts b/components/crash/core/browser/resources/crashes.ts new file mode 100644 index 0000000..4c7d88670 --- /dev/null +++ b/components/crash/core/browser/resources/crashes.ts
@@ -0,0 +1,260 @@ +// Copyright 2012 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// <if expr="is_ios"> +import 'chrome://resources/js/ios/web_ui.js'; +// </if> + +import 'chrome://resources/js/action_link.js'; +import './strings.m.js'; + +import {assert} from 'chrome://resources/js/assert_ts.js'; +import {addWebUiListener} from 'chrome://resources/js/cr.js'; +import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; +import {appendParam, getRequiredElement} from 'chrome://resources/js/util_ts.js'; + +/* Id for tracking automatic refresh of crash list. */ +let refreshCrashListId: number|undefined = undefined; + +/** + * Requests the list of crashes from the backend. + */ +function requestCrashes() { + chrome.send('requestCrashList'); +} + +// Keep in sync with components/crash/core/browser/crashes_ui_util.cc. +enum State { + NOT_UPLOADED = 'not_uploaded', + PENDING = 'pending', + PENDING_USER_REQUESTED = 'pending_user_requested', + UPLOADED = 'uploaded', +} + +interface CrashData { + file_size: string; + id: string; + local_id: string; + state: State; + capture_time?: string; + upload_time?: string; +} + +interface UpdateCrashListParams { + enabled: boolean; + dynamicBackend: boolean; + manualUploads: boolean; + crashes: CrashData[]; + version: string; + os: string; + isGoogleAccount: boolean; +} + +/** + * Callback from backend with the list of crashes. Builds the UI. + */ +function updateCrashList({ + enabled, + dynamicBackend, + manualUploads, + crashes, + version, + os, + isGoogleAccount, +}: UpdateCrashListParams) { + getRequiredElement('crashesCount').textContent = loadTimeData.getStringF( + 'crashCountFormat', crashes.length.toLocaleString()); + + const crashList = getRequiredElement('crashList'); + + getRequiredElement('disabledMode').hidden = enabled; + getRequiredElement('crashUploadStatus').hidden = !enabled || !dynamicBackend; + + const template = crashList.querySelector('template'); + assert(template); + + // Clear any previous list. + crashList.querySelectorAll('.crash-row').forEach((elm) => elm.remove()); + + const productName = loadTimeData.getString('shortProductName'); + + for (const crash of crashes) { + if (crash.local_id === '') { + crash.local_id = productName; + } + + const clone = template.content.cloneNode(true) as HTMLElement; + if (crash.state !== State.UPLOADED) { + const crashRow = clone.querySelector('.crash-row'); + assert(crashRow); + crashRow.classList.add('not-uploaded'); + } + + const uploaded = crash.state === State.UPLOADED; + + // Some clients do not distinguish between capture time and upload time, + // so use the latter if the former is not available. + const captureTime = clone.querySelector('.capture-time'); + assert(captureTime); + captureTime.textContent = loadTimeData.getStringF( + 'crashCaptureTimeFormat', + crash.capture_time || crash.upload_time || ''); + const localIdCell = clone.querySelector('.local-id .value'); + assert(localIdCell); + localIdCell.textContent = crash.local_id; + + let stateText = ''; + switch (crash.state) { + case State.NOT_UPLOADED: + stateText = loadTimeData.getString('crashStatusNotUploaded'); + break; + case State.PENDING: + stateText = loadTimeData.getString('crashStatusPending'); + break; + case State.PENDING_USER_REQUESTED: + stateText = loadTimeData.getString('crashStatusPendingUserRequested'); + break; + case State.UPLOADED: + stateText = loadTimeData.getString('crashStatusUploaded'); + break; + default: + continue; // Unknown state. + } + const statusCell = clone.querySelector('.status .value'); + assert(statusCell); + statusCell.textContent = stateText; + + const uploadId = clone.querySelector('.upload-id'); + assert(uploadId); + const uploadTime = clone.querySelector('.upload-time'); + assert(uploadTime); + const sendNowButton = clone.querySelector<HTMLButtonElement>('.send-now'); + assert(sendNowButton); + const fileBugButton = clone.querySelector<HTMLButtonElement>('.file-bug'); + assert(fileBugButton); + if (uploaded) { + const uploadIdValue = uploadId.querySelector('.value'); + assert(uploadIdValue); + if (isGoogleAccount) { + const crashLink = document.createElement('a'); + crashLink.href = `https://goto.google.com/crash/${crash.id}`; + crashLink.target = '_blank'; + crashLink.textContent = crash.id; + uploadIdValue.appendChild(crashLink); + } else { + uploadIdValue.textContent = crash.id; + } + + const uploadTimeCell = uploadTime.querySelector('.value'); + assert(uploadTimeCell); + uploadTimeCell.textContent = crash.upload_time || ''; + + sendNowButton.remove(); + fileBugButton.onclick = () => fileBug(crash.id, os, version); + } else { + uploadId.remove(); + uploadTime.remove(); + fileBugButton.remove(); + // Do not allow crash submission if the Chromium build does not support + // it, or if the user already requested it. + if (!manualUploads || crash.state === State.PENDING_USER_REQUESTED) { + sendNowButton.remove(); + } + sendNowButton.onclick = (_e: Event) => { + sendNowButton.disabled = true; + chrome.send('requestSingleCrashUpload', [crash.local_id]); + }; + } + + const fileSize = clone.querySelector('.file-size'); + assert(fileSize); + if (crash.file_size === '') { + fileSize.remove(); + } else { + const fileSizeCell = fileSize.querySelector('.value'); + assert(fileSizeCell); + fileSizeCell.textContent = crash.file_size; + } + + crashList.appendChild(clone); + } + + getRequiredElement('noCrashes').hidden = crashes.length !== 0; +} + +/** + * Opens a new tab/window to report the crash to crbug. + * @param The crash report ID. + * @param The OS name. + * @param The product version. + */ +function fileBug(crashId: string, os: string, version: string) { + const commentLines = [ + 'IMPORTANT: Your crash has already been automatically reported ' + + 'to our crash system. Please file this bug only if you can provide ' + + 'more information about it.', + '', + '', + 'Chrome Version: ' + version, + 'Operating System: ' + os, + '', + 'URL (if applicable) where crash occurred:', + '', + 'Can you reproduce this crash?', + '', + 'What steps will reproduce this crash? (If it\'s not ' + + 'reproducible, what were you doing just before the crash?)', + '1.', + '2.', + '3.', + '', + '****DO NOT CHANGE BELOW THIS LINE****', + 'Crash ID: crash/' + crashId, + ]; + const params: {[key: string]: string} = { + template: 'Crash Report', + comment: commentLines.join('\n'), + // TODO(scottmg): Use add_labels to add 'User-Submitted' rather than + // duplicating the template's labels (the first two) once + // https://bugs.chromium.org/p/monorail/issues/detail?id=1488 is done. + labels: + 'Restrict-View-EditIssue,Stability-Crash,User-Submitted,Pri-3,Type-Bug', + }; + let href = 'https://bugs.chromium.org/p/chromium/issues/entry'; + for (const param in params) { + href = appendParam(href, param, params[param]!); + } + + window.open(href); +} + +/** + * Request crashes get uploaded in the background. + */ +function requestCrashUpload() { + // Don't need locking with this call because the system crash reporter + // has locking built into itself. + chrome.send('requestCrashUpload'); + + // Trigger a refresh in 5 seconds. Clear any previous requests. + clearTimeout(refreshCrashListId); + refreshCrashListId = setTimeout(requestCrashes, 5000); +} + +/** + * Toggles hiding/showing the developer details of a crash report, depending + * on the value of the check box. + */ +function toggleDevDetails(e: Event) { + getRequiredElement('crashList') + .classList.toggle( + 'showing-dev-details', (e.target as HTMLInputElement).checked); +} + +document.addEventListener('DOMContentLoaded', function() { + addWebUiListener('update-crash-list', updateCrashList); + getRequiredElement('uploadCrashes').onclick = requestCrashUpload; + getRequiredElement('showDevDetails').onclick = toggleDevDetails; + requestCrashes(); +});
diff --git a/components/cronet/android/BUILD.gn b/components/cronet/android/BUILD.gn index f4870ee9..fa01227 100644 --- a/components/cronet/android/BUILD.gn +++ b/components/cronet/android/BUILD.gn
@@ -1018,6 +1018,7 @@ "test/javatests/src/org/chromium/net/CronetUrlRequestTest.java", "test/javatests/src/org/chromium/net/DiskStorageTest.java", "test/javatests/src/org/chromium/net/ExperimentalOptionsTest.java", + "test/javatests/src/org/chromium/net/FileUtils.java", "test/javatests/src/org/chromium/net/GetStatusTest.java", "test/javatests/src/org/chromium/net/MetricsTestUtil.java", "test/javatests/src/org/chromium/net/MockCertVerifierTest.java",
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java index 480ce21..8869c71 100644 --- a/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java +++ b/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java
@@ -36,7 +36,6 @@ import org.junit.Test; import org.junit.runner.RunWith; -import org.chromium.base.FileUtils; import org.chromium.base.PathUtils; import org.chromium.base.annotations.JNINamespace; import org.chromium.base.test.util.Feature; @@ -543,7 +542,7 @@ assertTrue(logFile.exists()); assertTrue(logFile.length() != 0); assertFalse(hasBytesInNetLog(logFile)); - FileUtils.recursivelyDeleteFile(netLogDir, FileUtils.DELETE_ALL); + FileUtils.recursivelyDeleteFile(netLogDir); assertFalse(netLogDir.exists()); } @@ -603,7 +602,7 @@ assertTrue(logFile.exists()); assertTrue(logFile.length() != 0); - FileUtils.recursivelyDeleteFile(netLogDir, FileUtils.DELETE_ALL); + FileUtils.recursivelyDeleteFile(netLogDir); assertFalse(netLogDir.exists()); } @@ -857,9 +856,9 @@ assertTrue(containsStringInNetLog(logFile2, mUrl404)); assertTrue(containsStringInNetLog(logFile2, mUrl500)); - FileUtils.recursivelyDeleteFile(netLogDir1, FileUtils.DELETE_ALL); + FileUtils.recursivelyDeleteFile(netLogDir1); assertFalse(netLogDir1.exists()); - FileUtils.recursivelyDeleteFile(netLogDir2, FileUtils.DELETE_ALL); + FileUtils.recursivelyDeleteFile(netLogDir2); assertFalse(netLogDir2.exists()); } @@ -1033,7 +1032,7 @@ assertEquals("Engine is shut down.", e.getMessage()); } assertFalse(logFile.exists()); - FileUtils.recursivelyDeleteFile(netLogDir, FileUtils.DELETE_ALL); + FileUtils.recursivelyDeleteFile(netLogDir); assertFalse(netLogDir.exists()); } @@ -1091,7 +1090,7 @@ assertTrue(logFile.exists()); assertTrue(logFile.length() != 0); assertFalse(hasBytesInNetLog(logFile)); - FileUtils.recursivelyDeleteFile(netLogDir, FileUtils.DELETE_ALL); + FileUtils.recursivelyDeleteFile(netLogDir); assertFalse(netLogDir.exists()); } @@ -1151,7 +1150,7 @@ assertTrue(logFile.exists()); assertTrue(logFile.length() != 0); assertFalse(hasBytesInNetLog(logFile)); - FileUtils.recursivelyDeleteFile(netLogDir, FileUtils.DELETE_ALL); + FileUtils.recursivelyDeleteFile(netLogDir); assertFalse(netLogDir.exists()); } @@ -1206,7 +1205,7 @@ assertTrue(logFile.exists()); assertTrue(logFile.length() != 0); assertTrue(hasBytesInNetLog(logFile)); - FileUtils.recursivelyDeleteFile(netLogDir, FileUtils.DELETE_ALL); + FileUtils.recursivelyDeleteFile(netLogDir); assertFalse(netLogDir.exists()); }
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/DiskStorageTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/DiskStorageTest.java index d5acf26..846c792a 100644 --- a/components/cronet/android/test/javatests/src/org/chromium/net/DiskStorageTest.java +++ b/components/cronet/android/test/javatests/src/org/chromium/net/DiskStorageTest.java
@@ -22,7 +22,6 @@ import org.junit.Test; import org.junit.runner.RunWith; -import org.chromium.base.FileUtils; import org.chromium.base.PathUtils; import org.chromium.base.test.util.Feature; import org.chromium.net.CronetTestRule.OnlyRunNativeCronet; @@ -53,7 +52,7 @@ @After public void tearDown() throws Exception { if (mReadOnlyStoragePath != null) { - FileUtils.recursivelyDeleteFile(new File(mReadOnlyStoragePath), FileUtils.DELETE_ALL); + FileUtils.recursivelyDeleteFile(new File(mReadOnlyStoragePath)); } NativeTestServer.shutdownNativeTestServer(); }
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/FileUtils.java b/components/cronet/android/test/javatests/src/org/chromium/net/FileUtils.java new file mode 100644 index 0000000..3fd84773 --- /dev/null +++ b/components/cronet/android/test/javatests/src/org/chromium/net/FileUtils.java
@@ -0,0 +1,41 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.net; + +import org.chromium.base.Log; + +import java.io.File; + +/** + * Simpler fork of the org.chromium.base class that doesn't rely on java.util.function.Function + * (unavailable on Android <= M). + */ +public class FileUtils { + private static final String TAG = "FileUtils"; + + public static boolean recursivelyDeleteFile(File currentFile) { + if (!currentFile.exists()) { + // This file could be a broken symlink, so try to delete. If we don't delete a broken + // symlink, the directory containing it cannot be deleted. + currentFile.delete(); + return true; + } + + if (currentFile.isDirectory()) { + File[] files = currentFile.listFiles(); + if (files != null) { + for (var file : files) { + recursivelyDeleteFile(file); + } + } + } + + boolean ret = currentFile.delete(); + if (!ret) { + Log.e(TAG, "Failed to delete: %s", currentFile); + } + return ret; + } +}
diff --git a/components/enterprise/browser/controller/chrome_browser_cloud_management_controller.cc b/components/enterprise/browser/controller/chrome_browser_cloud_management_controller.cc index 8fc09105..cab052e 100644 --- a/components/enterprise/browser/controller/chrome_browser_cloud_management_controller.cc +++ b/components/enterprise/browser/controller/chrome_browser_cloud_management_controller.cc
@@ -29,6 +29,7 @@ #include "components/policy/core/common/cloud/machine_level_user_cloud_policy_manager.h" #include "components/policy/core/common/cloud/machine_level_user_cloud_policy_store.h" #include "components/policy/core/common/configuration_policy_provider.h" +#include "components/prefs/pref_service.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #if !BUILDFLAG(IS_ANDROID)
diff --git a/components/exo/shell_surface_base.cc b/components/exo/shell_surface_base.cc index de31a67..94c80e4 100644 --- a/components/exo/shell_surface_base.cc +++ b/components/exo/shell_surface_base.cc
@@ -881,7 +881,7 @@ CommitWidget(); OnPostWidgetCommit(); - + DidCommit(); SubmitCompositorFrame(); }
diff --git a/components/exo/surface_tree_host.cc b/components/exo/surface_tree_host.cc index 963e96a..e6df4711 100644 --- a/components/exo/surface_tree_host.cc +++ b/components/exo/surface_tree_host.cc
@@ -197,6 +197,10 @@ active_presentation_callbacks_.erase(it); } +void SurfaceTreeHost::SetScaleFactor(float scale_factor) { + pending_scale_factor_ = scale_factor; +} + void SurfaceTreeHost::SetSecurityDelegate(SecurityDelegate* security_delegate) { DCHECK(security_delegate_ == nullptr); security_delegate_ = security_delegate; @@ -270,6 +274,10 @@ } } +void SurfaceTreeHost::DidCommit() { + scale_factor_ = pending_scale_factor_; +} + void SurfaceTreeHost::SubmitCompositorFrame() { viz::CompositorFrame frame = PrepareToSubmitCompositorFrame(); @@ -299,8 +307,7 @@ } root_surface_->AppendSurfaceHierarchyContentsToFrame( - gfx::PointF(root_surface_origin_), - host_window()->layer()->device_scale_factor(), + gfx::PointF(root_surface_origin_), GetScaleFactor(), layer_tree_frame_sink_holder_->resource_manager(), &frame); std::vector<GLbyte*> sync_tokens; @@ -358,7 +365,7 @@ // synchronization. if (client_submits_surfaces_in_pixel_coordinates_) { gfx::Transform tr; - float scale = host_window_->layer()->device_scale_factor(); + float scale = GetScaleFactor(); tr.Scale(1.0f / scale, 1.0f / scale); if (host_window_->transform() != tr) host_window_->SetTransform(tr); @@ -410,8 +417,7 @@ // compositor frame, otherwise we may set the Surface created by Viz to be the // wrong size. Then, trying to submit a regular compositor frame will fail // because the size is different. - const float device_scale_factor = - host_window()->layer()->device_scale_factor(); + const float device_scale_factor = GetScaleFactor(); // TODO(crbug.com/1131628): Should this be ceil? Why do we choose floor? gfx::Size output_surface_size_in_pixels = gfx::ToFlooredSize(gfx::ConvertSizeToPixels(host_window_->bounds().size(), @@ -446,4 +452,10 @@ SubmitCompositorFrame(); } +float SurfaceTreeHost::GetScaleFactor() { + if (scale_factor_) + return scale_factor_.value(); + return host_window_->layer()->device_scale_factor(); +} + } // namespace exo
diff --git a/components/exo/surface_tree_host.h b/components/exo/surface_tree_host.h index 2730978..63ad7f0 100644 --- a/components/exo/surface_tree_host.h +++ b/components/exo/surface_tree_host.h
@@ -61,6 +61,10 @@ void DidPresentCompositorFrame(uint32_t presentation_token, const gfx::PresentationFeedback& feedback); + // Sets the scale factor for all buffers associated with this surface. This + // affects all future commits. + void SetScaleFactor(float scale_factor); + aura::Window* host_window() { return host_window_.get(); } const aura::Window* host_window() const { return host_window_.get(); } @@ -133,6 +137,10 @@ protected: void UpdateDisplayOnTree(); + // Call this after a buffer has been committed but before a compositor frame + // has been submitted. + void DidCommit(); + // Call this to submit a compositor frame. void SubmitCompositorFrame(); @@ -154,6 +162,10 @@ void HandleContextLost(); + // If the client has submitted a scale factor, we use that. Otherwise we use + // the host window's layer's scale factor. + float GetScaleFactor(); + Surface* root_surface_ = nullptr; // Position of root surface relative to topmost, leftmost sub-surface. The @@ -175,6 +187,14 @@ base::flat_map<uint32_t, PresentationCallbacks> active_presentation_callbacks_; + // When a client calls set_scale_factor they're actually setting the scale + // factor for all future commits. + absl::optional<float> pending_scale_factor_; + + // This is the client-set scale factor that is being used for the current + // buffer. + absl::optional<float> scale_factor_; + viz::FrameTokenGenerator next_token_; scoped_refptr<viz::ContextProvider> context_provider_;
diff --git a/components/exo/wayland/protocol/aura-shell.xml b/components/exo/wayland/protocol/aura-shell.xml index 43f6d86..8fbe3c1 100644 --- a/components/exo/wayland/protocol/aura-shell.xml +++ b/components/exo/wayland/protocol/aura-shell.xml
@@ -24,7 +24,7 @@ DEALINGS IN THE SOFTWARE. </copyright> - <interface name="zaura_shell" version="45"> + <interface name="zaura_shell" version="46"> <description summary="aura_shell"> The global interface exposing aura shell capabilities is used to instantiate an interface extension for a wl_surface object. @@ -702,7 +702,7 @@ </event> </interface> - <interface name="zaura_toplevel" version="44"> + <interface name="zaura_toplevel" version="46"> <description summary="aura shell interface to the toplevel shell"> An interface to the toplevel shell, which allows the client to access shell specific functionality. @@ -985,9 +985,25 @@ </description> <arg name="mode" type="uint" enum="fullscreen_mode"/> </request> + + <!-- Version 46 additions --> + <request name="set_scale_factor" since="46"> + <description summary="Allows the client to set the scale factor for the future buffer commits."> + The client has a 32-bit float scale factor that is associated with each + zaura toplevel. This scale factor must be propagated exactly to exo. To + do so we reinterpret_cast into a 32-bit uint and later cast back into a + float. This is because wayland does not support native transport of + floats. As different CPU architectures may use different endian + representations for IEEE 754 floats, this protocol implicitly assumes + that the caller and receiver are the same machine. To avoid redundant + messages, this request needs to only be called once when the zaura + toplevel scale factor changes. + </description> + <arg name="scale_factor_as_uint" type="uint"/> + </request> </interface> - <interface name="zaura_popup" version="38"> + <interface name="zaura_popup" version="46"> <description summary="aura shell interface to the popup shell"> An interface to the popup shell, which allows the client to access shell specific functionality. @@ -1035,5 +1051,21 @@ See zaura_shell.release for destructor naming. </description> </request> + + <!-- Version 46 additions --> + <request name="set_scale_factor" since="46"> + <description summary="Allows the client to set the scale factor for the future buffer commits."> + The client has a 32-bit float scale factor that is associated with each + zaura popup. This scale factor must be propagated exactly to exo. To + do so we reinterpret_cast into a 32-bit uint and later cast back into a + float. This is because wayland does not support native transport of + floats. As different CPU architectures may use different endian + representations for IEEE 754 floats, this protocol implicitly assumes + that the caller and receiver are the same machine. To avoid redundant + messages, this request needs to only be called once when the zaura + popup's scale factor changes. + </description> + <arg name="scale_factor_as_uint" type="uint"/> + </request> </interface> </protocol>
diff --git a/components/exo/wayland/zaura_shell.cc b/components/exo/wayland/zaura_shell.cc index 7cb6eaf..f3b77650 100644 --- a/components/exo/wayland/zaura_shell.cc +++ b/components/exo/wayland/zaura_shell.cc
@@ -755,6 +755,10 @@ shell_surface_->SetUseImmersiveForFullscreen(IsImmersive(mode)); } +void AuraToplevel::SetScaleFactor(float scale_factor) { + shell_surface_->SetScaleFactor(scale_factor); +} + void AuraToplevel::SetClientUsesScreenCoordinates() { supports_window_bounds_ = true; shell_surface_->set_client_supports_window_bounds(true); @@ -842,6 +846,10 @@ shell_surface_->SetMenu(); } +void AuraPopup::SetScaleFactor(float scale_factor) { + shell_surface_->SetScaleFactor(scale_factor); +} + namespace { void aura_output_release(wl_client* client, wl_resource* resource) { @@ -1282,6 +1290,15 @@ GetUserDataAs<AuraToplevel>(resource)->SetFullscreenMode(mode); } +void aura_toplevel_set_scale_factor(wl_client* client, + wl_resource* resource, + uint32_t scale_factor_as_uint) { + static_assert(sizeof(uint32_t) == sizeof(float), + "Sizes much match for reinterpret cast to be meaningful"); + float scale_factor = *reinterpret_cast<float*>(&scale_factor_as_uint); + GetUserDataAs<AuraToplevel>(resource)->SetScaleFactor(scale_factor); +} + const struct zaura_toplevel_interface aura_toplevel_implementation = { aura_toplevel_set_orientation_lock, aura_toplevel_surface_submission_in_pixel_coordinates, @@ -1300,6 +1317,7 @@ aura_toplevel_activate, aura_toplevel_deactivate, aura_toplevel_set_fullscreen_mode, + aura_toplevel_set_scale_factor, }; void aura_popup_surface_submission_in_pixel_coordinates(wl_client* client, @@ -1337,11 +1355,21 @@ wl_resource_destroy(resource); } +void aura_popup_set_scale_factor(wl_client* client, + wl_resource* resource, + uint32_t scale_factor_as_uint) { + static_assert(sizeof(uint32_t) == sizeof(float), + "Sizes much match for reinterpret cast to be meaningful"); + float scale_factor = *reinterpret_cast<float*>(&scale_factor_as_uint); + GetUserDataAs<AuraPopup>(resource)->SetScaleFactor(scale_factor); +} + const struct zaura_popup_interface aura_popup_implementation = { aura_popup_surface_submission_in_pixel_coordinates, aura_popup_set_decoration, aura_popup_set_menu, aura_popup_release, + aura_popup_set_scale_factor, }; void aura_shell_get_aura_toplevel(wl_client* client,
diff --git a/components/exo/wayland/zaura_shell.h b/components/exo/wayland/zaura_shell.h index 083f78b6..45f0f8a 100644 --- a/components/exo/wayland/zaura_shell.h +++ b/components/exo/wayland/zaura_shell.h
@@ -27,7 +27,7 @@ namespace wayland { class SerialTracker; -constexpr uint32_t kZAuraShellVersion = 45; +constexpr uint32_t kZAuraShellVersion = 46; // Adds bindings to the Aura Shell. Normally this implies Ash on ChromeOS // builds. On non-ChromeOS builds the protocol provides access to Aura windowing @@ -138,6 +138,7 @@ void Activate(); void Deactivate(); void SetFullscreenMode(uint32_t mode); + void SetScaleFactor(float scale_factor); ShellSurface* shell_surface_; SerialTracker* const serial_tracker_; @@ -158,6 +159,7 @@ void SetClientSubmitsSurfacesInPixelCoordinates(bool enable); void SetDecoration(SurfaceFrameType type); void SetMenu(); + void SetScaleFactor(float scale_factor); private: ShellSurfaceBase* shell_surface_;
diff --git a/components/omnibox/browser/BUILD.gn b/components/omnibox/browser/BUILD.gn index 114217b..de0b00b1 100644 --- a/components/omnibox/browser/BUILD.gn +++ b/components/omnibox/browser/BUILD.gn
@@ -200,6 +200,8 @@ "on_device_model_update_listener.h", "on_device_tail_model_observer.cc", "on_device_tail_model_observer.h", + "on_device_tail_tokenizer.cc", + "on_device_tail_tokenizer.h", "open_tab_provider.cc", "open_tab_provider.h", "query_tile_provider.cc", @@ -595,6 +597,8 @@ "//components/test/data/omnibox/in_memory_url_index_test.sql", "//components/test/data/omnibox/in_memory_url_index_test_limited.sql", "//components/test/data/omnibox/on_device_head_test_model_index.bin", + "//components/test/data/omnibox/test_tail_model.tflite", + "//components/test/data/omnibox/vocab_test.txt", ] outputs = [ "{{bundle_resources_dir}}/" + "{{source_root_relative_dir}}/{{source_file_part}}" ] @@ -641,6 +645,7 @@ "on_device_head_model_unittest.cc", "on_device_head_provider_unittest.cc", "on_device_model_update_listener_unittest.cc", + "on_device_tail_tokenizer_unittest.cc", "query_tile_provider_unittest.cc", "remote_suggestions_service_unittest.cc", "scored_history_match_unittest.cc",
diff --git a/components/omnibox/browser/on_device_tail_tokenizer.cc b/components/omnibox/browser/on_device_tail_tokenizer.cc new file mode 100644 index 0000000..2d6d858c --- /dev/null +++ b/components/omnibox/browser/on_device_tail_tokenizer.cc
@@ -0,0 +1,242 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/omnibox/browser/on_device_tail_tokenizer.h" + +#include <algorithm> +#include <fstream> +#include <sstream> +#include <string> +#include <utility> +#include <vector> + +#include "base/containers/flat_map.h" +#include "base/containers/flat_set.h" +#include "base/files/file_util.h" +#include "base/logging.h" +#include "base/strings/string_util.h" + +namespace { +// Maximum vocabulary file size that will be loaded in bytes. +static constexpr size_t kVocabFileSizeLimit = 64 * 1024; + +// The max num of single char tokens. +static constexpr size_t kNumSingleChar = 256; + +// Special control tokens. +static constexpr char kBeginQueryToken[] = "<Q>"; +static constexpr char kEndQueryToken[] = "</Q>"; +static constexpr char kEmptyPreviousQueryToken[] = "<NPQ>"; +static constexpr char kUnknownToken[] = "<UNK>"; + +std::ostream& operator<<(std::ostream& os, + const base::flat_set<std::string>& tokens) { + if (tokens.empty()) { + return os; + } + + auto iter = tokens.begin(); + os << *iter; + ++iter; + + for (; iter != tokens.end(); iter++) { + os << ", " << *iter; + } + return os; +} + +} // namespace + +OnDeviceTailTokenization::OnDeviceTailTokenization() = default; + +OnDeviceTailTokenization::~OnDeviceTailTokenization() = default; + +OnDeviceTailTokenizer::OnDeviceTailTokenizer() = default; + +OnDeviceTailTokenizer::~OnDeviceTailTokenizer() = default; + +bool OnDeviceTailTokenizer::Init(const base::FilePath& vocabulary_filepath) { + std::string vocabulary_content; + if (!base::ReadFileToStringWithMaxSize( + vocabulary_filepath, &vocabulary_content, kVocabFileSizeLimit)) { + DVLOG(1) << "Failed to read the vocabulary file " + << vocabulary_filepath.LossyDisplayName(); + return false; + } + + base::flat_set<std::string> control_tokens = { + kBeginQueryToken, kEndQueryToken, kEmptyPreviousQueryToken, + kUnknownToken}; + + std::string token; + max_token_length_ = 0; + + // The first 256 tokens are ASCII characters. + for (size_t i = 0; i < kNumSingleChar; i++) { + token = static_cast<char>(i); + InsertTokenToMaps(token); + } + + std::stringstream vocabulary(vocabulary_content); + while (std::getline(vocabulary, token)) { + if (token.empty()) { + break; + } + + // Duplicate tokens are not allowed. + if (token_to_id_.find(token) != token_to_id_.end()) { + Reset(); + DVLOG(1) << "Duplicate token found: " << token; + return false; + } + + InsertTokenToMaps(token); + if (control_tokens.find(token) != control_tokens.end()) { + control_tokens.erase(token); + } else { + max_token_length_ = std::max<size_t>(max_token_length_, token.size()); + } + } + + // A valid vocabulary should include all control tokens. + if (!control_tokens.empty()) { + Reset(); + DVLOG(1) << "Missing following control tokens: " << control_tokens; + return false; + } + + InitAmbiguousMap(); + + return IsReady(); +} + +bool OnDeviceTailTokenizer::IsReady() const { + return !token_to_id_.empty(); +} + +void OnDeviceTailTokenizer::Reset() { + token_to_id_.clear(); + id_to_token_.clear(); + ambiguous_tokens_.clear(); +} + +std::string OnDeviceTailTokenizer::IDToToken(const size_t token_id) const { + if (token_id < 0 || token_id >= id_to_token_.size()) { + return kUnknownToken; + } + return id_to_token_[token_id]; +} + +size_t OnDeviceTailTokenizer::TokenToID(const std::string& token) const { + auto match = token_to_id_.find(token); + if (match == token_to_id_.end()) { + // The ID for unknown token. + return token_to_id_.find(kUnknownToken)->second; + } + return match->second; +} + +void OnDeviceTailTokenizer::InitAmbiguousMap() { + base::flat_map<std::string, size_t> prefix_count; + for (const std::string& token : id_to_token_) { + // Skip special tokens. + if (token[0] == '<') { + continue; + } + + for (size_t len = 1; len <= token.size(); len++) { + prefix_count[token.substr(0, len)] += 1; + } + } + + // Marks tokens as ambiguous if corresponding prefixes occur multiple times. + for (const auto& iter : prefix_count) { + if (iter.second > 1) { + ambiguous_tokens_.insert(iter.first); + } + } +} + +bool OnDeviceTailTokenizer::IsAmbiguousToken(const std::string& token) const { + return ambiguous_tokens_.find(token) != ambiguous_tokens_.end(); +} + +void OnDeviceTailTokenizer::EncodeRawString( + const std::string& raw_string, + std::vector<std::pair<std::string, size_t>>* token_and_ids) const { + size_t i = 0; + while (i < raw_string.size()) { + // Tries longest possible matches first and reduces the length gradually + // until a match is found. + size_t len = std::min<size_t>(max_token_length_, raw_string.size() - i); + while (len >= 1) { + auto iter = token_to_id_.find(raw_string.substr(i, len)); + if (iter != token_to_id_.end()) { + token_and_ids->push_back({iter->first, iter->second}); + i += len; + break; + } + len--; + } + + // Unknown token is found. + if (len == 0) { + DVLOG(1) << "Invalid token found for raw string: " << raw_string; + token_and_ids->clear(); + return; + } + } +} + +void OnDeviceTailTokenizer::TokenizePrevQuery( + const std::string& prev_query, + std::vector<size_t>* prev_query_token_ids) const { + prev_query_token_ids->clear(); + + if (prev_query.empty()) { + // Uses the special control token <NPQ> to mark empty previous query. + prev_query_token_ids->push_back(TokenToID(kEmptyPreviousQueryToken)); + return; + } + + std::vector<std::pair<std::string, size_t>> token_and_ids; + EncodeRawString(prev_query, &token_and_ids); + + for (const auto& pair : token_and_ids) { + prev_query_token_ids->push_back(pair.second); + } +} + +void OnDeviceTailTokenizer::CreatePrefixTokenization( + const std::string& prefix, + OnDeviceTailTokenization* tokenization) const { + std::vector<std::pair<std::string, size_t>> token_and_ids; + + EncodeRawString(prefix, &token_and_ids); + if (token_and_ids.empty()) { + return; + } + + // Checks if the last token is ambiguous. + size_t num_unambiguous = token_and_ids.size(); + if (IsAmbiguousToken(token_and_ids[token_and_ids.size() - 1].first)) { + num_unambiguous--; + tokenization->constraint_prefix = + token_and_ids[token_and_ids.size() - 1].first; + } + + // Always add begin query token at the front of the prefix. + tokenization->unambiguous_ids.push_back(TokenToID(kBeginQueryToken)); + for (size_t i = 0; i < num_unambiguous; ++i) { + tokenization->unambiguous_prefix += token_and_ids[i].first; + tokenization->unambiguous_ids.push_back(token_and_ids[i].second); + } +} + +void OnDeviceTailTokenizer::InsertTokenToMaps(const std::string& token) { + DCHECK(!token.empty()); + token_to_id_.insert({token, id_to_token_.size()}); + id_to_token_.push_back(std::move(token)); + DCHECK_EQ(token_to_id_.size(), id_to_token_.size()); +} \ No newline at end of file
diff --git a/components/omnibox/browser/on_device_tail_tokenizer.h b/components/omnibox/browser/on_device_tail_tokenizer.h new file mode 100644 index 0000000..cf52b3b --- /dev/null +++ b/components/omnibox/browser/on_device_tail_tokenizer.h
@@ -0,0 +1,105 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_OMNIBOX_BROWSER_ON_DEVICE_TAIL_TOKENIZER_H_ +#define COMPONENTS_OMNIBOX_BROWSER_ON_DEVICE_TAIL_TOKENIZER_H_ + +#include <memory> +#include <string> +#include <utility> +#include <vector> + +#include "base/containers/flat_map.h" +#include "base/containers/flat_set.h" +#include "base/files/file_path.h" + +// Data structure to store tokenization information. +struct OnDeviceTailTokenization { + // Unambiguous token IDs. This should at least include the begin query token. + std::vector<size_t> unambiguous_ids; + + // Human-readable unambiguous part of the prefix. + std::string unambiguous_prefix; + + // The constraint prefix for the next forward RNN step, if the last typed + // token was ambiguous. For example, given prefix [(pa)(t)] and if the + // trailing (t) could match multiple tokens, constraint prefix will be set as + // "t" and only outputs matching this prefix from the next step will be kept. + std::string constraint_prefix; + + OnDeviceTailTokenization(); + ~OnDeviceTailTokenization(); +}; + +// The tokenizer performs tokenization for on device tail machine learning +// model. It basically maps raw strings to/from tokens, and tokens to/from IDs +// accepted by the ML model or vice versa based on the given vocabulary file. +// This tokenizer has not supported CJK yet. +class OnDeviceTailTokenizer { + public: + ~OnDeviceTailTokenizer(); + OnDeviceTailTokenizer(); + + // Loads the vocabulary file and initializes the tokenizer. + bool Init(const base::FilePath& vocabulary_filepath); + + // Determines whether the instance is successfully initialized. + bool IsReady() const; + + // Fills the OnDeviceTailTokenization struct for the given prefix. + void CreatePrefixTokenization(const std::string& prefix, + OnDeviceTailTokenization* tokenization) const; + + // Tokenizes the previous query greedily. + void TokenizePrevQuery(const std::string& prev_query, + std::vector<size_t>* prev_query_token_ids) const; + + // Resets tokens <-> IDs maps. + void Reset(); + + // Maps token to ID and vice versa. + std::string IDToToken(const size_t token_id) const; + size_t TokenToID(const std::string& token) const; + + // Returns the size of the vocabulary. + size_t vocab_size() const { return token_to_id_.size(); } + + private: + // Determines if the given token is ambiguous. + bool IsAmbiguousToken(const std::string& token) const; + + // Initializes the ambiguous tokens map. + void InitAmbiguousMap(); + + // Encodes the given raw string to its corresponding token and ID pairs. + // Note we always use the longest tokens in the vocabulary first and gradually + // switch to shorter tokens until a match for the prefix of the remaining + // string is found. Then jump to the start of the unmatched part of the string + // and do this again until we match all characters of the string. + // For example, given vocabulary: + // [1:a], [2:b], [3:c], [4:abc], [5:ab] + // Encoding: + // string:abcabc -> tokens:[abc][abc] -> IDs:[4][4] + // string:abcab -> tokens:[abc][ab] -> IDs:[4][5] + // string:abcaba -> tokens:[abc][ab][a] -> IDs:[4][5][1] + // string:cbacba -> tokens:[c][b][a][c][b][a] -> IDs:[3][2][1][3][2][1] + void EncodeRawString( + const std::string& raw_string, + std::vector<std::pair<std::string, size_t>>* token_and_ids) const; + + // Insert token and its ID to tokens <-> IDs maps. + void InsertTokenToMaps(const std::string& token); + + // Maps for tokens <-> IDs. + base::flat_map<std::string, size_t> token_to_id_; + std::vector<std::string> id_to_token_; + + // The max length of tokens in the vocabulary. + size_t max_token_length_; + + // The list of ambiguous tokens. + base::flat_set<std::string> ambiguous_tokens_; +}; + +#endif // COMPONENTS_OMNIBOX_BROWSER_ON_DEVICE_TAIL_TOKENIZER_H_
diff --git a/components/omnibox/browser/on_device_tail_tokenizer_unittest.cc b/components/omnibox/browser/on_device_tail_tokenizer_unittest.cc new file mode 100644 index 0000000..032ef2a --- /dev/null +++ b/components/omnibox/browser/on_device_tail_tokenizer_unittest.cc
@@ -0,0 +1,105 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/omnibox/browser/on_device_tail_tokenizer.h" + +#include <string> +#include <vector> + +#include "base/files/file_path.h" +#include "base/path_service.h" +#include "base/strings/utf_string_conversions.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using ::testing::ElementsAreArray; + +namespace { + +base::FilePath GetTestVocabFilePath() { + base::FilePath file_path; + base::PathService::Get(base::DIR_SOURCE_ROOT, &file_path); + file_path = + file_path.AppendASCII("components/test/data/omnibox/vocab_test.txt"); + + return file_path; +} + +} // namespace + +class OnDeviceTailTokenizerTest : public ::testing::Test { + public: + OnDeviceTailTokenizerTest() { tokenizer_.Reset(); } + + protected: + OnDeviceTailTokenizer tokenizer_; +}; + +TEST_F(OnDeviceTailTokenizerTest, CreatePrefixTokenization) { + tokenizer_.Init(GetTestVocabFilePath()); + + EXPECT_TRUE(tokenizer_.IsReady()); + + { + OnDeviceTailTokenization tokenization; + // Expect tokens ["n", "j", " ", "do", "c"]. + // See OnDeviceTailTokenizer::EncodeRawString for details and simplified + // examples about how ID sequences are determined. + tokenizer_.CreatePrefixTokenization("nj doc", &tokenization); + EXPECT_THAT(tokenization.unambiguous_ids, + testing::ElementsAreArray({257, 110, 106, 32, 297})); + EXPECT_EQ("c", tokenization.constraint_prefix); + EXPECT_EQ("nj do", tokenization.unambiguous_prefix); + } + + { + OnDeviceTailTokenization tokenization; + // Expect tokens ["re", "mi", "t", "ly", " ", "log", "in"]. + tokenizer_.CreatePrefixTokenization("remitly login", &tokenization); + EXPECT_THAT(tokenization.unambiguous_ids, + testing::ElementsAreArray({257, 414, 366, 116, 363, 32, 521})); + EXPECT_EQ("in", tokenization.constraint_prefix); + EXPECT_EQ("remitly log", tokenization.unambiguous_prefix); + } + + { + OnDeviceTailTokenization tokenization; + // Expect tokens + // ["us", " ", "pa", "ss", "po", "rt", " ", "ap", "pl", "ica", "tio", "n"] + tokenizer_.CreatePrefixTokenization("us passport application", + &tokenization); + EXPECT_THAT(tokenization.unambiguous_ids, + testing::ElementsAreArray({257, 456, 32, 402, 434, 407, 424, 32, + 270, 406, 507, 549})); + EXPECT_EQ("n", tokenization.constraint_prefix); + EXPECT_EQ("us passport applicatio", tokenization.unambiguous_prefix); + } +} + +TEST_F(OnDeviceTailTokenizerTest, TokenizePrevQuery) { + tokenizer_.Init(GetTestVocabFilePath()); + + EXPECT_TRUE(tokenizer_.IsReady()); + { + std::vector<size_t> token_ids; + tokenizer_.TokenizePrevQuery("facebook", &token_ids); + + // Expect tokens: ["fa", "ce", "bo", "ok"] + EXPECT_EQ(4, (int)token_ids.size()); + EXPECT_THAT(token_ids, ElementsAreArray({317, 285, 281, 390})); + EXPECT_EQ("fa", tokenizer_.IDToToken(token_ids[0])); + } + + { + std::vector<size_t> token_ids; + tokenizer_.TokenizePrevQuery("matching gym outfits", &token_ids); + + // Expect tokens: + // ["ma", "t", "chi", "ng", " ", "g", "y", "m", " ", "out", "fi", "ts"] + EXPECT_EQ(12, (int)token_ids.size()); + EXPECT_THAT(token_ids, ElementsAreArray({364, 116, 488, 375, 32, 103, 121, + 109, 32, 533, 320, 443})); + EXPECT_EQ("ma", tokenizer_.IDToToken(token_ids[0])); + } +}
diff --git a/components/omnibox/browser/url_index_private_data.cc b/components/omnibox/browser/url_index_private_data.cc index 5fcd611e..20d192a0 100644 --- a/components/omnibox/browser/url_index_private_data.cc +++ b/components/omnibox/browser/url_index_private_data.cc
@@ -669,16 +669,26 @@ // unique hosts in the matches instead. static bool count_unique_hosts = base::FeatureList::IsEnabled( omnibox::kHistoryQuickProviderSpecificityScoreCountUniqueHosts); - const size_t num_unique_hosts = - count_unique_hosts ? base::MakeFlatSet<std::string>( - history_ids, {}, - [&](const auto history_id) { - return history_info_map_.find(history_id) - ->second.url_row.url() - .host(); - }) - .size() - : history_ids.size(); + size_t num_unique_hosts; + if (count_unique_hosts) { + std::set<std::string> unique_hosts = {}; + for (const auto& history_id : history_ids) { + DCHECK(history_info_map_.count(history_id)); + unique_hosts.insert( + history_info_map_.find(history_id)->second.url_row.url().host()); + // `ScoredHistoryMatch` assigns the same specificity to suggestions for + // counts 4 or larger. + // TODO(manukh) Should share `kMaxUniqueHosts` with `ScoredHistoryMatch`, + // but doing so is complicated as it's derived from parsing the default + // string value for the finch param `kHQPNumMatchesScoresRule`. + constexpr size_t kMaxUniqueHosts = 4; + if (unique_hosts.size() >= kMaxUniqueHosts) + break; + } + num_unique_hosts = unique_hosts.size(); + } else { + num_unique_hosts = history_ids.size(); + } for (HistoryID history_id : history_ids) { auto hist_pos = history_info_map_.find(history_id);
diff --git a/components/payments/content/payment_handler_host.cc b/components/payments/content/payment_handler_host.cc index b4b39f3..4924824 100644 --- a/components/payments/content/payment_handler_host.cc +++ b/components/payments/content/payment_handler_host.cc
@@ -17,6 +17,7 @@ #include "content/public/browser/devtools_background_services_context.h" #include "content/public/browser/storage_partition.h" #include "content/public/browser/web_contents.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" #include "url/origin.h" namespace payments { @@ -152,7 +153,7 @@ } dev_tools->LogBackgroundServiceEvent( - registration_id_for_logs_, sw_origin_for_logs_, + registration_id_for_logs_, blink::StorageKey(sw_origin_for_logs_), content::DevToolsBackgroundService::kPaymentHandler, "Update with", /*instance_id=*/payment_request_id_for_logs_, data); } @@ -202,7 +203,7 @@ auto* dev_tools = GetDevTools(web_contents_.get(), sw_origin_for_logs_); if (dev_tools) { dev_tools->LogBackgroundServiceEvent( - registration_id_for_logs_, sw_origin_for_logs_, + registration_id_for_logs_, blink::StorageKey(sw_origin_for_logs_), content::DevToolsBackgroundService::kPaymentHandler, "Change payment method", /*instance_id=*/payment_request_id_for_logs_, @@ -232,7 +233,7 @@ auto* dev_tools = GetDevTools(web_contents_.get(), sw_origin_for_logs_); if (dev_tools) { dev_tools->LogBackgroundServiceEvent( - registration_id_for_logs_, sw_origin_for_logs_, + registration_id_for_logs_, blink::StorageKey(sw_origin_for_logs_), content::DevToolsBackgroundService::kPaymentHandler, "Change shipping option", /*instance_id=*/payment_request_id_for_logs_, @@ -283,7 +284,7 @@ shipping_address_map.emplace("Phone", shipping_address->phone); dev_tools->LogBackgroundServiceEvent( - registration_id_for_logs_, sw_origin_for_logs_, + registration_id_for_logs_, blink::StorageKey(sw_origin_for_logs_), content::DevToolsBackgroundService::kPaymentHandler, "Change shipping address", /*instance_id=*/payment_request_id_for_logs_, shipping_address_map);
diff --git a/components/performance_manager/v8_memory/v8_detailed_memory_decorator.cc b/components/performance_manager/v8_memory/v8_detailed_memory_decorator.cc index e5f6191a..ddf6e86 100644 --- a/components/performance_manager/v8_memory/v8_detailed_memory_decorator.cc +++ b/components/performance_manager/v8_memory/v8_detailed_memory_decorator.cc
@@ -15,6 +15,8 @@ #include "base/containers/flat_map.h" #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" +#include "base/metrics/histogram_functions.h" +#include "base/strings/strcat.h" #include "base/timer/timer.h" #include "base/values.h" #include "components/performance_manager/public/execution_context/execution_context.h" @@ -93,6 +95,19 @@ using MeasurementMode = V8DetailedMemoryRequest::MeasurementMode; +// Measurement modes for logging to histograms. Use this for logging instead of +// `MeasurementMode` so that the public API can be updated without breaking +// histogram compatibility. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +enum class V8DetailedMemoryMeasurementMode { + kBounded = 0, + kLazy = 1, + kEagerForTesting = 2, + kMaxValue = kEagerForTesting, +}; + // Forwards the pending receiver to the RenderProcessHost and binds it on the // UI thread. void BindReceiverOnUIThread( @@ -269,9 +284,24 @@ const ProcessNode* process_node); private: - void StartMeasurement(MeasurementMode mode); + // Sends a measurement request to the renderer process. `is_global_request` is + // true if this measurement request came from the global request queue (so a + // copy if it will be sent to all renderers). + void StartMeasurement(MeasurementMode mode, bool is_global_request); + + // Schedules a call to UpgradeToBoundedMeasurementIfNeeded() at the point + // when the next measurement with mode kBounded would start, to ensure that + // kBounded requests can be scheduled while kLazy requests are running. void ScheduleUpgradeToBoundedMeasurement(); - void UpgradeToBoundedMeasurementIfNeeded(MeasurementMode bounded_mode); + + // If a measurement with mode kLazy is in progress, calls StartMeasurement() + // with mode `bounded_mode` to override it. Otherwise do nothing to let + // ScheduleNextMeasurement() start the bounded measurement. + // `is_global_request` is true if the bounded measurement request came from + // the global request queue (so a copy if it will be sent to all renderers). + void UpgradeToBoundedMeasurementIfNeeded(MeasurementMode bounded_mode, + bool is_global_request); + void EnsureRemote(); void OnV8MemoryUsage(blink::mojom::PerProcessV8MemoryUsagePtr result); @@ -360,14 +390,16 @@ // Find the next request for this process, checking both the per-process // queue and the global queue. - const V8DetailedMemoryRequest* next_request = + const V8DetailedMemoryRequest* next_process_request = process_measurement_requests_.GetNextRequest(); + const V8DetailedMemoryRequest* next_global_request = nullptr; auto* decorator = V8DetailedMemoryDecorator::GetFromGraph(process_node_->GetGraph()); if (decorator) { - next_request = - ChooseHigherPriorityRequest(next_request, decorator->GetNextRequest()); + next_global_request = decorator->GetNextRequest(); } + const V8DetailedMemoryRequest* next_request = + ChooseHigherPriorityRequest(next_process_request, next_global_request); if (!next_request) { // All measurements have been cancelled, or decorator was removed from @@ -382,7 +414,7 @@ state_ = State::kWaiting; if (last_request_time_.is_null()) { // This is the first measurement. Perform it immediately. - StartMeasurement(next_request->mode()); + StartMeasurement(next_request->mode(), next_request == next_global_request); return; } @@ -391,10 +423,12 @@ request_timer_.Start( FROM_HERE, next_request_time - base::TimeTicks::Now(), base::BindOnce(&NodeAttachedProcessData::StartMeasurement, - base::Unretained(this), next_request->mode())); + base::Unretained(this), next_request->mode(), + next_request == next_global_request)); } -void NodeAttachedProcessData::StartMeasurement(MeasurementMode mode) { +void NodeAttachedProcessData::StartMeasurement(MeasurementMode mode, + bool is_global_request) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (IsMeasurementBounded(mode)) { DCHECK(state_ == State::kWaiting || state_ == State::kMeasuringLazy); @@ -418,35 +452,46 @@ // NodeAttachedProcessData when the last V8DetailedMemoryRequest is deleted, // which could happen at any time. blink::mojom::V8DetailedMemoryReporter::Mode mojo_mode; + V8DetailedMemoryMeasurementMode metrics_mode; switch (mode) { case MeasurementMode::kLazy: mojo_mode = blink::mojom::V8DetailedMemoryReporter::Mode::LAZY; + metrics_mode = V8DetailedMemoryMeasurementMode::kLazy; break; case MeasurementMode::kBounded: mojo_mode = blink::mojom::V8DetailedMemoryReporter::Mode::DEFAULT; + metrics_mode = V8DetailedMemoryMeasurementMode::kBounded; break; case MeasurementMode::kEagerForTesting: mojo_mode = blink::mojom::V8DetailedMemoryReporter::Mode::EAGER; + metrics_mode = V8DetailedMemoryMeasurementMode::kEagerForTesting; break; } resource_usage_reporter_->GetV8MemoryUsage( mojo_mode, base::BindOnce(&NodeAttachedProcessData::OnV8MemoryUsage, weak_factory_.GetWeakPtr())); + base::UmaHistogramEnumeration( + base::StrCat({"PerformanceManager.V8DetailedMemory.", + is_global_request ? "AllRenderers" : "SingleRenderer", + ".MeasurementMode"}), + metrics_mode); } void NodeAttachedProcessData::ScheduleUpgradeToBoundedMeasurement() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_EQ(state_, State::kMeasuringLazy); - const V8DetailedMemoryRequest* bounded_request = + const V8DetailedMemoryRequest* process_bounded_request = process_measurement_requests_.GetNextBoundedRequest(); + const V8DetailedMemoryRequest* global_bounded_request = nullptr; auto* decorator = V8DetailedMemoryDecorator::GetFromGraph(process_node_->GetGraph()); if (decorator) { - bounded_request = ChooseHigherPriorityRequest( - bounded_request, decorator->GetNextBoundedRequest()); + global_bounded_request = decorator->GetNextBoundedRequest(); } + const V8DetailedMemoryRequest* bounded_request = ChooseHigherPriorityRequest( + process_bounded_request, global_bounded_request); if (!bounded_request) { // All measurements have been cancelled, or decorator was removed from // graph. @@ -459,18 +504,20 @@ FROM_HERE, bounded_request_time - base::TimeTicks::Now(), base::BindOnce( &NodeAttachedProcessData::UpgradeToBoundedMeasurementIfNeeded, - base::Unretained(this), bounded_request->mode())); + base::Unretained(this), bounded_request->mode(), + bounded_request == global_bounded_request)); } void NodeAttachedProcessData::UpgradeToBoundedMeasurementIfNeeded( - MeasurementMode bounded_mode) { + MeasurementMode bounded_mode, + bool is_global_request) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (state_ != State::kMeasuringLazy) { // State changed before timer expired. return; } DCHECK(IsMeasurementBounded(bounded_mode)); - StartMeasurement(bounded_mode); + StartMeasurement(bounded_mode, is_global_request); } void NodeAttachedProcessData::OnV8MemoryUsage(
diff --git a/components/permissions/permission_manager_unittest.cc b/components/permissions/permission_manager_unittest.cc index 0c7f778..47253f2b3 100644 --- a/components/permissions/permission_manager_unittest.cc +++ b/components/permissions/permission_manager_unittest.cc
@@ -35,10 +35,6 @@ #include "third_party/blink/public/mojom/permissions_policy/permissions_policy.mojom.h" #include "url/origin.h" -#if BUILDFLAG(IS_ANDROID) -#include "base/android/build_info.h" -#endif // BUILDFLAG(IS_ANDROID) - using blink::PermissionType; using blink::mojom::PermissionsPolicyFeature; using blink::mojom::PermissionStatus; @@ -74,23 +70,6 @@ raw_ptr<content::ContentBrowserClient> old_client_; }; -#if BUILDFLAG(IS_ANDROID) -// See https://crbug.com/904883. -auto GetDefaultProtectedMediaIdentifierPermissionStatus() { - return base::android::BuildInfo::GetInstance()->sdk_int() >= - base::android::SDK_VERSION_MARSHMALLOW - ? PermissionStatus::GRANTED - : PermissionStatus::ASK; -} - -auto GetDefaultProtectedMediaIdentifierContentSetting() { - return base::android::BuildInfo::GetInstance()->sdk_int() >= - base::android::SDK_VERSION_MARSHMALLOW - ? PermissionStatus::GRANTED - : PermissionStatus::ASK; -} -#endif // BUILDFLAG(IS_ANDROID) - } // namespace class PermissionManagerTest : public content::RenderViewHostTestHarness { @@ -341,7 +320,7 @@ CheckPermissionStatus(PermissionType::GEOLOCATION, PermissionStatus::ASK); #if BUILDFLAG(IS_ANDROID) CheckPermissionStatus(PermissionType::PROTECTED_MEDIA_IDENTIFIER, - GetDefaultProtectedMediaIdentifierPermissionStatus()); + PermissionStatus::GRANTED); CheckPermissionStatus(PermissionType::WINDOW_MANAGEMENT, PermissionStatus::DENIED); #else @@ -386,7 +365,7 @@ content::PermissionStatusSource::UNSPECIFIED); #if BUILDFLAG(IS_ANDROID) CheckPermissionResult(PermissionType::PROTECTED_MEDIA_IDENTIFIER, - GetDefaultProtectedMediaIdentifierContentSetting(), + PermissionStatus::GRANTED, content::PermissionStatusSource::UNSPECIFIED); #endif }
diff --git a/components/permissions/permission_request.cc b/components/permissions/permission_request.cc index 3dd1c0e..fbcb731 100644 --- a/components/permissions/permission_request.cc +++ b/components/permissions/permission_request.cc
@@ -13,10 +13,6 @@ #include "components/url_formatter/elide_url.h" #include "ui/base/l10n/l10n_util.h" -#if BUILDFLAG(IS_ANDROID) -#include "media/base/android/media_drm_bridge.h" -#endif - namespace permissions { PermissionRequest::PermissionRequest(
diff --git a/components/policy/resources/templates/policy_definitions/DeviceUpdate/DeviceRollbackToTargetVersion.yaml b/components/policy/resources/templates/policy_definitions/DeviceUpdate/DeviceRollbackToTargetVersion.yaml index b601d41..924d98b 100644 --- a/components/policy/resources/templates/policy_definitions/DeviceUpdate/DeviceRollbackToTargetVersion.yaml +++ b/components/policy/resources/templates/policy_definitions/DeviceUpdate/DeviceRollbackToTargetVersion.yaml
@@ -13,7 +13,7 @@ value: 1 - caption: |- Roll back device to target version if current OS version is newer than target. The device is powerwashed but device-wide network configurations without certificates are preserved and it automatically re-enrolls. - Supported on rollback to <ph name="PRODUCT_OS_NAME">$2<ex>Google ChromeOS</ex></ph> version 106 and higher. For older clients, the preservation of networks may not work and the device will not automatically re-enroll. + Rollback to <ph name="PRODUCT_OS_NAME">$2<ex>Google ChromeOS</ex></ph> version 106 or earlier is not supported. name: RollbackAndRestoreIfPossible value: 3 owners:
diff --git a/components/reading_list/core/reading_list_sync_bridge.cc b/components/reading_list/core/reading_list_sync_bridge.cc index c00773a..d0195fde 100644 --- a/components/reading_list/core/reading_list_sync_bridge.cc +++ b/components/reading_list/core/reading_list_sync_bridge.cc
@@ -148,14 +148,13 @@ loaded_entries.emplace(url, std::move(*entry)); } - delegate_->StoreLoaded(std::move(loaded_entries)); - - store_->ReadAllMetadata( - base::BindOnce(&ReadingListSyncBridge::OnReadAllMetadata, - weak_ptr_factory_.GetWeakPtr())); + store_->ReadAllMetadata(base::BindOnce( + &ReadingListSyncBridge::OnReadAllMetadata, weak_ptr_factory_.GetWeakPtr(), + std::move(loaded_entries))); } void ReadingListSyncBridge::OnReadAllMetadata( + ReadingListSyncBridgeDelegate::ReadingListEntries loaded_entries, const absl::optional<syncer::ModelError>& error, std::unique_ptr<syncer::MetadataBatch> metadata_batch) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -164,6 +163,8 @@ } else { change_processor()->ModelReadyToSync(std::move(metadata_batch)); } + + delegate_->StoreLoaded(std::move(loaded_entries)); } void ReadingListSyncBridge::OnDatabaseSave(
diff --git a/components/reading_list/core/reading_list_sync_bridge.h b/components/reading_list/core/reading_list_sync_bridge.h index d4998036..484355c 100644 --- a/components/reading_list/core/reading_list_sync_bridge.h +++ b/components/reading_list/core/reading_list_sync_bridge.h
@@ -160,8 +160,10 @@ const absl::optional<syncer::ModelError>& error, std::unique_ptr<syncer::ModelTypeStore::RecordList> entries); void OnDatabaseSave(const absl::optional<syncer::ModelError>& error); - void OnReadAllMetadata(const absl::optional<syncer::ModelError>& error, - std::unique_ptr<syncer::MetadataBatch> metadata_batch); + void OnReadAllMetadata( + ReadingListSyncBridgeDelegate::ReadingListEntries loaded_entries, + const absl::optional<syncer::ModelError>& error, + std::unique_ptr<syncer::MetadataBatch> metadata_batch); void AddEntryToBatch(syncer::MutableDataBatch* batch, const ReadingListEntry& entry);
diff --git a/components/reading_list/core/reading_list_sync_bridge_unittest.cc b/components/reading_list/core/reading_list_sync_bridge_unittest.cc index ae794fc..a057470 100644 --- a/components/reading_list/core/reading_list_sync_bridge_unittest.cc +++ b/components/reading_list/core/reading_list_sync_bridge_unittest.cc
@@ -44,6 +44,17 @@ return true; } +MATCHER_P2(MatchesEntry, url_matcher, is_read_matcher, "") { + if (!arg) { + *result_listener << "which is null"; + return false; + } + return testing::SafeMatcherCast<GURL>(url_matcher) + .MatchAndExplain(arg->URL(), result_listener) && + testing::SafeMatcherCast<bool>(is_read_matcher) + .MatchAndExplain(arg->IsRead(), result_listener); +} + // Tests that the transition from |entryA| to |entryB| is possible (|possible| // is true) or not. void ExpectAB(const sync_pb::ReadingListSpecifics& entryA, @@ -78,88 +89,71 @@ return clock->Now(); } -} // namespace - -class FakeModelTypeChangeProcessorObserver { +class MockReadingListSyncBridgeDelegate : public ReadingListSyncBridgeDelegate { public: - virtual void Put(const std::string& client_tag, - std::unique_ptr<syncer::EntityData> entity_data, - syncer::MetadataChangeList* metadata_change_list) = 0; + MockReadingListSyncBridgeDelegate() = default; + ~MockReadingListSyncBridgeDelegate() override = default; - virtual void Delete(const std::string& client_tag, - syncer::MetadataChangeList* metadata_change_list) = 0; + MOCK_METHOD(void, StoreLoaded, (ReadingListEntries), (override)); + MOCK_METHOD(void, + SyncAddEntry, + (std::unique_ptr<ReadingListEntry>), + (override)); + MOCK_METHOD(ReadingListEntry*, + SyncMergeEntry, + (std::unique_ptr<ReadingListEntry>), + (override)); + MOCK_METHOD(void, SyncRemoveEntry, (const GURL& url), (override)); }; -class ReadingListSyncBridgeTest : public testing::Test, - public ReadingListSyncBridgeDelegate { +} // namespace + +// This test doesn't use the test fixture to intercept and verify early calls +// during loading. +TEST(ReadingListSyncBridgeLoadTest, Load) { + base::SimpleTestClock clock; + testing::NiceMock<syncer::MockModelTypeChangeProcessor> processor; + testing::NiceMock<MockReadingListSyncBridgeDelegate> delegate; + base::test::SingleThreadTaskEnvironment task_environment; + + auto bridge = std::make_unique<ReadingListSyncBridge>( + syncer::ModelTypeStoreTestUtil::MoveStoreToFactory( + syncer::ModelTypeStoreTestUtil::CreateInMemoryStoreForTest()), + processor.CreateForwardingProcessor()); + auto model = std::make_unique<ReadingListModelImpl>(nullptr, nullptr, &clock); + + // StoreLoaded() should be invoked after ModelReadyToSync(). + testing::InSequence seq; + EXPECT_CALL(processor, ModelReadyToSync); + EXPECT_CALL(delegate, StoreLoaded); + + bridge->SetReadingListModel(model.get(), &delegate, &clock); + base::RunLoop().RunUntilIdle(); +} + +class ReadingListSyncBridgeTest : public testing::Test { protected: - ReadingListSyncBridgeTest() - : store_(syncer::ModelTypeStoreTestUtil::CreateInMemoryStoreForTest()) { + ReadingListSyncBridgeTest() { ON_CALL(processor_, IsTrackingMetadata()) .WillByDefault(testing::Return(true)); - ClearState(); reading_list_sync_bridge_ = std::make_unique<ReadingListSyncBridge>( - syncer::ModelTypeStoreTestUtil::MoveStoreToFactory(std::move(store_)), + syncer::ModelTypeStoreTestUtil::MoveStoreToFactory( + syncer::ModelTypeStoreTestUtil::CreateInMemoryStoreForTest()), processor_.CreateForwardingProcessor()); model_ = std::make_unique<ReadingListModelImpl>(nullptr, nullptr, &clock_); - reading_list_sync_bridge_->SetReadingListModel(model_.get(), this, &clock_); - + reading_list_sync_bridge_->SetReadingListModel(model_.get(), &delegate_, + &clock_); base::RunLoop().RunUntilIdle(); } - void AssertCounts(int sync_add_called, - int sync_remove_called, - int sync_merge_called) { - EXPECT_EQ(sync_add_called, sync_add_called_); - EXPECT_EQ(sync_remove_called, sync_remove_called_); - EXPECT_EQ(sync_merge_called, sync_merge_called_); - } - - void ClearState() { - sync_add_called_ = 0; - sync_remove_called_ = 0; - sync_merge_called_ = 0; - sync_added_.clear(); - sync_removed_.clear(); - sync_merged_.clear(); - } - - // These methods handle callbacks from a ReadingListSyncBridge. - void StoreLoaded(ReadingListEntries entries) override {} - - // Handle sync events. - void SyncAddEntry(std::unique_ptr<ReadingListEntry> entry) override { - sync_add_called_++; - sync_added_[entry->URL().spec()] = entry->IsRead(); - } - - void SyncRemoveEntry(const GURL& gurl) override { - sync_remove_called_++; - sync_removed_.insert(gurl.spec()); - } - - ReadingListEntry* SyncMergeEntry( - std::unique_ptr<ReadingListEntry> entry) override { - sync_merge_called_++; - sync_merged_[entry->URL().spec()] = entry->IsRead(); - return model_->SyncMergeEntry(std::move(entry)); - } - // In memory model type store needs to be able to post tasks. base::test::SingleThreadTaskEnvironment task_environment_; testing::NiceMock<syncer::MockModelTypeChangeProcessor> processor_; - std::unique_ptr<syncer::ModelTypeStore> store_; + testing::NiceMock<MockReadingListSyncBridgeDelegate> delegate_; std::unique_ptr<ReadingListModelImpl> model_; base::SimpleTestClock clock_; std::unique_ptr<ReadingListSyncBridge> reading_list_sync_bridge_; - - int sync_add_called_; - int sync_remove_called_; - int sync_merge_called_; - std::map<std::string, bool> sync_added_; - std::set<std::string> sync_removed_; - std::map<std::string, bool> sync_merged_; }; TEST_F(ReadingListSyncBridgeTest, CheckEmpties) { @@ -167,6 +161,10 @@ } TEST_F(ReadingListSyncBridgeTest, SaveOneRead) { + EXPECT_CALL(delegate_, SyncAddEntry).Times(0); + EXPECT_CALL(delegate_, SyncMergeEntry).Times(0); + EXPECT_CALL(delegate_, SyncRemoveEntry).Times(0); + ReadingListEntry entry(GURL("http://read.example.com/"), "read title", AdvanceAndGetTime(&clock_)); entry.SetRead(true, AdvanceAndGetTime(&clock_)); @@ -177,10 +175,13 @@ sync_pb::ReadingListSpecifics::READ), _)); reading_list_sync_bridge_->SaveEntry(entry); - AssertCounts(0, 0, 0); } TEST_F(ReadingListSyncBridgeTest, SaveOneUnread) { + EXPECT_CALL(delegate_, SyncAddEntry).Times(0); + EXPECT_CALL(delegate_, SyncMergeEntry).Times(0); + EXPECT_CALL(delegate_, SyncRemoveEntry).Times(0); + ReadingListEntry entry(GURL("http://unread.example.com/"), "unread title", AdvanceAndGetTime(&clock_)); EXPECT_CALL(processor_, @@ -189,11 +190,15 @@ sync_pb::ReadingListSpecifics::UNSEEN), _)); reading_list_sync_bridge_->SaveEntry(entry); - AssertCounts(0, 0, 0); } TEST_F(ReadingListSyncBridgeTest, SyncMergeOneEntry) { EXPECT_CALL(processor_, Put(_, _, _)).Times(0); + EXPECT_CALL(delegate_, SyncMergeEntry).Times(0); + EXPECT_CALL(delegate_, SyncRemoveEntry).Times(0); + + EXPECT_CALL(delegate_, SyncAddEntry(MatchesEntry("http://read.example.com/", + /*is_read=*/true))); syncer::EntityChangeList remote_input; ReadingListEntry entry(GURL("http://read.example.com/"), "read title", @@ -212,14 +217,16 @@ reading_list_sync_bridge_->CreateMetadataChangeList()); auto error = reading_list_sync_bridge_->MergeSyncData( std::move(metadata_changes), std::move(remote_input)); - AssertCounts(1, 0, 0); - EXPECT_EQ(sync_added_.size(), 1u); - EXPECT_EQ(sync_added_.count("http://read.example.com/"), 1u); - EXPECT_EQ(sync_added_["http://read.example.com/"], true); + EXPECT_FALSE(error.has_value()); } TEST_F(ReadingListSyncBridgeTest, ApplySyncChangesOneAdd) { EXPECT_CALL(processor_, Put(_, _, _)).Times(0); + EXPECT_CALL(delegate_, SyncMergeEntry).Times(0); + EXPECT_CALL(delegate_, SyncRemoveEntry).Times(0); + + EXPECT_CALL(delegate_, SyncAddEntry(MatchesEntry("http://read.example.com/", + /*is_read=*/true))); ReadingListEntry entry(GURL("http://read.example.com/"), "read title", AdvanceAndGetTime(&clock_)); @@ -236,13 +243,21 @@ auto error = reading_list_sync_bridge_->ApplySyncChanges( reading_list_sync_bridge_->CreateMetadataChangeList(), std::move(add_changes)); - AssertCounts(1, 0, 0); - EXPECT_EQ(sync_added_.size(), 1u); - EXPECT_EQ(sync_added_.count("http://read.example.com/"), 1u); - EXPECT_EQ(sync_added_["http://read.example.com/"], true); + EXPECT_FALSE(error.has_value()); } TEST_F(ReadingListSyncBridgeTest, ApplySyncChangesOneMerge) { + EXPECT_CALL(delegate_, SyncAddEntry).Times(0); + EXPECT_CALL(delegate_, SyncRemoveEntry).Times(0); + + EXPECT_CALL(delegate_, SyncMergeEntry(MatchesEntry( + "http://unread.example.com/", /*is_read=*/true))) + .WillOnce([this](std::unique_ptr<ReadingListEntry> entry) { + // SyncMergeEntry() must return non-null so forward the call to the + // model. + return model_->SyncMergeEntry(std::move(entry)); + }); + AdvanceAndGetTime(&clock_); model_->AddEntry(GURL("http://unread.example.com/"), "unread title", reading_list::ADDED_VIA_CURRENT_APP); @@ -265,10 +280,7 @@ auto error = reading_list_sync_bridge_->ApplySyncChanges( reading_list_sync_bridge_->CreateMetadataChangeList(), std::move(add_changes)); - AssertCounts(0, 0, 1); - EXPECT_EQ(sync_merged_.size(), 1u); - EXPECT_EQ(sync_merged_.count("http://unread.example.com/"), 1u); - EXPECT_EQ(sync_merged_["http://unread.example.com/"], true); + EXPECT_FALSE(error.has_value()); } TEST_F(ReadingListSyncBridgeTest, ApplySyncChangesOneIgnored) { @@ -280,7 +292,6 @@ AdvanceAndGetTime(&clock_); model_->AddEntry(GURL("http://unread.example.com/"), "new unread title", reading_list::ADDED_VIA_CURRENT_APP); - AssertCounts(0, 0, 0); std::unique_ptr<sync_pb::ReadingListSpecifics> specifics = old_entry.AsReadingListSpecifics(); @@ -291,26 +302,39 @@ // triggering ping-pong between two syncing devices. EXPECT_CALL(processor_, Put(_, _, _)).Times(0); + EXPECT_CALL(delegate_, SyncAddEntry).Times(0); + EXPECT_CALL(delegate_, SyncRemoveEntry).Times(0); + + EXPECT_CALL(delegate_, + SyncMergeEntry(MatchesEntry("http://unread.example.com/", + /*is_read=*/_))) + .WillOnce([this](std::unique_ptr<ReadingListEntry> entry) { + // SyncMergeEntry() must return non-null so forward the call to the + // model. + return model_->SyncMergeEntry(std::move(entry)); + }); + syncer::EntityChangeList add_changes; add_changes.push_back(syncer::EntityChange::CreateAdd( "http://unread.example.com/", std::move(data))); auto error = reading_list_sync_bridge_->ApplySyncChanges( reading_list_sync_bridge_->CreateMetadataChangeList(), std::move(add_changes)); - AssertCounts(0, 0, 1); - EXPECT_EQ(sync_merged_.size(), 1u); } TEST_F(ReadingListSyncBridgeTest, ApplySyncChangesOneRemove) { + EXPECT_CALL(delegate_, SyncAddEntry).Times(0); + EXPECT_CALL(delegate_, SyncMergeEntry).Times(0); + + EXPECT_CALL(delegate_, SyncRemoveEntry(GURL("http://read.example.com/"))); + syncer::EntityChangeList delete_changes; delete_changes.push_back( syncer::EntityChange::CreateDelete("http://read.example.com/")); auto error = reading_list_sync_bridge_->ApplySyncChanges( reading_list_sync_bridge_->CreateMetadataChangeList(), std::move(delete_changes)); - AssertCounts(0, 1, 0); - EXPECT_EQ(sync_removed_.size(), 1u); - EXPECT_EQ(sync_removed_.count("http://read.example.com/"), 1u); + EXPECT_FALSE(error.has_value()); } TEST_F(ReadingListSyncBridgeTest, CompareEntriesForSync) {
diff --git a/components/resources/BUILD.gn b/components/resources/BUILD.gn index b22aedd8..1662bb37 100644 --- a/components/resources/BUILD.gn +++ b/components/resources/BUILD.gn
@@ -72,6 +72,7 @@ ] deps = [ + "//components/crash/core/browser/resources:build_ts", "//components/local_state:build", "//components/policy/resources/webui:html_wrapper_files", ]
diff --git a/components/resources/crash_resources.grdp b/components/resources/crash_resources.grdp index 91d8fcdf..e6fcc2e2 100644 --- a/components/resources/crash_resources.grdp +++ b/components/resources/crash_resources.grdp
@@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <grit-part> <include name="IDR_CRASH_CRASHES_HTML" file="../crash/core/browser/resources/crashes.html" preprocess="true" type="BINDATA" /> - <include name="IDR_CRASH_CRASHES_JS" file="../crash/core/browser/resources/crashes.js" preprocess="true" type="BINDATA" /> + <include name="IDR_CRASH_CRASHES_JS" file="${root_gen_dir}/components/crash/core/browser/resources/tsc/crashes.js" use_base_dir="false" type="BINDATA" /> <include name="IDR_CRASH_CRASHES_CSS" file="../crash/core/browser/resources/crashes.css" type="BINDATA" /> <include name="IDR_CRASH_SADTAB_SVG" file="sadtab.svg" type="BINDATA" /> </grit-part>
diff --git a/components/safe_browsing/content/browser/client_side_detection_service.cc b/components/safe_browsing/content/browser/client_side_detection_service.cc index cf337b28..f549ed86 100644 --- a/components/safe_browsing/content/browser/client_side_detection_service.cc +++ b/components/safe_browsing/content/browser/client_side_detection_service.cc
@@ -19,6 +19,7 @@ #include "base/strings/strcat.h" #include "base/task/single_thread_task_runner.h" #include "base/time/time.h" +#include "base/values.h" #include "components/prefs/pref_service.h" #include "components/safe_browsing/content/browser/client_side_detection_host.h" #include "components/safe_browsing/content/browser/client_side_phishing_model.h" @@ -390,10 +391,11 @@ if (!delegate_ || !delegate_->GetPrefs()) return; - base::ListValue time_list; + base::Value::List time_list; for (const base::Time& report_time : phishing_report_times_) time_list.Append(base::Value(report_time.ToDoubleT())); - delegate_->GetPrefs()->Set(prefs::kSafeBrowsingCsdPingTimestamps, time_list); + delegate_->GetPrefs()->SetList(prefs::kSafeBrowsingCsdPingTimestamps, + std::move(time_list)); } void ClientSideDetectionService::LoadPhishingReportTimesFromPrefs() {
diff --git a/components/safe_browsing/content/browser/triggers/trigger_throttler.cc b/components/safe_browsing/content/browser/triggers/trigger_throttler.cc index aa5a3e5..0bab6c4 100644 --- a/components/safe_browsing/content/browser/triggers/trigger_throttler.cc +++ b/components/safe_browsing/content/browser/triggers/trigger_throttler.cc
@@ -11,6 +11,7 @@ #include "base/strings/string_split.h" #include "base/time/default_clock.h" #include "base/time/time.h" +#include "base/values.h" #include "components/prefs/pref_service.h" #include "components/safe_browsing/core/common/features.h" #include "components/safe_browsing/core/common/safe_browsing_prefs.h" @@ -174,18 +175,19 @@ if (!local_state_prefs_) return; - base::DictionaryValue trigger_dict; + base::Value::Dict trigger_dict; for (const auto& trigger_item : trigger_events_) { - base::Value* pref_timestamps = trigger_dict.SetKey( - base::NumberToString(static_cast<int>(trigger_item.first)), - base::Value(base::Value::Type::LIST)); + base::Value::List timestamps; for (const base::Time timestamp : trigger_item.second) { - pref_timestamps->Append(base::Value(timestamp.ToDoubleT())); + timestamps.Append(timestamp.ToDoubleT()); } + + trigger_dict.Set(base::NumberToString(static_cast<int>(trigger_item.first)), + std::move(timestamps)); } - local_state_prefs_->Set(prefs::kSafeBrowsingTriggerEventTimestamps, - trigger_dict); + local_state_prefs_->SetDict(prefs::kSafeBrowsingTriggerEventTimestamps, + std::move(trigger_dict)); } size_t TriggerThrottler::GetDailyQuotaForTrigger(
diff --git a/components/safe_browsing/core/browser/verdict_cache_manager_unittest.cc b/components/safe_browsing/core/browser/verdict_cache_manager_unittest.cc index 174fb941..3e76d07 100644 --- a/components/safe_browsing/core/browser/verdict_cache_manager_unittest.cc +++ b/components/safe_browsing/core/browser/verdict_cache_manager_unittest.cc
@@ -21,6 +21,8 @@ namespace { +using testing::SizeIs; + class MockSafeBrowsingSyncObserver : public SafeBrowsingSyncObserver { public: MockSafeBrowsingSyncObserver() : SafeBrowsingSyncObserver() {} @@ -230,18 +232,18 @@ verdict.SerializeToString(&verdict_serialized); base::Base64Encode(verdict_serialized, &verdict_serialized); - auto cache_dictionary = std::make_unique<base::DictionaryValue>(); - auto* verdict_dictionary = - cache_dictionary->SetKey("2", base::Value(base::Value::Type::DICTIONARY)); - auto* verdict_entry = verdict_dictionary->SetKey( - "www.google.com/", base::Value(base::Value::Type::DICTIONARY)); - verdict_entry->SetStringKey("cache_creation_time", "invalid_time"); - verdict_entry->SetStringKey("verdict_proto", verdict_serialized); + base::Value::Dict verdict_entry; + verdict_entry.Set("cache_creation_time", "invalid_time"); + verdict_entry.Set("verdict_proto", std::move(verdict_serialized)); + base::Value::Dict verdict_dictionary; + verdict_dictionary.Set("www.google.com/", std::move(verdict_entry)); + base::Value::Dict cache_dictionary; + cache_dictionary.Set("2", std::move(verdict_dictionary)); content_setting_map_->SetWebsiteSettingDefaultScope( GURL("http://www.google.com/"), GURL(), ContentSettingsType::PASSWORD_PROTECTION, - base::Value::FromUniquePtrValue(std::move(cache_dictionary))); + base::Value(std::move(cache_dictionary))); ReusedPasswordAccountType password_type; password_type.set_account_type(ReusedPasswordAccountType::GSUITE); @@ -481,18 +483,18 @@ verdict.SerializeToString(&verdict_serialized); base::Base64Encode(verdict_serialized, &verdict_serialized); - auto cache_dictionary = std::make_unique<base::DictionaryValue>(); - auto* verdict_dictionary = - cache_dictionary->SetKey("1", base::Value(base::Value::Type::DICTIONARY)); - auto* verdict_entry = verdict_dictionary->SetKey( - "www.google.com/path", base::Value(base::Value::Type::DICTIONARY)); - verdict_entry->SetStringKey("cache_creation_time", "invalid_time"); - verdict_entry->SetStringKey("verdict_proto", verdict_serialized); + base::Value::Dict verdict_entry; + verdict_entry.Set("cache_creation_time", "invalid_time"); + verdict_entry.Set("verdict_proto", std::move(verdict_serialized)); + base::Value::Dict verdict_dictionary; + verdict_dictionary.Set("www.google.com/path", std::move(verdict_entry)); + base::Value::Dict cache_dictionary; + cache_dictionary.Set("1", std::move(verdict_dictionary)); content_setting_map_->SetWebsiteSettingDefaultScope( GURL("http://www.google.com/"), GURL(), ContentSettingsType::PASSWORD_PROTECTION, - base::Value::FromUniquePtrValue(std::move(cache_dictionary))); + base::Value(std::move(cache_dictionary))); ReusedPasswordAccountType password_type; password_type.set_account_type(ReusedPasswordAccountType::GSUITE); @@ -502,22 +504,22 @@ "www.google.com/", base::Time::Now()); // Verify we saved two entries under PasswordType PRIMARY_ACCOUNT_PASSWORD - EXPECT_EQ(2U, content_setting_map_ - ->GetWebsiteSetting( - GURL("http://www.google.com/"), GURL(), - ContentSettingsType::PASSWORD_PROTECTION, nullptr) - .FindDictKey("1") - ->DictSize()); + base::Value setting_entry = content_setting_map_->GetWebsiteSetting( + GURL("http://www.google.com/"), GURL(), + ContentSettingsType::PASSWORD_PROTECTION, nullptr); + const base::Value::Dict* setting_dict = setting_entry.GetIfDict(); + ASSERT_TRUE(setting_dict); + EXPECT_THAT(*setting_dict->FindDict("1"), SizeIs(2u)); cache_manager_->CleanUpExpiredVerdicts(); // One should have been cleaned up - EXPECT_EQ(1U, content_setting_map_ - ->GetWebsiteSetting( - GURL("http://www.google.com/"), GURL(), - ContentSettingsType::PASSWORD_PROTECTION, nullptr) - .FindDictKey("1") - ->DictSize()); + setting_entry = content_setting_map_->GetWebsiteSetting( + GURL("http://www.google.com/"), GURL(), + ContentSettingsType::PASSWORD_PROTECTION, nullptr); + ASSERT_TRUE(setting_entry.is_dict()); + setting_dict = setting_entry.GetIfDict(); + EXPECT_THAT(*setting_dict->FindDict("1"), SizeIs(1u)); } TEST_F(VerdictCacheManagerTest, TestCanRetrieveCachedRealTimeUrlCheckVerdict) {
diff --git a/components/safe_browsing/core/common/safe_browsing_prefs_unittest.cc b/components/safe_browsing/core/common/safe_browsing_prefs_unittest.cc index fe3da0d..139d06b 100644 --- a/components/safe_browsing/core/common/safe_browsing_prefs_unittest.cc +++ b/components/safe_browsing/core/common/safe_browsing_prefs_unittest.cc
@@ -8,6 +8,7 @@ #include "base/strings/string_piece.h" #include "base/strings/string_util.h" #include "base/test/scoped_feature_list.h" +#include "base/values.h" #include "build/build_config.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/testing_pref_service.h" @@ -71,14 +72,14 @@ EXPECT_FALSE(prefs_.HasPrefPath(prefs::kPasswordProtectionLoginURLs)); EXPECT_FALSE(MatchesPasswordProtectionLoginURL(url, prefs_)); - base::ListValue login_urls; + base::Value::List login_urls; login_urls.Append("https://otherdomain.com/login.html"); - prefs_.Set(prefs::kPasswordProtectionLoginURLs, login_urls); + prefs_.SetList(prefs::kPasswordProtectionLoginURLs, login_urls.Clone()); EXPECT_TRUE(prefs_.HasPrefPath(prefs::kPasswordProtectionLoginURLs)); EXPECT_FALSE(MatchesPasswordProtectionLoginURL(url, prefs_)); login_urls.Append("https://mydomain.com/login.html"); - prefs_.Set(prefs::kPasswordProtectionLoginURLs, login_urls); + prefs_.SetList(prefs::kPasswordProtectionLoginURLs, std::move(login_urls)); EXPECT_TRUE(prefs_.HasPrefPath(prefs::kPasswordProtectionLoginURLs)); EXPECT_TRUE(MatchesPasswordProtectionLoginURL(url, prefs_)); } @@ -151,9 +152,10 @@ GURL target_url("https://www.foo.com"); EXPECT_FALSE(prefs_.HasPrefPath(prefs::kSafeBrowsingAllowlistDomains)); - base::ListValue allowlisted_domains; + base::Value::List allowlisted_domains; allowlisted_domains.Append("foo.com"); - prefs_.Set(prefs::kSafeBrowsingAllowlistDomains, allowlisted_domains); + prefs_.SetList(prefs::kSafeBrowsingAllowlistDomains, + std::move(allowlisted_domains)); StringListPrefMember string_list_pref; string_list_pref.Init(prefs::kSafeBrowsingAllowlistDomains, &prefs_); EXPECT_TRUE(IsURLAllowlistedByPolicy(target_url, prefs_));
diff --git a/components/segmentation_platform/internal/database/segment_info_database.cc b/components/segmentation_platform/internal/database/segment_info_database.cc index c758c29..ed01ce3b 100644 --- a/components/segmentation_platform/internal/database/segment_info_database.cc +++ b/components/segmentation_platform/internal/database/segment_info_database.cc
@@ -133,6 +133,33 @@ std::move(keys_to_delete), std::move(callback)); } +void SegmentInfoDatabase::UpdateMultipleSegments( + const SegmentInfoList& segments_to_update, + const std::vector<proto::SegmentId>& segments_to_delete, + SuccessCallback callback) { + auto entries_to_save = std::make_unique< + std::vector<std::pair<std::string, proto::SegmentInfo>>>(); + auto entries_to_delete = std::make_unique<std::vector<std::string>>(); + for (auto& segment : segments_to_update) { + const proto::SegmentId segment_id = segment.first; + auto& segment_info = segment.second; + + // Updating the cache. + cache_->UpdateSegmentInfo(segment_id, absl::make_optional(segment_info)); + + // Determining entries to save for database. + entries_to_save->emplace_back( + std::make_pair(ToString(segment_id), std::move(segment_info))); + } + + for (auto& segment_id : segments_to_delete) { + entries_to_delete->emplace_back(ToString(segment_id)); + } + + database_->UpdateEntries(std::move(entries_to_save), + std::move(entries_to_delete), std::move(callback)); +} + void SegmentInfoDatabase::SaveSegmentResult( SegmentId segment_id, absl::optional<proto::PredictionResult> result,
diff --git a/components/segmentation_platform/internal/database/segment_info_database.h b/components/segmentation_platform/internal/database/segment_info_database.h index 04a59d4..4471cdc 100644 --- a/components/segmentation_platform/internal/database/segment_info_database.h +++ b/components/segmentation_platform/internal/database/segment_info_database.h
@@ -64,6 +64,15 @@ absl::optional<proto::SegmentInfo> segment_info, SuccessCallback callback); + // Called to save or update metadata for multiple segments in a single + // database call. The previous data for all the provided segments is + // overwritten with new data. `segments_to_delete` includes list of + // segment ids to be deleted from the database. + virtual void UpdateMultipleSegments( + const SegmentInfoList& segments_to_update, + const std::vector<SegmentId>& segments_to_delete, + SuccessCallback callback); + // Called to write the model execution results for a given segment. It will // first read the currently stored result, and then overwrite it with // |result|. If |result| is null, the existing result will be deleted.
diff --git a/components/segmentation_platform/internal/database/segment_info_database_unittest.cc b/components/segmentation_platform/internal/database/segment_info_database_unittest.cc index d2fa4fc..5c6700b 100644 --- a/components/segmentation_platform/internal/database/segment_info_database_unittest.cc +++ b/components/segmentation_platform/internal/database/segment_info_database_unittest.cc
@@ -215,6 +215,55 @@ ExecuteAndVerifyGetSegmentInfoForSegments({kSegmentId, kSegmentId2}); } +TEST_P(SegmentInfoDatabaseTest, UpdateMultipleSegments) { + // Initialize DB with two entry. + db_entries_.insert( + std::make_pair(ToString(kSegmentId), CreateSegment(kSegmentId))); + db_entries_.insert( + std::make_pair(ToString(kSegmentId2), CreateSegment(kSegmentId2))); + SetUpDB(GetParam()); + + segment_db_->Initialize(base::DoNothing()); + db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK); + + // Delete both segments. + segment_db_->UpdateMultipleSegments({}, {kSegmentId, kSegmentId2}, + base::DoNothing()); + db_->UpdateCallback(true); + VerifyDb({}); + + // Insert multiple segments and verify. + std::vector<std::pair<SegmentId, proto::SegmentInfo>> segments_to_update; + segments_to_update.emplace_back( + std::make_pair(kSegmentId, CreateSegment(kSegmentId))); + segments_to_update.emplace_back( + std::make_pair(kSegmentId2, CreateSegment(kSegmentId2))); + segment_db_->UpdateMultipleSegments(segments_to_update, {}, + base::DoNothing()); + db_->UpdateCallback(true); + VerifyDb({kSegmentId, kSegmentId2}); + + // Update one of the existing segment and verify. + proto::SegmentInfo segment_info = CreateSegment(kSegmentId2); + segment_info.mutable_prediction_result()->add_result(0.9f); + // Add this entry to `segments_to_update`. + segments_to_update.clear(); + segments_to_update.emplace_back(std::make_pair(kSegmentId2, segment_info)); + // Call and Verify. + segment_db_->UpdateMultipleSegments(segments_to_update, {}, + base::DoNothing()); + db_->UpdateCallback(true); + VerifyDb({kSegmentId, kSegmentId2}); + VerifyResult(kSegmentId2, 0.9f); + + // Verify GetSegmentInfoForSegments. + ExecuteAndVerifyGetSegmentInfoForSegments({kSegmentId2}); + + ExecuteAndVerifyGetSegmentInfoForSegments({kSegmentId}); + + ExecuteAndVerifyGetSegmentInfoForSegments({kSegmentId, kSegmentId2}); +} + TEST_P(SegmentInfoDatabaseTest, WriteResult) { // Initialize DB with one entry. db_entries_.insert(
diff --git a/components/segmentation_platform/internal/proto/model_prediction.proto b/components/segmentation_platform/internal/proto/model_prediction.proto index fb457d8..a9e8d6e7 100644 --- a/components/segmentation_platform/internal/proto/model_prediction.proto +++ b/components/segmentation_platform/internal/proto/model_prediction.proto
@@ -8,38 +8,9 @@ package segmentation_platform.proto; import "components/segmentation_platform/public/proto/model_metadata.proto"; +import "components/segmentation_platform/public/proto/prediction_result.proto"; import "components/segmentation_platform/public/proto/segmentation_platform.proto"; -// Corresponds to a single output in the model result. -message LabeledResult { - // The label associated with the output. - optional string label = 1; - - // The score represented by the output. - optional float result = 2; -} - -// Result from the model evaluation for a given segment. -message PredictionResult { - // The result is the confidence rating from the model evaluation. - // This field will be deprecated going forward. - repeated float result = 1; - - // The time when the prediction was made, in terms of the number of - // microseconds since Windows epoch. - optional int64 timestamp_us = 2; - - // The result is the list of scores from the model evaluation. - // `labeled_results` is set once the model execution is completed and results - // are ready. The result are merged with appropriate `label` and set to this - // field. Each entry tells what the result(score) is. The OutputConfig tells - // us how to interpret it. - repeated LabeledResult labeled_results = 3; - - // The output config from the metadata. - optional OutputConfig output_config = 4; -} - // Partial training data set with only inputs, used when observation period has // not ended. message TrainingData {
diff --git a/components/segmentation_platform/public/proto/BUILD.gn b/components/segmentation_platform/public/proto/BUILD.gn index 8ea35016..48d3b6d 100644 --- a/components/segmentation_platform/public/proto/BUILD.gn +++ b/components/segmentation_platform/public/proto/BUILD.gn
@@ -13,6 +13,8 @@ sources = [ "aggregation.proto", "model_metadata.proto", + "output_config.proto", + "prediction_result.proto", "segmentation_platform.proto", "types.proto", ] @@ -21,6 +23,10 @@ if (is_android) { proto_java_library("segmentation_platform_proto_java") { proto_path = "//" - sources = [ "segmentation_platform.proto" ] + sources = [ + "output_config.proto", + "prediction_result.proto", + "segmentation_platform.proto", + ] } }
diff --git a/components/segmentation_platform/public/proto/model_metadata.proto b/components/segmentation_platform/public/proto/model_metadata.proto index 529ebcf0..bf72bc1 100644 --- a/components/segmentation_platform/public/proto/model_metadata.proto +++ b/components/segmentation_platform/public/proto/model_metadata.proto
@@ -8,6 +8,7 @@ package segmentation_platform.proto; import "components/segmentation_platform/public/proto/aggregation.proto"; +import "components/segmentation_platform/public/proto/output_config.proto"; import "components/segmentation_platform/public/proto/types.proto"; // The version is used to verify if the metadata provided by the server is @@ -283,42 +284,6 @@ optional uint64 duration = 2; } -// Defines what type of model is supplied. Results are based on which -// classifier the model is in. -message Classifier { - // A classifier to interpret model results as a boolean. - message BooleanClassifier { - // Limit to classify result as false/true. - optional float threshold = 1; - } - - // A classifier to interpret model results as one of multiple classes. Each - // output of the model corresponds to one of the classes. - message MultiClassClassifier { - // Number of top results the client is interested in. Must be less than - // or equal to the number of labels specified. - optional int64 top_k_outputs = 1; - } - - oneof ClassifierType { - // Model result is classified as boolean. - BooleanClassifier boolean_classifier = 2; - - // Model result is of multi-class type. - MultiClassClassifier multi_class_classifier = 3; - } -} - -// Specified by client in the metadata on how to interpret the model results. -message OutputConfig { - // Each `output_label` corresponds to one output. It signifies how to - // interpret the output. - repeated string output_label = 1; - - // Tells the return type of the result for model evaluation. - optional Classifier classifier = 2; -} - // Metadata about a segmentation model for a given segment. Contains information // on how to use the model such as collecting signals, interpreting results etc. // Next tag: 16
diff --git a/components/segmentation_platform/public/proto/output_config.proto b/components/segmentation_platform/public/proto/output_config.proto new file mode 100644 index 0000000..884dc8a --- /dev/null +++ b/components/segmentation_platform/public/proto/output_config.proto
@@ -0,0 +1,46 @@ +// Copyright 2021 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +syntax = "proto2"; +option optimize_for = LITE_RUNTIME; +option java_package = "org.chromium.components.segmentation_platform.proto"; +option java_outer_classname = "OutputConfigProto"; + +package segmentation_platform.proto; + +// Defines what type of model is supplied. Results are based on which +// classifier the model is in. +message Classifier { + // A classifier to interpret model results as a boolean. + message BooleanClassifier { + // Limit to classify result as false/true. + optional float threshold = 1; + } + + // A classifier to interpret model results as one of multiple classes. Each + // output of the model corresponds to one of the classes. + message MultiClassClassifier { + // Number of top results the client is interested in. Must be less than + // or equal to the number of labels specified. + optional int64 top_k_outputs = 1; + } + + oneof ClassifierType { + // Model result is classified as boolean. + BooleanClassifier boolean_classifier = 2; + + // Model result is of multi-class type. + MultiClassClassifier multi_class_classifier = 3; + } +} + +// Specified by client in the metadata on how to interpret the model results. +message OutputConfig { + // Each `output_label` corresponds to one output. It signifies how to + // interpret the output. + repeated string output_labels = 1; + + // Tells the return type of the result for model evaluation. + optional Classifier classifier = 2; +}
diff --git a/components/segmentation_platform/public/proto/prediction_result.proto b/components/segmentation_platform/public/proto/prediction_result.proto new file mode 100644 index 0000000..b73af96 --- /dev/null +++ b/components/segmentation_platform/public/proto/prediction_result.proto
@@ -0,0 +1,42 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +syntax = "proto2"; +option optimize_for = LITE_RUNTIME; +option java_package = "org.chromium.components.segmentation_platform.proto"; +option java_outer_classname = "PredictionResultProto"; + +package segmentation_platform.proto; + +import "components/segmentation_platform/public/proto/output_config.proto"; + +// Corresponds to a single output in the model result. +message LabeledResult { + // The label associated with the output. + optional string label = 1; + + // The score represented by the output. + optional float result = 2; +} + +// Result from the model evaluation for a given segment. +message PredictionResult { + // The result is the confidence rating from the model evaluation. + // This field will be deprecated going forward. + repeated float result = 1; + + // The time when the prediction was made, in terms of the number of + // microseconds since Windows epoch. + optional int64 timestamp_us = 2; + + // The result is the list of scores from the model evaluation. + // `labeled_results` is set once the model execution is completed and results + // are ready. The result are merged with appropriate `label` and set to this + // field. Each entry tells what the result(score) is. The OutputConfig tells + // us how to interpret it. + repeated LabeledResult labeled_results = 3; + + // The output config from the metadata. + optional OutputConfig output_config = 4; +}
diff --git a/components/services/screen_ai/proto/visual_annotator_proto_convertor.cc b/components/services/screen_ai/proto/visual_annotator_proto_convertor.cc index 621e80c..f64b9366 100644 --- a/components/services/screen_ai/proto/visual_annotator_proto_convertor.cc +++ b/components/services/screen_ai/proto/visual_annotator_proto_convertor.cc
@@ -399,11 +399,8 @@ return update; } - // TODO(https://crbug.com/1278249): After updating the service to explicitly - // use one of the OCR or Layout Extraction functions, remove this line and - // add a DCHECK that ensures either |lines| or |ui_components| exists. - if (visual_annotation.lines_size()) - visual_annotation.clear_ui_component(); + DCHECK(visual_annotation.lines_size() == 0 || + visual_annotation.ui_component_size() == 0); // TODO(https://crbug.com/1278249): Create an AXTreeSource and create the // update using AXTreeSerializer.
diff --git a/components/services/screen_ai/screen_ai_service_impl.cc b/components/services/screen_ai/screen_ai_service_impl.cc index d7b70c07..78b802b 100644 --- a/components/services/screen_ai/screen_ai_service_impl.cc +++ b/components/services/screen_ai/screen_ai_service_impl.cc
@@ -37,9 +37,11 @@ // numeric values should never be reused. enum class ScreenAILoadLibraryResult { kAllOk = 0, - kVisualAnnotationFailed = 1, + kDeprecatedVisualAnnotationFailed = 1, kMainContentExtractionFailed = 2, - kMaxValue = kMainContentExtractionFailed, + kLayoutExtractionFailed = 3, + kOcrFailed = 4, + kMaxValue = kOcrFailed, }; std::vector<char> LoadModelFile(base::File& model_file) { @@ -60,15 +62,35 @@ } NO_SANITIZE("cfi-icall") -bool CallInitVisualAnnotationsFunction(LibraryFunctions* library_functions, - const base::FilePath& models_folder) { +std::string CallGetLibraryVersionFunction(LibraryFunctions* library_functions) { DCHECK(library_functions); - DCHECK(library_functions->init_visual_annotation_); - return library_functions->init_visual_annotation_( + DCHECK(library_functions->get_library_version_); + + char* library_version; + library_functions->get_library_version_(library_version); + std::string version_string(library_version); + delete library_version; + return version_string; +} + +NO_SANITIZE("cfi-icall") +bool CallInitLayoutExtractionFunction(LibraryFunctions* library_functions, + const base::FilePath& models_folder) { + DCHECK(library_functions); + DCHECK(library_functions->init_layout_extraction_); + return library_functions->init_layout_extraction_( models_folder.MaybeAsASCII().c_str()); } NO_SANITIZE("cfi-icall") +bool CallInitOCRFunction(LibraryFunctions* library_functions, + const base::FilePath& models_folder) { + DCHECK(library_functions); + DCHECK(library_functions->init_ocr_); + return library_functions->init_ocr_(models_folder.MaybeAsASCII().c_str()); +} + +NO_SANITIZE("cfi-icall") bool CallInitMainContentExtractionFunction(LibraryFunctions* library_functions, base::File& model_config_file, base::File& model_tflite_file) { @@ -97,17 +119,28 @@ std::unique_ptr<LibraryFunctions> library_functions = std::make_unique<LibraryFunctions>(library_path); + VLOG(2) << "Screen AI library version: " + << CallGetLibraryVersionFunction(library_functions.get()); + if (features::IsScreenAIDebugModeEnabled()) CallEnableDebugMode(library_functions.get()); bool init_ok = true; - if (features::IsPdfOcrEnabled() || features::IsLayoutExtractionEnabled()) { - if (!CallInitVisualAnnotationsFunction(library_functions.get(), - library_path.DirName())) { + if (features::IsPdfOcrEnabled()) { + if (!CallInitOCRFunction(library_functions.get(), library_path.DirName())) { + init_ok = false; + base::UmaHistogramEnumeration("Accessibility.ScreenAI.LoadLibraryResult", + ScreenAILoadLibraryResult::kOcrFailed); + } + } + + if (init_ok && features::IsLayoutExtractionEnabled()) { + if (!CallInitLayoutExtractionFunction(library_functions.get(), + library_path.DirName())) { init_ok = false; base::UmaHistogramEnumeration( "Accessibility.ScreenAI.LoadLibraryResult", - ScreenAILoadLibraryResult::kVisualAnnotationFailed); + ScreenAILoadLibraryResult::kLayoutExtractionFailed); } } @@ -155,8 +188,9 @@ // Main Content Extraction functions. if (features::IsReadAnythingWithScreen2xEnabled()) { - init_main_content_extraction_ = reinterpret_cast<InitMainContentExtraction>( - library_.GetFunctionPointer("InitMainContentExtraction")); + init_main_content_extraction_ = + reinterpret_cast<InitMainContentExtractionFn>( + library_.GetFunctionPointer("InitMainContentExtraction")); DCHECK(init_main_content_extraction_); extract_main_content_ = reinterpret_cast<ExtractMainContent>( library_.GetFunctionPointer("ExtractMainContent")); @@ -166,17 +200,30 @@ extract_main_content_ = nullptr; } - // Visual Annotation functions. - if (features::IsPdfOcrEnabled() || features::IsLayoutExtractionEnabled()) { - init_visual_annotation_ = reinterpret_cast<InitVisualAnnotations>( - library_.GetFunctionPointer("InitVisualAnnotations")); - DCHECK(init_visual_annotation_); - annotate_ = - reinterpret_cast<Annotate>(library_.GetFunctionPointer("Annotate")); - DCHECK(annotate_); + // Layout Extraction. + if (features::IsLayoutExtractionEnabled()) { + init_layout_extraction_ = reinterpret_cast<InitLayoutExtractionFn>( + library_.GetFunctionPointer("InitLayoutExtraction")); + DCHECK(init_layout_extraction_); + extract_layout_ = reinterpret_cast<ExtractLayoutFn>( + library_.GetFunctionPointer("ExtractLayout")); + DCHECK(extract_layout_); } else { - init_visual_annotation_ = nullptr; - annotate_ = nullptr; + init_layout_extraction_ = nullptr; + extract_layout_ = nullptr; + } + + // OCR. + if (features::IsPdfOcrEnabled()) { + init_ocr_ = + reinterpret_cast<InitOCRFn>(library_.GetFunctionPointer("InitOCR")); + DCHECK(init_ocr_); + perform_ocr_ = reinterpret_cast<PerformOcrFn>( + library_.GetFunctionPointer("PerformOCR")); + DCHECK(perform_ocr_); + } else { + init_ocr_ = nullptr; + perform_ocr_ = nullptr; } } @@ -216,6 +263,8 @@ std::move(main_content_extractor)); } +// TODO(https://crbug.com/1278249): Update mojo interface to have different +// entry points for OCR and Layout Extraction requests and remove |Annotate|. void ScreenAIService::Annotate(const SkBitmap& image, const ui::AXTreeID& parent_tree_id, AnnotationCallback callback) { @@ -231,7 +280,7 @@ // binding the task. task_runner_->PostTaskAndReply( FROM_HERE, - base::BindOnce(&ScreenAIService::AnnotateInternal, + base::BindOnce(&ScreenAIService::OcrInternal, weak_ptr_factory_.GetWeakPtr(), std::move(image), std::move(parent_tree_id), base::Unretained(annotation_ptr)), @@ -251,19 +300,17 @@ std::move(annotation))); } -void ScreenAIService::AnnotateInternal(const SkBitmap& image, - const ui::AXTreeID& parent_tree_id, - ui::AXTreeUpdate* annotation) { +void ScreenAIService::OcrInternal(const SkBitmap& image, + const ui::AXTreeID& parent_tree_id, + ui::AXTreeUpdate* annotation) { DCHECK(screen_ai_annotator_client_.is_bound()); - VLOG(2) << "Screen AI library starting to process " << image.width() << "x" - << image.height() << " snapshot."; char* annotation_proto = nullptr; uint32_t annotation_proto_length = 0; // TODO(https://crbug.com/1278249): Consider adding a signature that // verifies the data integrity and source. - if (!CallLibraryAnnotateFunction(image, annotation_proto, - annotation_proto_length)) { + if (!CallLibraryOcrFunction(image, annotation_proto, + annotation_proto_length)) { DCHECK_EQ(annotation->tree_data.tree_id, ui::AXTreeIDUnknown()); VLOG(1) << "Screen AI library could not process snapshot."; return; @@ -288,14 +335,14 @@ } NO_SANITIZE("cfi-icall") -bool ScreenAIService::CallLibraryAnnotateFunction( +bool ScreenAIService::CallLibraryOcrFunction( const SkBitmap& image, char*& annotation_proto, uint32_t& annotation_proto_length) { DCHECK(library_functions_); - DCHECK(library_functions_->annotate_); - return library_functions_->annotate_(image, annotation_proto, - annotation_proto_length); + DCHECK(library_functions_->perform_ocr_); + return library_functions_->perform_ocr_(image, annotation_proto, + annotation_proto_length); } void ScreenAIService::ExtractMainContent(const ui::AXTreeUpdate& snapshot,
diff --git a/components/services/screen_ai/screen_ai_service_impl.h b/components/services/screen_ai/screen_ai_service_impl.h index 34d1f9f9..5872a147 100644 --- a/components/services/screen_ai/screen_ai_service_impl.h +++ b/components/services/screen_ai/screen_ai_service_impl.h
@@ -33,32 +33,52 @@ LibraryFunctions& operator=(const LibraryFunctions&) = delete; ~LibraryFunctions() = default; - // Initializes the pipeline for layout extraction and OCR. + // Initializes the pipeline for layout extraction. // |models_folder| is a null terminated string pointing to the - // folder that includes model files for layout extraction and OCR. + // folder that includes model files for layout extraction. // TODO(http://crbug.com/1278249): Replace |models_folder| with file // handle(s). - typedef bool (*InitVisualAnnotations)(const char* /*models_folder*/); - InitVisualAnnotations init_visual_annotation_ = nullptr; + typedef bool (*InitLayoutExtractionFn)(const char* /*models_folder*/); + InitLayoutExtractionFn init_layout_extraction_ = nullptr; - // Sends the given bitmap to ScreenAI pipeline and returns visual + // Sends the given bitmap to layout extraction pipeline and returns visual // annotations. The annotations will be returned as a serialized // VisualAnnotation proto. `serialized_visual_annotation` will be allocated // for the output and the ownership of the buffer will be passed to the // caller function. - typedef bool (*Annotate)(const SkBitmap& /*bitmap*/, - char*& /*serialized_visual_annotation*/, - uint32_t& /*serialized_visual_annotation_length*/); - Annotate annotate_ = nullptr; + typedef bool (*ExtractLayoutFn)( + const SkBitmap& /*bitmap*/, + char*& /*serialized_visual_annotation*/, + uint32_t& /*serialized_visual_annotation_length*/); + ExtractLayoutFn extract_layout_ = nullptr; + + // Initializes the pipeline for OCR. + // |models_folder| is a null terminated string pointing to the + // folder that includes model files for OCR. + // TODO(http://crbug.com/1278249): Replace |models_folder| with file + // handle(s). + typedef bool (*InitOCRFn)(const char* /*models_folder*/); + InitOCRFn init_ocr_ = nullptr; + + // Sends the given bitmap to the OCR pipeline and returns visual + // annotations. The annotations will be returned as a serialized + // VisualAnnotation proto. `serialized_visual_annotation` will be allocated + // for the output and the ownership of the buffer will be passed to the + // caller function. + typedef bool (*PerformOcrFn)( + const SkBitmap& /*bitmap*/, + char*& /*serialized_visual_annotation*/, + uint32_t& /*serialized_visual_annotation_length*/); + PerformOcrFn perform_ocr_ = nullptr; // Initializes the pipeline for main content extraction. // |model_config| and |model_tflite| pass content of the required files to // initialize Screen2x engine. - typedef bool (*InitMainContentExtraction)(const char* model_config, - uint32_t model_config_length, - const char* model_tflite, - uint32_t model_tflite_length); - InitMainContentExtraction init_main_content_extraction_ = nullptr; + typedef bool (*InitMainContentExtractionFn)(const char* model_config, + uint32_t model_config_length, + const char* model_tflite, + uint32_t model_tflite_length); + InitMainContentExtractionFn init_main_content_extraction_ = nullptr; // Passes the given accessibility tree proto to Screen2x pipeline and // returns the main content ids. The input is in form of a serialized @@ -131,16 +151,16 @@ main_content_extractor) override; // Wrapper functions for task scheduler. - void AnnotateInternal(const SkBitmap& image, - const ui::AXTreeID& parent_tree_id, - ui::AXTreeUpdate* annotation); + void OcrInternal(const SkBitmap& image, + const ui::AXTreeID& parent_tree_id, + ui::AXTreeUpdate* annotation); void ExtractMainContentInternal(const ui::AXTreeUpdate& snapshot, std::vector<int32_t>* content_node_ids); // Library function calls are isolated to have specific compiler directives. - bool CallLibraryAnnotateFunction(const SkBitmap& image, - char*& annotation_proto, - uint32_t& annotation_proto_length); + bool CallLibraryOcrFunction(const SkBitmap& image, + char*& annotation_proto, + uint32_t& annotation_proto_length); bool CallLibraryExtractMainContentFunction( const char* serialized_snapshot, const uint32_t serialized_snapshot_length,
diff --git a/components/viz/test/test_image_factory.cc b/components/viz/test/test_image_factory.cc index 3d407376..e43b5fc 100644 --- a/components/viz/test/test_image_factory.cc +++ b/components/viz/test/test_image_factory.cc
@@ -5,12 +5,82 @@ #include "components/viz/test/test_image_factory.h" #include <stddef.h> +#include <utility> +#include "base/logging.h" #include "base/numerics/safe_conversions.h" -#include "ui/gl/gl_image_shared_memory.h" +#include "base/numerics/safe_math.h" +#include "base/system/sys_info.h" +#include "ui/gfx/buffer_format_util.h" +#include "ui/gl/gl_image_memory.h" namespace viz { +namespace { + +class GLImageSharedMemory : public gl::GLImageMemory { + public: + explicit GLImageSharedMemory(const gfx::Size& size) + : gl::GLImageMemory(size) {} + + GLImageSharedMemory(const GLImageSharedMemory&) = delete; + GLImageSharedMemory& operator=(const GLImageSharedMemory&) = delete; + + bool Initialize(const base::UnsafeSharedMemoryRegion& region, + gfx::GenericSharedMemoryId shared_memory_id, + gfx::BufferFormat format, + size_t offset, + size_t stride) { + if (!region.IsValid()) + return false; + + if (gfx::NumberOfPlanesForLinearBufferFormat(format) != 1) + return false; + + base::CheckedNumeric<size_t> checked_size = stride; + checked_size *= GetSize().height(); + if (!checked_size.IsValid()) + return false; + + // Minimize the amount of address space we use but make sure offset is a + // multiple of page size as required by MapAt(). + size_t memory_offset = offset % base::SysInfo::VMAllocationGranularity(); + size_t map_offset = base::SysInfo::VMAllocationGranularity() * + (offset / base::SysInfo::VMAllocationGranularity()); + + checked_size += memory_offset; + if (!checked_size.IsValid()) + return false; + + auto shared_memory_mapping = + region.MapAt(static_cast<off_t>(map_offset), checked_size.ValueOrDie()); + if (!shared_memory_mapping.IsValid()) { + DVLOG(0) << "Failed to map shared memory."; + return false; + } + + if (!gl::GLImageMemory::Initialize( + static_cast<uint8_t*>(shared_memory_mapping.memory()) + + memory_offset, + format, stride)) { + return false; + } + + DCHECK(!shared_memory_mapping_.IsValid()); + shared_memory_mapping_ = std::move(shared_memory_mapping); + shared_memory_id_ = shared_memory_id; + return true; + } + + private: + ~GLImageSharedMemory() override = default; + + base::WritableSharedMemoryMapping shared_memory_mapping_; + gfx::GenericSharedMemoryId shared_memory_id_; +}; + +} // namespace + TestImageFactory::TestImageFactory() = default; TestImageFactory::~TestImageFactory() = default; @@ -24,7 +94,7 @@ int client_id, gpu::SurfaceHandle surface_handle) { DCHECK_EQ(handle.type, gfx::SHARED_MEMORY_BUFFER); - auto image = base::MakeRefCounted<gl::GLImageSharedMemory>(size); + auto image = base::MakeRefCounted<GLImageSharedMemory>(size); if (!image->Initialize(handle.region, handle.id, format, handle.offset, handle.stride)) return nullptr;
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 9264d7d0..b4da042 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -1480,6 +1480,8 @@ "preloading/prerender/prerender_navigation_throttle.h", "preloading/prerender/prerender_navigation_utils.cc", "preloading/prerender/prerender_navigation_utils.h", + "preloading/prerender/prerender_new_tab_handle.cc", + "preloading/prerender/prerender_new_tab_handle.h", "preloading/prerender/prerender_subframe_navigation_throttle.cc", "preloading/prerender/prerender_subframe_navigation_throttle.h", "preloading/prerenderer.cc", @@ -2321,6 +2323,8 @@ "font_service.cc", "font_service.h", "media/stable_video_decoder_factory.cc", + "media/video_encode_accelerator_provider_launcher.cc", + "media/video_encode_accelerator_provider_launcher.h", "memory/swap_metrics_driver_impl_linux.cc", "memory/swap_metrics_driver_impl_linux.h", "sandbox_host_linux.cc",
diff --git a/content/browser/aggregation_service/aggregation_service_test_utils.cc b/content/browser/aggregation_service/aggregation_service_test_utils.cc index 545ae7a..b849239d 100644 --- a/content/browser/aggregation_service/aggregation_service_test_utils.cc +++ b/content/browser/aggregation_service/aggregation_service_test_utils.cc
@@ -23,6 +23,7 @@ #include "base/strings/strcat.h" #include "base/task/thread_pool.h" #include "base/threading/sequence_bound.h" +#include "base/time/clock.h" #include "base/time/time.h" #include "base/values.h" #include "content/browser/aggregation_service/aggregatable_report.h"
diff --git a/content/browser/android/app_web_message_port.cc b/content/browser/android/app_web_message_port.cc index 128b774..6e0f959 100644 --- a/content/browser/android/app_web_message_port.cc +++ b/content/browser/android/app_web_message_port.cc
@@ -152,16 +152,17 @@ // Decode mojo message failed. return false; } + auto ports = std::move(transferable_message.ports); auto optional_payload = - blink::DecodeToWebMessagePayload(transferable_message); + blink::DecodeToWebMessagePayload(std::move(transferable_message)); if (!optional_payload) { // Unsupported or invalid payload. return true; } const auto& payload = optional_payload.value(); - auto j_ports = CreateJavaMessagePort( - blink::MessagePortChannel::ReleaseHandles(transferable_message.ports)); + auto j_ports = + CreateJavaMessagePort(blink::MessagePortChannel::ReleaseHandles(ports)); base::android::ScopedJavaLocalRef<jobject> j_message = ConvertWebMessagePayloadToJava(payload); DCHECK(j_message);
diff --git a/content/browser/android/message_payload.cc b/content/browser/android/message_payload.cc index 7623671..e2fc8cfe 100644 --- a/content/browser/android/message_payload.cc +++ b/content/browser/android/message_payload.cc
@@ -10,13 +10,47 @@ #include "base/android/jni_array.h" #include "base/android/jni_string.h" #include "base/android/scoped_java_ref.h" +#include "base/containers/span.h" #include "base/functional/overloaded.h" #include "base/notreached.h" #include "content/public/android/content_jni_headers/MessagePayloadJni_jni.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/abseil-cpp/absl/types/variant.h" #include "third_party/blink/public/common/messaging/string_message_codec.h" #include "third_party/blink/public/common/messaging/transferable_message.h" +namespace { + +// An ArrayBufferPayload impl for Browser (Java) to JavaScript message, the +// ArrayBuffer payload data is stored in a Java byte array. +class JavaArrayBuffer : public blink::WebMessageArrayBufferPayload { + public: + explicit JavaArrayBuffer(const base::android::JavaRef<jbyteArray>& array) + : length_(base::android::SafeGetArrayLength( + base::android::AttachCurrentThread(), + array)), + array_(array) {} + + size_t GetLength() const override { return length_; } + + // Due to JNI limitation, Java ByteArray cannot be converted into base::span + // trivially. + absl::optional<base::span<const uint8_t>> GetAsSpanIfPossible() + const override { + return absl::nullopt; + } + + void CopyInto(base::span<uint8_t> dest) const override { + base::android::JavaByteArrayToByteSpan(base::android::AttachCurrentThread(), + array_, dest); + } + + private: + size_t length_; + base::android::ScopedJavaGlobalRef<jbyteArray> array_; +}; +} // namespace + namespace content::android { base::android::ScopedJavaLocalRef<jobject> ConvertWebMessagePayloadToJava( @@ -28,12 +62,26 @@ return Java_MessagePayloadJni_createFromString( env, base::android::ConvertUTF16ToJavaString(env, str)); }, - [env](const std::vector<uint8_t>& array_buffer) { - return Java_MessagePayloadJni_createFromArrayBuffer( - env, base::android::ToJavaByteArray(env, array_buffer.data(), - array_buffer.size())); - }, - }, + [env](const std::unique_ptr<blink::WebMessageArrayBufferPayload>& + array_buffer) { + // Data is from renderer process, copy it first before use. + base::android::ScopedJavaLocalRef<jbyteArray> j_byte_array; + + auto span_optional = array_buffer->GetAsSpanIfPossible(); + if (span_optional) { + j_byte_array = + base::android::ToJavaByteArray(env, span_optional.value()); + } else { + // The ArrayBufferPayload impl does not support |GetArrayBuffer|. + // Fallback to allocate a temporary buffer and copy the data. + std::vector<uint8_t> data(array_buffer->GetLength()); + array_buffer->CopyInto(data); + j_byte_array = base::android::ToJavaByteArray(env, data); + } + + return Java_MessagePayloadJni_createFromArrayBuffer(env, + j_byte_array); + }}, payload); } @@ -51,9 +99,7 @@ case MessagePayloadType::kArrayBuffer: { auto byte_array = Java_MessagePayloadJni_getAsArrayBuffer(env, java_message); - std::vector<uint8_t> vector; - base::android::JavaByteArrayToByteVector(env, byte_array, &vector); - return vector; + return std::make_unique<JavaArrayBuffer>(byte_array); } case MessagePayloadType::kInvalid: break;
diff --git a/content/browser/android/message_payload_unittest.cc b/content/browser/android/message_payload_unittest.cc index 344167d..cd5d0284 100644 --- a/content/browser/android/message_payload_unittest.cc +++ b/content/browser/android/message_payload_unittest.cc
@@ -3,7 +3,9 @@ // found in the LICENSE file. #include "content/public/browser/android/message_payload.h" + #include <cstddef> +#include <memory> #include <string> #include "testing/gtest/include/gtest/gtest.h" @@ -24,15 +26,40 @@ TEST(MessagePayloadTest, SelfTest_ArrayBuffer) { std::vector<uint8_t> data(200, 0XFF); auto generated_message = android::ConvertToWebMessagePayloadFromJava( - android::ConvertWebMessagePayloadToJava(data)); - EXPECT_EQ(blink::WebMessagePayload(data), generated_message); + android::ConvertWebMessagePayloadToJava( + blink::WebMessageArrayBufferPayload::CreateForTesting(data))); + const auto& array_buffer = + absl::get<std::unique_ptr<blink::WebMessageArrayBufferPayload>>( + generated_message); + EXPECT_EQ(data.size(), array_buffer->GetLength()); + EXPECT_FALSE(array_buffer->GetAsSpanIfPossible()); + std::vector<uint8_t> copied_data(data.size()); + array_buffer->CopyInto(base::make_span(copied_data)); + EXPECT_EQ(data, copied_data); + + // Encode the message and decode it again. This time the ArrayBuffer should be + // stored in Java ByteArray, which does not support |GetArrayBuffer|. + auto generated_message2 = android::ConvertToWebMessagePayloadFromJava( + android::ConvertWebMessagePayloadToJava(generated_message)); + const auto& array_buffer2 = + absl::get<std::unique_ptr<blink::WebMessageArrayBufferPayload>>( + generated_message2); + EXPECT_EQ(data.size(), array_buffer2->GetLength()); + copied_data.clear(); + copied_data.resize(data.size()); + array_buffer->CopyInto(base::make_span(copied_data)); + EXPECT_EQ(data, copied_data); } TEST(MessagePayloadTest, SelfTest_ArrayBufferEmpty) { - std::vector<uint8_t> data; auto generated_message = android::ConvertToWebMessagePayloadFromJava( - android::ConvertWebMessagePayloadToJava(data)); - EXPECT_EQ(blink::WebMessagePayload(data), generated_message); + android::ConvertWebMessagePayloadToJava( + blink::WebMessageArrayBufferPayload::CreateForTesting( + std::vector<uint8_t>()))); + EXPECT_EQ(absl::get<std::unique_ptr<blink::WebMessageArrayBufferPayload>>( + generated_message) + ->GetLength(), + 0u); } } // namespace
diff --git a/content/browser/background_fetch/background_fetch_event_dispatcher.cc b/content/browser/background_fetch/background_fetch_event_dispatcher.cc index 55df395..ea97486 100644 --- a/content/browser/background_fetch/background_fetch_event_dispatcher.cc +++ b/content/browser/background_fetch/background_fetch_event_dispatcher.cc
@@ -368,11 +368,9 @@ metadata["Failure Reason"] = stream.str(); } - // TODO(https://crbug.com/1199077): Pass `registration_id.storage_key()` - // directly once DevToolsBackgroundServicesContextImpl implements StorageKey. devtools_context_->LogBackgroundServiceEvent( registration_id.service_worker_registration_id(), - registration_id.storage_key().origin(), + registration_id.storage_key(), DevToolsBackgroundService::kBackgroundFetch, /* event_name= */ "Background Fetch completed", /* instance_id= */ registration_id.developer_id(), metadata);
diff --git a/content/browser/background_fetch/background_fetch_scheduler.cc b/content/browser/background_fetch/background_fetch_scheduler.cc index 0757eda8..4b4edb3 100644 --- a/content/browser/background_fetch/background_fetch_scheduler.cc +++ b/content/browser/background_fetch/background_fetch_scheduler.cc
@@ -577,11 +577,9 @@ base::NumberToString(request_info->request_body_size()); } - // TODO(https://crbug.com/1199077): Pass `registration_id.storage_key()` - // directly once DevToolsBackgroundServicesContextImpl implements StorageKey. devtools_context_->LogBackgroundServiceEvent( registration_id.service_worker_registration_id(), - registration_id.storage_key().origin(), + registration_id.storage_key(), DevToolsBackgroundService::kBackgroundFetch, std::move(event_name), /* instance_id= */ registration_id.developer_id(), metadata); }
diff --git a/content/browser/background_sync/background_sync_manager.cc b/content/browser/background_sync/background_sync_manager.cc index 83d2a55c..c5d2c9d 100644 --- a/content/browser/background_sync/background_sync_manager.cc +++ b/content/browser/background_sync/background_sync_manager.cc
@@ -1032,7 +1032,7 @@ if (registration.sync_type() == BackgroundSyncType::PERIODIC && ShouldLogToDevTools(registration.sync_type())) { devtools_context_->LogBackgroundServiceEvent( - sw_registration_id, registration.origin(), + sw_registration_id, blink::StorageKey(registration.origin()), DevToolsBackgroundService::kPeriodicBackgroundSync, /* event_name= */ "Got next event delay", /* instance_id= */ registration.options()->tag, @@ -1310,7 +1310,8 @@ if (registration_info.sync_type == BackgroundSyncType::PERIODIC && ShouldLogToDevTools(registration_info.sync_type)) { devtools_context_->LogBackgroundServiceEvent( - registration_info.service_worker_registration_id, origin, + registration_info.service_worker_registration_id, + blink::StorageKey(origin), DevToolsBackgroundService::kPeriodicBackgroundSync, /* event_name= */ "Unregistered periodicsync", /* instance_id= */ registration_info.tag, @@ -1340,7 +1341,8 @@ base::NumberToString(sync_registration.options()->min_interval); } devtools_context_->LogBackgroundServiceEvent( - sw_registration_id, origin, GetDevToolsBackgroundService(sync_type), + sw_registration_id, blink::StorageKey(origin), + GetDevToolsBackgroundService(sync_type), /* event_name= */ "Registered " + GetSyncEventName(sync_type), /* instance_id= */ sync_registration.options()->tag, event_metadata); } @@ -1402,7 +1404,7 @@ if (devtools_context_->IsRecording( DevToolsBackgroundService::kBackgroundSync)) { devtools_context_->LogBackgroundServiceEvent( - active_version->registration_id(), active_version->key().origin(), + active_version->registration_id(), active_version->key(), DevToolsBackgroundService::kBackgroundSync, /* event_name= */ "Dispatched sync event", /* instance_id= */ tag, @@ -1444,7 +1446,7 @@ if (devtools_context_->IsRecording( DevToolsBackgroundService::kPeriodicBackgroundSync)) { devtools_context_->LogBackgroundServiceEvent( - active_version->registration_id(), active_version->key().origin(), + active_version->registration_id(), active_version->key(), DevToolsBackgroundService::kPeriodicBackgroundSync, /* event_name= */ "Dispatched periodicsync event", /* instance_id= */ tag, @@ -2177,6 +2179,7 @@ UpdateNumFiringRegistrationsBy(registration_info->sync_type, -1); + blink::StorageKey storage_key = blink::StorageKey(origin); BackgroundSyncRegistration* registration = LookupActiveRegistration(*registration_info); if (!registration) { @@ -2196,7 +2199,7 @@ registration_completed = false; if (ShouldLogToDevTools(registration->sync_type())) { devtools_context_->LogBackgroundServiceEvent( - registration_info->service_worker_registration_id, origin, + registration_info->service_worker_registration_id, storage_key, GetDevToolsBackgroundService(registration->sync_type()), /* event_name= */ "Sync event reregistered", /* instance_id= */ registration_info->tag, @@ -2223,7 +2226,7 @@ if (ShouldLogToDevTools(registration->sync_type())) { devtools_context_->LogBackgroundServiceEvent( - registration_info->service_worker_registration_id, origin, + registration_info->service_worker_registration_id, storage_key, GetDevToolsBackgroundService(registration->sync_type()), event_name, /* instance_id= */ registration_info->tag, event_metadata); } @@ -2235,7 +2238,7 @@ if (ShouldLogToDevTools(registration->sync_type())) { devtools_context_->LogBackgroundServiceEvent( - registration_info->service_worker_registration_id, origin, + registration_info->service_worker_registration_id, storage_key, GetDevToolsBackgroundService(registration->sync_type()), /* event_name= */ "Sync completed", /* instance_id= */ registration_info->tag,
diff --git a/content/browser/browser_interface_binders.cc b/content/browser/browser_interface_binders.cc index 5a252d8c7..a626b94cf 100644 --- a/content/browser/browser_interface_binders.cc +++ b/content/browser/browser_interface_binders.cc
@@ -86,6 +86,7 @@ #include "device/vr/public/mojom/vr_service.mojom.h" #include "media/capture/mojom/image_capture.mojom.h" #include "media/capture/mojom/video_capture.mojom.h" +#include "media/midi/midi_service.h" #include "media/mojo/mojom/interface_factory.mojom.h" #include "media/mojo/mojom/media_metrics_provider.mojom.h" #include "media/mojo/mojom/media_player.mojom.h" @@ -981,6 +982,12 @@ map->Add<blink::mojom::RenderAccessibilityHost>( base::BindRepeating(&RenderFrameHostImpl::BindRenderAccessibilityHost, base::Unretained(host))); + +#if BUILDFLAG(IS_FUCHSIA) + map->Add<media::mojom::FuchsiaMediaCodecProvider>( + base::BindRepeating(&RenderProcessHost::BindMediaCodecProvider, + base::Unretained(host->GetProcess()))); +#endif } void PopulateBinderMapWithContext( @@ -1175,17 +1182,15 @@ map->Add<blink::mojom::BucketManagerHost>(base::BindRepeating( &DedicatedWorkerHost::CreateBucketManagerHost, base::Unretained(host))); -#if BUILDFLAG(IS_FUCHSIA) - map->Add<media::mojom::FuchsiaMediaResourceProvider>(base::BindRepeating( - &DedicatedWorkerHost::BindFuchsiaMediaResourceProvider, - base::Unretained(host))); -#endif // BUILDFLAG(IS_FUCHSIA) - // RenderProcessHost binders map->Add<media::mojom::VideoDecodePerfHistory>(BindWorkerReceiver( &RenderProcessHostImpl::BindVideoDecodePerfHistory, host)); map->Add<media::mojom::WebrtcVideoPerfHistory>(BindWorkerReceiver( &RenderProcessHostImpl::BindWebrtcVideoPerfHistory, host)); +#if BUILDFLAG(IS_FUCHSIA) + map->Add<media::mojom::FuchsiaMediaCodecProvider>( + BindWorkerReceiver(&RenderProcessHostImpl::BindMediaCodecProvider, host)); +#endif // RenderProcessHost binders taking a StorageKey map->Add<blink::mojom::FileSystemAccessManager>(
diff --git a/content/browser/devtools/devtools_background_services.proto b/content/browser/devtools/devtools_background_services.proto index 39e0256..4663b3c 100644 --- a/content/browser/devtools/devtools_background_services.proto +++ b/content/browser/devtools/devtools_background_services.proto
@@ -28,7 +28,7 @@ // A proto for storing the background service event with common metadata for // all events. // -// Next Tag: 8 +// Next Tag: 9 message BackgroundServiceEvent { // Microseconds since windows epoch. optional int64 timestamp = 1; @@ -50,4 +50,7 @@ // Additional custom information related to this event. map<string, string> event_metadata = 7; + + // Storage key the background service belongs to. + optional string storage_key = 8; } \ No newline at end of file
diff --git a/content/browser/devtools/devtools_background_services_context_impl.cc b/content/browser/devtools/devtools_background_services_context_impl.cc index f9f6f1c..5031a974 100644 --- a/content/browser/devtools/devtools_background_services_context_impl.cc +++ b/content/browser/devtools/devtools_background_services_context_impl.cc
@@ -189,7 +189,7 @@ void DevToolsBackgroundServicesContextImpl::LogBackgroundServiceEvent( uint64_t service_worker_registration_id, - const url::Origin& origin, + blink::StorageKey storage_key, DevToolsBackgroundService service, const std::string& event_name, const std::string& instance_id, @@ -209,7 +209,8 @@ devtools::proto::BackgroundServiceEvent event; event.set_timestamp( base::Time::Now().ToDeltaSinceWindowsEpoch().InMicroseconds()); - event.set_origin(origin.GetURL().spec()); + event.set_origin(storage_key.origin().GetURL().spec()); + event.set_storage_key(storage_key.Serialize()); event.set_service_worker_registration_id(service_worker_registration_id); event.set_background_service(ServiceToProtoEnum(service)); event.set_event_name(event_name); @@ -220,7 +221,7 @@ // TODO(crbug.com/1199077): Update this when // DevToolsBackgroundServicesContextImpl implements StorageKey. service_worker_context_->StoreRegistrationUserData( - service_worker_registration_id, blink::StorageKey(origin), + service_worker_registration_id, storage_key, {{CreateEntryKey(event.background_service()), event.SerializeAsString()}}, base::DoNothing());
diff --git a/content/browser/devtools/devtools_background_services_context_impl.h b/content/browser/devtools/devtools_background_services_context_impl.h index f68c94b..520f71cf 100644 --- a/content/browser/devtools/devtools_background_services_context_impl.h +++ b/content/browser/devtools/devtools_background_services_context_impl.h
@@ -70,7 +70,7 @@ bool IsRecording(DevToolsBackgroundService service) override; void LogBackgroundServiceEvent( uint64_t service_worker_registration_id, - const url::Origin& origin, + blink::StorageKey storage_key, DevToolsBackgroundService service, const std::string& event_name, const std::string& instance_id,
diff --git a/content/browser/devtools/devtools_background_services_context_impl_unittest.cc b/content/browser/devtools/devtools_background_services_context_impl_unittest.cc index 74c3c68..aeb8fc6b 100644 --- a/content/browser/devtools/devtools_background_services_context_impl_unittest.cc +++ b/content/browser/devtools/devtools_background_services_context_impl_unittest.cc
@@ -173,7 +173,7 @@ void LogTestBackgroundServiceEvent(const std::string& log_message) { context_->LogBackgroundServiceEvent( - service_worker_registration_id_, origin_, + service_worker_registration_id_, blink::StorageKey(origin_), DevToolsBackgroundService::kBackgroundFetch, kEventName, kInstanceId, {{"key", log_message}}); }
diff --git a/content/browser/devtools/protocol/background_service_handler.cc b/content/browser/devtools/protocol/background_service_handler.cc index 2cdfb94..068e023f 100644 --- a/content/browser/devtools/protocol/background_service_handler.cc +++ b/content/browser/devtools/protocol/background_service_handler.cc
@@ -89,6 +89,7 @@ .SetEventName(event.event_name()) .SetInstanceId(event.instance_id()) .SetEventMetadata(ProtoMapToArray(event.event_metadata())) + .SetStorageKey(event.storage_key()) .Build(); }
diff --git a/content/browser/media/capture/web_contents_video_capture_device.cc b/content/browser/media/capture/web_contents_video_capture_device.cc index 7b25442..ee4a548 100644 --- a/content/browser/media/capture/web_contents_video_capture_device.cc +++ b/content/browser/media/capture/web_contents_video_capture_device.cc
@@ -12,6 +12,7 @@ #include "base/memory/weak_ptr.h" #include "base/task/single_thread_task_runner.h" #include "build/build_config.h" +#include "content/browser/media/capture/mouse_cursor_overlay_controller.h" #include "content/browser/renderer_host/render_widget_host_view_base.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/render_frame_host.h"
diff --git a/content/browser/media/media_internals.cc b/content/browser/media/media_internals.cc index 3a431ae..98ee76c 100644 --- a/content/browser/media/media_internals.cc +++ b/content/browser/media/media_internals.cc
@@ -21,6 +21,7 @@ #include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" +#include "base/values.h" #include "build/build_config.h" #include "content/browser/media/session/media_session_impl.h" #include "content/browser/renderer_host/media/media_stream_manager.h" @@ -555,8 +556,8 @@ video_capture_capabilities_cached_data_.clear(); for (const auto& device_format_pair : descriptors_and_formats) { - base::ListValue control_support; - base::ListValue format_list; + base::Value::List control_support; + base::Value::List format_list; // TODO(nisse): Representing format information as a string, to be // parsed by the javascript handler, is brittle. Consider passing // a list of mappings instead.
diff --git a/content/browser/media/video_encode_accelerator_provider_launcher.cc b/content/browser/media/video_encode_accelerator_provider_launcher.cc new file mode 100644 index 0000000..0d4951c --- /dev/null +++ b/content/browser/media/video_encode_accelerator_provider_launcher.cc
@@ -0,0 +1,18 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/media/video_encode_accelerator_provider_launcher.h" +#include "content/public/browser/service_process_host.h" + +namespace content { + +void LaunchVideoEncodeAcceleratorProviderFactory( + mojo::PendingReceiver<media::mojom::VideoEncodeAcceleratorProviderFactory> + receiver) { + ServiceProcessHost::Launch( + std::move(receiver), + ServiceProcessHost::Options().WithDisplayName("Video Encoder").Pass()); +} + +} // namespace content \ No newline at end of file
diff --git a/content/browser/media/video_encode_accelerator_provider_launcher.h b/content/browser/media/video_encode_accelerator_provider_launcher.h new file mode 100644 index 0000000..a7f1c3af --- /dev/null +++ b/content/browser/media/video_encode_accelerator_provider_launcher.h
@@ -0,0 +1,22 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_MEDIA_VIDEO_ENCODE_ACCELERATOR_PROVIDER_LAUNCHER_H_ +#define CONTENT_BROWSER_MEDIA_VIDEO_ENCODE_ACCELERATOR_PROVIDER_LAUNCHER_H_ + +#include "media/mojo/mojom/video_encode_accelerator.mojom.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" + +namespace content { + +// This method is used to create a utility process that hosts a +// VideoEncodeAcceleratorProviderFactory implementation so that video +// encode acceleration can be done outside of the GPU process. +void LaunchVideoEncodeAcceleratorProviderFactory( + mojo::PendingReceiver<media::mojom::VideoEncodeAcceleratorProviderFactory> + receiver); + +} // namespace content + +#endif // CONTENT_BROWSER_MEDIA_VIDEO_ENCODE_ACCELERATOR_PROVIDER_LAUNCHER_H_ \ No newline at end of file
diff --git a/content/browser/message_port_provider_browsertest.cc b/content/browser/message_port_provider_browsertest.cc index 8716a08..3f7c980 100644 --- a/content/browser/message_port_provider_browsertest.cc +++ b/content/browser/message_port_provider_browsertest.cc
@@ -14,6 +14,7 @@ #include "content/public/test/content_browser_test.h" #include "content/public/test/content_browser_test_utils.h" #include "content/shell/browser/shell.h" +#include "third_party/blink/public/common/messaging/string_message_codec.h" namespace content { @@ -70,7 +71,7 @@ MessagePortProvider::PostMessageToFrame( shell()->web_contents()->GetPrimaryPage(), base::UTF8ToUTF16(source_origin), base::UTF8ToUTF16(target_origin), - message); + blink::WebMessageArrayBufferPayload::CreateForTesting(message)); // Verify that the message was received (and had the expected payload). std::string expected_test_reply =
diff --git a/content/browser/network/network_errors_listing_ui.cc b/content/browser/network/network_errors_listing_ui.cc index beb78fbec..8e2b8d98 100644 --- a/content/browser/network/network_errors_listing_ui.cc +++ b/content/browser/network/network_errors_listing_ui.cc
@@ -12,6 +12,7 @@ #include "base/memory/ref_counted_memory.h" #include "base/values.h" #include "content/grit/dev_ui_content_resources.h" +#include "content/public/browser/browser_context.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui.h" #include "content/public/common/url_constants.h"
diff --git a/content/browser/notifications/devtools_event_logging.cc b/content/browser/notifications/devtools_event_logging.cc index daa9a5f..a3c7f96 100644 --- a/content/browser/notifications/devtools_event_logging.cc +++ b/content/browser/notifications/devtools_event_logging.cc
@@ -12,6 +12,7 @@ #include "content/public/browser/devtools_background_services_context.h" #include "content/public/browser/notification_database_data.h" #include "content/public/browser/storage_partition.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" #include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h" #include "url/gurl.h" @@ -57,13 +58,14 @@ if (!devtools_context) return DevToolsCallback(); + url::Origin origin = url::Origin::Create(data.origin); + // Passing the |devtools_context| as base::Unretained is safe as the callback // is executed synchronously. auto base_callback = base::BindOnce( &DevToolsBackgroundServicesContext::LogBackgroundServiceEvent, base::Unretained(devtools_context), data.service_worker_registration_id, - url::Origin::Create(data.origin), - DevToolsBackgroundService::kNotifications); + blink::StorageKey(origin), DevToolsBackgroundService::kNotifications); return base::BindOnce( [](DevToolsBaseCallback callback, const std::string& notification_id,
diff --git a/content/browser/payments/payment_app_provider_impl.cc b/content/browser/payments/payment_app_provider_impl.cc index 880ad7b6..65657c1 100644 --- a/content/browser/payments/payment_app_provider_impl.cc +++ b/content/browser/payments/payment_app_provider_impl.cc
@@ -34,6 +34,7 @@ #include "mojo/public/cpp/bindings/message.h" #include "mojo/public/mojom/base/time.mojom.h" #include "third_party/blink/public/common/service_worker/service_worker_status_code.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" #include "third_party/blink/public/mojom/service_worker/service_worker_container_type.mojom.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/gfx/image/image.h" @@ -119,8 +120,8 @@ AddMethodDataToMap(event_data->method_data, &data); AddModifiersToMap(event_data->modifiers, &data); dev_tools->LogBackgroundServiceEvent( - registration_id, sw_origin, DevToolsBackgroundService::kPaymentHandler, - "Payment request", + registration_id, blink::StorageKey(sw_origin), + DevToolsBackgroundService::kPaymentHandler, "Payment request", /*instance_id=*/event_data->payment_request_id, data); } @@ -175,7 +176,7 @@ {"Service Worker Uses Cache", sw_use_cache ? "true" : "false"}, }; dev_tools->LogBackgroundServiceEvent( - /*service_worker_registration_id=*/-1, sw_origin, + /*service_worker_registration_id=*/-1, blink::StorageKey(sw_origin), DevToolsBackgroundService::kPaymentHandler, "Install payment handler", /*instance_id=*/event_data->payment_request_id, data); } @@ -238,8 +239,8 @@ AddMethodDataToMap(event_data->method_data, &data); AddModifiersToMap(event_data->modifiers, &data); dev_tools->LogBackgroundServiceEvent( - registration_id, sw_origin, DevToolsBackgroundService::kPaymentHandler, - "Can make payment", + registration_id, blink::StorageKey(sw_origin), + DevToolsBackgroundService::kPaymentHandler, "Can make payment", /*instance_id=*/payment_request_id, data); } @@ -266,8 +267,8 @@ GetDevTools(sw_origin); if (dev_tools) { dev_tools->LogBackgroundServiceEvent( - registration_id, sw_origin, DevToolsBackgroundService::kPaymentHandler, - "Abort payment", + registration_id, blink::StorageKey(sw_origin), + DevToolsBackgroundService::kPaymentHandler, "Abort payment", /*instance_id=*/payment_request_id, {}); } @@ -361,7 +362,8 @@ registration_id >= 0 ? "true" : "false"}, }; dev_tools->LogBackgroundServiceEvent( - registration_id, sw_origin, DevToolsBackgroundService::kPaymentHandler, + registration_id, blink::StorageKey(sw_origin), + DevToolsBackgroundService::kPaymentHandler, "Install payment handler result", /*instance_id=*/event_data->payment_request_id, data); }
diff --git a/content/browser/payments/payment_event_dispatcher.cc b/content/browser/payments/payment_event_dispatcher.cc index d0828122..8dc19c4a 100644 --- a/content/browser/payments/payment_event_dispatcher.cc +++ b/content/browser/payments/payment_event_dispatcher.cc
@@ -10,6 +10,7 @@ #include "content/browser/payments/payment_app_provider_impl.h" #include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/public/common/content_features.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" namespace content { namespace { @@ -56,8 +57,8 @@ std::stringstream response_type; response_type << response->response_type; dev_tools->LogBackgroundServiceEvent( - registration_id, sw_origin, DevToolsBackgroundService::kPaymentHandler, - "Payment response", + registration_id, blink::StorageKey(sw_origin), + DevToolsBackgroundService::kPaymentHandler, "Payment response", /*instance_id=*/payment_request_id, {{"Method Name", response->method_name}, {"Details", response->stringified_details}, @@ -81,8 +82,8 @@ {"Type", response_type.str()}, {"Can Make Payment", response->can_make_payment ? "true" : "false"}}; dev_tools->LogBackgroundServiceEvent( - registration_id, sw_origin, DevToolsBackgroundService::kPaymentHandler, - "Can make payment response", + registration_id, blink::StorageKey(sw_origin), + DevToolsBackgroundService::kPaymentHandler, "Can make payment response", /*instance_id=*/payment_request_id, data); } @@ -98,8 +99,8 @@ bool payment_aborted) { if (dev_tools) { dev_tools->LogBackgroundServiceEvent( - registration_id, sw_origin, DevToolsBackgroundService::kPaymentHandler, - "Abort payment response", + registration_id, blink::StorageKey(sw_origin), + DevToolsBackgroundService::kPaymentHandler, "Abort payment response", /*instance_id=*/payment_request_id, {{"Payment Aborted", payment_aborted ? "true" : "false"}}); }
diff --git a/content/browser/preloading/prerender/README.md b/content/browser/preloading/prerender/README.md index 5615b1a..244bc51 100644 --- a/content/browser/preloading/prerender/README.md +++ b/content/browser/preloading/prerender/README.md
@@ -1,6 +1,5 @@ -This directory contains the experimental Prerender2 implementation -(https://crbug.com/1126305). This feature is now behind the -`blink::features::kPrerender2` flag. +This directory contains the Prerender2 implementation +(https://crbug.com/1126305). If you're interested in relevant code changes, join the prerendering-reviews@chromium.org group.
diff --git a/content/browser/preloading/prerender/prerender_browsertest.cc b/content/browser/preloading/prerender/prerender_browsertest.cc index 6328594..bd93e45 100644 --- a/content/browser/preloading/prerender/prerender_browsertest.cc +++ b/content/browser/preloading/prerender/prerender_browsertest.cc
@@ -185,6 +185,21 @@ PreloadingFailureReason::kPreloadingFailureReasonCommonEnd)); } +// Tests the params of WebContentsImpl that contains a prerendered page for a +// new tab navigation. +void ExpectWebContentsIsForNewTabPrerendering(WebContentsImpl& web_contents) { + // The primary page shows the initial blank page. + EXPECT_TRUE(web_contents.GetLastCommittedURL().is_empty()); + + EXPECT_FALSE(web_contents.HasOpener()); + + // In the current implementation, WebContentsImpl needs to be visible to start + // prerendering, but actually this WebContents is not visible to users. This + // should be fixed. See the TODO comment in the constructor of + // PrerenderNewTabHandle for details. + EXPECT_FALSE(web_contents.IsHidden()); +} + class PrerenderBrowserTest : public ContentBrowserTest, public WebContentsObserver { public: @@ -200,15 +215,7 @@ prerender_helper_ = std::make_unique<test::PrerenderTestHelper>(base::BindRepeating( &PrerenderBrowserTest::web_contents, base::Unretained(this))); - - // Need to initialize features after creating PrerenderTestHelper since it - // initializes features in its constructor. - feature_list_.InitWithFeaturesAndParameters( - // TODO(crbug.com/1273341): remove the limitation and run tests with - // multiple prerenders. - {{blink::features::kPrerender2, - {{"max_num_of_running_speculation_rules", "1"}}}}, - {}); + feature_list_.InitAndEnableFeature(blink::features::kPrerender2InNewTab); } ~PrerenderBrowserTest() override = default; @@ -259,6 +266,12 @@ prerender_helper_->AddMultiplePrerenderAsync(prerendering_urls); } + void AddPrerenderWithTargetHintAsync(const GURL& prerendering_url, + const std::string& target_hint) { + prerender_helper_->AddPrerenderWithTargetHintAsync(prerendering_url, + target_hint); + } + bool AddTestUtilJS(RenderFrameHost* host) { bool success = false; std::string js = R"( @@ -700,6 +713,50 @@ ExpectFinalStatusForSpeculationRule(PrerenderFinalStatus::kActivated); } +// Tests that clicking a link annotated with "target=_blank" can activate a +// prerender whose target_hint is "_blank". +IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, + ActivateOnLinkClick_TargetBlank_WithTargetHintBlank) { + const GURL kInitialUrl = GetUrl("/simple_links.html"); + const GURL kPrerenderingUrl = GetUrl("/title2.html"); + + // Navigate to an initial page which has a link to `kPrerenderingUrl`. + ASSERT_TRUE(NavigateToURL(shell(), kInitialUrl)); + + // Start prerendering `kPrerenderingUrl`. + TestNavigationObserver nav_observer(kPrerenderingUrl); + nav_observer.StartWatchingNewWebContents(); + AddPrerenderWithTargetHintAsync(kPrerenderingUrl, "_blank"); + nav_observer.WaitForNavigationFinished(); + EXPECT_EQ(nav_observer.last_navigation_url(), kPrerenderingUrl); + + PrerenderHost* prerender_host = + web_contents_impl()->GetPrerenderHostRegistry()->FindHostByUrlForTesting( + kPrerenderingUrl); + ASSERT_TRUE(prerender_host); + auto* prerender_web_contents = WebContentsImpl::FromFrameTreeNode( + prerender_host->GetPrerenderFrameTree().root()); + ASSERT_NE(prerender_web_contents, web_contents_impl()); + ExpectWebContentsIsForNewTabPrerendering(*prerender_web_contents); + + // Click the link annotated with "target=_blank". This should activate the + // prerendered page. + test::PrerenderHostObserver prerender_observer( + *prerender_web_contents, prerender_host->frame_tree_node_id()); + const std::string kLinkClickScript = R"( + clickSameSiteNewWindowLink(); + )"; + EXPECT_TRUE(ExecJs(web_contents(), kLinkClickScript)); + EXPECT_EQ(prerender_web_contents->GetLastCommittedURL(), kPrerenderingUrl); + EXPECT_TRUE(prerender_observer.was_activated()); + EXPECT_FALSE(HasHostForUrl(kPrerenderingUrl)); + ExpectFinalStatusForSpeculationRule(PrerenderFinalStatus::kActivated); + + // The navigation occurred in a new WebContents, so the original WebContents + // should still be showing the initial trigger page. + EXPECT_EQ(web_contents()->GetLastCommittedURL(), kInitialUrl); +} + // Tests that clicking a link annotated with "target=_blank rel=noopener" cannot // activate a prerender. IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, @@ -741,6 +798,51 @@ ExpectFinalStatusForSpeculationRule(PrerenderFinalStatus::kActivated); } +// Tests that clicking a link annotated with "target=_blank rel=noopener" can +// activate a prerender whose target_hint is "_blank". +IN_PROC_BROWSER_TEST_F( + PrerenderBrowserTest, + ActivateOnLinkClick_TargetBlankWithNoopener_WithTargetHintBlank) { + const GURL kInitialUrl = GetUrl("/simple_links.html"); + const GURL kPrerenderingUrl = GetUrl("/title2.html"); + + // Navigate to an initial page which has a link to `kPrerenderingUrl`. + ASSERT_TRUE(NavigateToURL(shell(), kInitialUrl)); + + // Start prerendering `kPrerenderingUrl`. + TestNavigationObserver nav_observer(kPrerenderingUrl); + nav_observer.StartWatchingNewWebContents(); + AddPrerenderWithTargetHintAsync(kPrerenderingUrl, "_blank"); + nav_observer.WaitForNavigationFinished(); + EXPECT_EQ(nav_observer.last_navigation_url(), kPrerenderingUrl); + + PrerenderHost* prerender_host = + web_contents_impl()->GetPrerenderHostRegistry()->FindHostByUrlForTesting( + kPrerenderingUrl); + ASSERT_TRUE(prerender_host); + auto* prerender_web_contents = WebContentsImpl::FromFrameTreeNode( + prerender_host->GetPrerenderFrameTree().root()); + ASSERT_NE(prerender_web_contents, web_contents_impl()); + ExpectWebContentsIsForNewTabPrerendering(*prerender_web_contents); + + // Click the link annotated with "target=_blank rel=noopener". This should + // activate the prerendered page. + test::PrerenderHostObserver prerender_observer( + *prerender_web_contents, prerender_host->frame_tree_node_id()); + const std::string kLinkClickScript = R"( + clickSameSiteNewWindowWithNoopenerLink(); + )"; + EXPECT_TRUE(ExecJs(web_contents(), kLinkClickScript)); + EXPECT_EQ(prerender_web_contents->GetLastCommittedURL(), kPrerenderingUrl); + EXPECT_TRUE(prerender_observer.was_activated()); + EXPECT_FALSE(HasHostForUrl(kPrerenderingUrl)); + ExpectFinalStatusForSpeculationRule(PrerenderFinalStatus::kActivated); + + // The navigation occurred in a new WebContents, so the original WebContents + // should still be showing the initial trigger page. + EXPECT_EQ(web_contents()->GetLastCommittedURL(), kInitialUrl); +} + // Tests that clicking a link annotated with "target=_blank rel=opener" cannot // activate a prerender. IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, @@ -788,6 +890,60 @@ ExpectFinalStatusForSpeculationRule(PrerenderFinalStatus::kTriggerDestroyed); } +// Tests that clicking a link annotated with "target=_blank rel=opener" cannot +// activate a prerender whose target_hint is "_blank". +IN_PROC_BROWSER_TEST_F( + PrerenderBrowserTest, + ActivateOnLinkClick_TargetBlankWithOpener_WithTargetHintBlank) { + const GURL kInitialUrl = GetUrl("/simple_links.html"); + const GURL kPrerenderingUrl = GetUrl("/title2.html"); + + // Navigate to an initial page which has a link to `kPrerenderingUrl`. + ASSERT_TRUE(NavigateToURL(shell(), kInitialUrl)); + + // Start prerendering `kPrerenderingUrl`. + TestNavigationObserver nav_observer(kPrerenderingUrl); + nav_observer.StartWatchingNewWebContents(); + AddPrerenderWithTargetHintAsync(kPrerenderingUrl, "_blank"); + nav_observer.WaitForNavigationFinished(); + EXPECT_EQ(nav_observer.last_navigation_url(), kPrerenderingUrl); + + PrerenderHost* prerender_host = + web_contents_impl()->GetPrerenderHostRegistry()->FindHostByUrlForTesting( + kPrerenderingUrl); + ASSERT_TRUE(prerender_host); + auto* prerender_web_contents = WebContentsImpl::FromFrameTreeNode( + prerender_host->GetPrerenderFrameTree().root()); + ASSERT_NE(prerender_web_contents, web_contents_impl()); + ExpectWebContentsIsForNewTabPrerendering(*prerender_web_contents); + + // Click the link annotated with "target=_blank rel=opener". This should not + // activate the prerendered page. + test::PrerenderHostObserver prerender_observer( + *prerender_web_contents, prerender_host->frame_tree_node_id()); + const std::string kLinkClickScript = R"( + clickSameSiteNewWindowWithOpenerLink(); + )"; + EXPECT_TRUE(ExecJs(web_contents(), kLinkClickScript)); + // The WebContents pre-created for prerendering should not be used. + EXPECT_NE(prerender_web_contents->GetLastCommittedURL(), kPrerenderingUrl); + EXPECT_FALSE(prerender_observer.was_activated()); + // The host should still be available. + EXPECT_TRUE(HasHostForUrl(kPrerenderingUrl)); + + // The navigation occurred in a new WebContents, so the original WebContents + // should still be showing the initial trigger page. + EXPECT_EQ(web_contents()->GetLastCommittedURL(), kInitialUrl); +} + +// TODO(crbug.com/1350676): Add more test cases for prerender-in-new-tab: +// - Multiple prerendering requests with the same URL but different target hint. +// - Navigation in a new tab to the prerendering URL multiple times. Only the +// first navigation should activate the prerendered page. +// - Cancellation of prerender-in-new-tab (e.g., removing speculation rules, +// calling disallowed features in a prerendered page). +// - Behavior of PrerenderNewTabHandle::WebContentsDelegateImpl. + IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, ResponseHeaders) { const GURL kInitialUrl = GetUrl("/empty.html"); const GURL kPrerenderingUrl = GetUrl("/set-header?X-Foo: bar"); @@ -3774,8 +3930,7 @@ std::string memory_threshold = base::NumberToString(base::SysInfo::AmountOfPhysicalMemoryMB() + 1); feature_list_.InitWithFeaturesAndParameters( - {{blink::features::kPrerender2, {}}, - {blink::features::kPrerender2MemoryControls, + {{blink::features::kPrerender2MemoryControls, {{blink::features::kPrerender2MemoryThresholdParamName, memory_threshold}}}}, {}); @@ -4644,8 +4799,7 @@ public: PrerenderHostRegistryInBackgroundTest() { scoped_feature_list_.InitWithFeatures( - {blink::features::kPrerender2, - // Enable to run prerenderings in the background. + {// Enable to run prerenderings in the background. blink::features::kPrerender2InBackground}, // Disable the memory requirement of Prerender2 so the test can run on // any bot. @@ -4734,8 +4888,7 @@ public: SequentialPrerenderInBackgroundBrowserTest() { scoped_feature_list_.InitWithFeatures( - {blink::features::kPrerender2, - // Enable to run prerenderings in the background. + {// Enable to run prerenderings in the background. blink::features::kPrerender2InBackground}, // Disable the memory requirement of Prerender2 so the test can run on // any bot. @@ -6082,11 +6235,8 @@ class PrerenderSameSiteCrossOriginBrowserTest : public PrerenderBrowserTest { public: PrerenderSameSiteCrossOriginBrowserTest() { - feature_list_.InitWithFeaturesAndParameters( - {{blink::features::kPrerender2, {{}}}, - {blink::features::kSameSiteCrossOriginForSpeculationRulesPrerender, - {{}}}}, - {/* disabled_features */}); + feature_list_.InitAndEnableFeature( + blink::features::kSameSiteCrossOriginForSpeculationRulesPrerender); } void SetUp() override { @@ -6343,73 +6493,6 @@ ExpectFinalStatusForSpeculationRule(PrerenderFinalStatus::kTriggerDestroyed); } -// Tests that PrerenderHostRegistry only starts prerendering for the first -// prerender speculation rule it receives. -IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, AddSpeculationRulesMultipleTimes) { - const GURL kInitialUrl = GetUrl("/empty.html"); - const GURL kFirstPrerenderingUrl = GetUrl("/empty.html?prerender1"); - const GURL kSecondPrerenderingUrl = GetUrl("/empty.html?prerender2"); - - // Add the first prerender speculation rule; it should trigger prerendering - // successfully. - ASSERT_TRUE(NavigateToURL(shell(), kInitialUrl)); - AddPrerender(kFirstPrerenderingUrl); - histogram_tester().ExpectBucketCount( - "Prerender.Experimental.PrerenderHostFinalStatus.SpeculationRule", - PrerenderFinalStatus::kMaxNumOfRunningPrerendersExceeded, 0); - - test::PrerenderHostRegistryObserver registry_observer(*web_contents_impl()); - - // Add a new prerender speculation rule. Since PrerenderHostRegistry limits - // the number of running prerenders to one, this rule should not be applied. - AddPrerenderAsync(kSecondPrerenderingUrl); - registry_observer.WaitForTrigger(kSecondPrerenderingUrl); - EXPECT_FALSE(HasHostForUrl(kSecondPrerenderingUrl)); - ExpectFinalStatusForSpeculationRule( - PrerenderFinalStatus::kMaxNumOfRunningPrerendersExceeded); - - // Navigate primary page to flush the metrics. - NavigationHandleObserver activation_observer(web_contents(), - kFirstPrerenderingUrl); - NavigatePrimaryPage(kFirstPrerenderingUrl); - { - // Verify that we log the correct metrics associated with case when we hit - // max prerenders exceeded. - ukm::SourceId ukm_source_id = activation_observer.next_page_ukm_source_id(); - - auto ukm_entries = test_ukm_recorder()->GetEntries( - Preloading_Attempt::kEntryName, test::kPreloadingAttemptUkmMetrics); - auto prediction_ukm_entries = - test_ukm_recorder()->GetEntries(Preloading_Prediction::kEntryName, - test::kPreloadingPredictionUkmMetrics); - EXPECT_EQ(prediction_ukm_entries.size(), 3u); - EXPECT_EQ(ukm_entries.size(), 2u); - - std::vector<UkmEntry> expected_entries = { - attempt_ukm_entry_builder().BuildEntry( - ukm_source_id, PreloadingType::kPrerender, - PreloadingEligibility::kEligible, - PreloadingHoldbackStatus::kAllowed, - PreloadingTriggeringOutcome::kSuccess, - PreloadingFailureReason::kUnspecified, - /*accurate=*/true), - attempt_ukm_entry_builder().BuildEntry( - ukm_source_id, PreloadingType::kPrerender, - PreloadingEligibility::kEligible, - PreloadingHoldbackStatus::kAllowed, - PreloadingTriggeringOutcome::kFailure, - ToPreloadingFailureReason( - PrerenderFinalStatus::kMaxNumOfRunningPrerendersExceeded), - /*accurate=*/false), - }; - - EXPECT_THAT(ukm_entries, - testing::UnorderedElementsAreArray(expected_entries)) - << content::test::ActualVsExpectedUkmEntriesToString(ukm_entries, - expected_entries); - } -} - // Tests that PrerenderHostRegistry can hold up to two prerendering for the // prerender embedders it receives. IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, StartByEmbeddersMultipleTimes) { @@ -8202,10 +8285,7 @@ class PrerenderPreloaderHoldbackBrowserTest : public PrerenderBrowserTest { public: PrerenderPreloaderHoldbackBrowserTest() { - feature_list_.InitWithFeaturesAndParameters( - {{blink::features::kPrerender2, {{}}}, - {features::kPrerender2Holdback, {{}}}}, - {/* disabled_features */}); + feature_list_.InitAndEnableFeature(features::kPrerender2Holdback); } ~PrerenderPreloaderHoldbackBrowserTest() override = default;
diff --git a/content/browser/preloading/prerender/prerender_host.cc b/content/browser/preloading/prerender/prerender_host.cc index 6e09bce..96355601 100644 --- a/content/browser/preloading/prerender/prerender_host.cc +++ b/content/browser/preloading/prerender/prerender_host.cc
@@ -6,6 +6,7 @@ #include "base/feature_list.h" #include "base/functional/callback_forward.h" +#include "base/notreached.h" #include "base/observer_list.h" #include "base/run_loop.h" #include "base/task/thread_pool.h" @@ -213,8 +214,8 @@ } if (!final_status_) { - RecordFinalStatus(PrerenderFinalStatus::kDestroyed, - attributes_.initiator_ukm_id, ukm::kInvalidSourceId); + RecordFailedFinalStatusImpl( + PrerenderCancellationReason(PrerenderFinalStatus::kDestroyed)); } // If we are still waiting on test loop, we can assume the page loading step @@ -519,12 +520,7 @@ } } - // TODO(crbug.com/1299330): Replace - // `navigation_request.GetNextPageUkmSourceId()` with prerendered page's UKM - // source ID. - RecordFinalStatus(PrerenderFinalStatus::kActivated, - attributes_.initiator_ukm_id, - navigation_request.GetNextPageUkmSourceId()); + RecordActivation(navigation_request); // Prerender is activated. Set the status to kSuccess. SetTriggeringOutcome(PreloadingTriggeringOutcome::kSuccess); @@ -825,14 +821,33 @@ return *frame_tree_; } -void PrerenderHost::RecordFinalStatus(base::PassKey<PrerenderHostRegistry>, - PrerenderFinalStatus status) { - RecordFinalStatus(status, attributes_.initiator_ukm_id, - ukm::kInvalidSourceId); +void PrerenderHost::RecordFailedFinalStatus( + base::PassKey<PrerenderHostRegistry>, + const PrerenderCancellationReason& reason) { + RecordFailedFinalStatusImpl(reason); +} + +void PrerenderHost::RecordFailedFinalStatusImpl( + const PrerenderCancellationReason& reason) { + DCHECK(!final_status_); + DCHECK_NE(reason.final_status(), PrerenderFinalStatus::kActivated); + final_status_ = reason.final_status(); + RecordFailedPrerenderFinalStatus(reason, attributes_); // Set failure reason for this PreloadingAttempt specific to the // FinalStatus. - SetFailureReason(status); + SetFailureReason(reason.final_status()); +} + +void PrerenderHost::RecordActivation(NavigationRequest& navigation_request) { + DCHECK(!final_status_); + final_status_ = PrerenderFinalStatus::kActivated; + + // TODO(crbug.com/1299330): Replace + // `navigation_request.GetNextPageUkmSourceId()` with prerendered page's UKM + // source ID. + ReportSuccessActivation(attributes_, + navigation_request.GetNextPageUkmSourceId()); } PrerenderHost::LoadingOutcome PrerenderHost::WaitForLoadStopForTesting() { @@ -854,14 +869,6 @@ return status; } -void PrerenderHost::RecordFinalStatus(PrerenderFinalStatus status, - ukm::SourceId initiator_ukm_id, - ukm::SourceId prerendered_ukm_id) { - DCHECK(!final_status_); - final_status_ = status; - RecordPrerenderFinalStatus(status, attributes_, prerendered_ukm_id); -} - const GURL& PrerenderHost::GetInitialUrl() const { return attributes_.prerendering_url; } @@ -912,12 +919,10 @@ // When adding a new failure reason, consider whether it should be // propagated to `attempt_`. Most values should be propagated, but we // explicitly do not propagate failure reasons if: - // 1. the prerender was actually successful (kActivated). - // 2. prerender was successfully prepared but then destroyed because it + // 1. prerender was successfully prepared but then destroyed because it // wasn't needed for a subsequent navigation (kTriggerDestroyed). - // 3. the prerender was still pending for its initial navigation when it was + // 2. the prerender was still pending for its initial navigation when it was // activated (kActivatedBeforeStarted). - case PrerenderFinalStatus::kActivated: case PrerenderFinalStatus::kTriggerDestroyed: case PrerenderFinalStatus::kActivatedBeforeStarted: return; @@ -968,6 +973,10 @@ // PrerenderHost deletion is async. attempt_.reset(); return; + case PrerenderFinalStatus::kActivated: + // The activation path does not call this method, so it should never reach + // this case. + NOTREACHED(); } }
diff --git a/content/browser/preloading/prerender/prerender_host.h b/content/browser/preloading/prerender/prerender_host.h index d83c1a1f..7af26fe 100644 --- a/content/browser/preloading/prerender/prerender_host.h +++ b/content/browser/preloading/prerender/prerender_host.h
@@ -46,6 +46,8 @@ class FrameTreeNode; class PrerenderHostRegistry; class RenderFrameHostImpl; +class WebContentsImpl; +class PrerenderCancellationReason; // Prerender2: // PrerenderHost creates a new FrameTree in WebContents associated with the page @@ -184,9 +186,14 @@ FrameTree& GetPrerenderFrameTree(); // Tells the reason of the destruction of this host. PrerenderHostRegistry - // uses this before abandoning the host. - void RecordFinalStatus(base::PassKey<PrerenderHostRegistry>, - PrerenderFinalStatus status); + // uses this before abandoning the host. Exposed to PrerenderHostRegistry + // only. + void RecordFailedFinalStatus(base::PassKey<PrerenderHostRegistry>, + const PrerenderCancellationReason& reason); + + // Called by PrerenderHostRegistry to report that this prerender host is + // successfully activated. + void RecordActivation(NavigationRequest& navigation_request); enum class LoadingOutcome { kLoadingCompleted, @@ -255,13 +262,7 @@ base::WeakPtr<PreloadingAttempt> preloading_attempt() { return attempt_; } private: - // Records the status to UMA and UKM. `initiator_ukm_id` represents the page - // that starts prerendering and `prerendered_ukm_id` represents the - // prerendered page. `prerendered_ukm_id` is valid after the page is - // activated. - void RecordFinalStatus(PrerenderFinalStatus status, - ukm::SourceId initiator_ukm_id, - ukm::SourceId prerendered_ukm_id); + void RecordFailedFinalStatusImpl(const PrerenderCancellationReason& reason); // Asks the registry to cancel prerendering. void Cancel(PrerenderFinalStatus status);
diff --git a/content/browser/preloading/prerender/prerender_host_registry.cc b/content/browser/preloading/prerender/prerender_host_registry.cc index 70d5b59..f10fc76a 100644 --- a/content/browser/preloading/prerender/prerender_host_registry.cc +++ b/content/browser/preloading/prerender/prerender_host_registry.cc
@@ -24,6 +24,7 @@ #include "content/browser/preloading/prerender/prerender_final_status.h" #include "content/browser/preloading/prerender/prerender_metrics.h" #include "content/browser/preloading/prerender/prerender_navigation_utils.h" +#include "content/browser/preloading/prerender/prerender_new_tab_handle.h" #include "content/browser/renderer_host/frame_tree_node.h" #include "content/browser/renderer_host/navigation_request.h" #include "content/browser/renderer_host/render_frame_host_impl.h" @@ -124,8 +125,10 @@ // Don't prerender when the trigger is in the background. if (web_contents.GetVisibility() == Visibility::HIDDEN) { - RecordPrerenderFinalStatus(PrerenderFinalStatus::kTriggerBackgrounded, - attributes, ukm::kInvalidSourceId); + RecordFailedPrerenderFinalStatus( + PrerenderCancellationReason( + PrerenderFinalStatus::kTriggerBackgrounded), + attributes); if (attempt) attempt->SetEligibility(PreloadingEligibility::kHidden); return RenderFrameHost::kNoFrameTreeNodeId; @@ -133,8 +136,9 @@ // Don't prerender on low-end devices. if (!DeviceHasEnoughMemoryForPrerender()) { - RecordPrerenderFinalStatus(PrerenderFinalStatus::kLowEndDevice, - attributes, ukm::kInvalidSourceId); + RecordFailedPrerenderFinalStatus( + PrerenderCancellationReason(PrerenderFinalStatus::kLowEndDevice), + attributes); if (attempt) attempt->SetEligibility(PreloadingEligibility::kLowMemory); return RenderFrameHost::kNoFrameTreeNodeId; @@ -143,8 +147,9 @@ // Don't prerender when the Data Saver setting is enabled. if (GetContentClient()->browser()->IsDataSaverEnabled( web_contents.GetBrowserContext())) { - RecordPrerenderFinalStatus(PrerenderFinalStatus::kDataSaverEnabled, - attributes, ukm::kInvalidSourceId); + RecordFailedPrerenderFinalStatus( + PrerenderCancellationReason(PrerenderFinalStatus::kDataSaverEnabled), + attributes); if (attempt) attempt->SetEligibility(PreloadingEligibility::kDataSaverEnabled); return RenderFrameHost::kNoFrameTreeNodeId; @@ -158,9 +163,10 @@ if (!prerender_navigation_utils::IsSameSite( attributes.prerendering_url, attributes.initiator_origin.value())) { - RecordPrerenderFinalStatus(PrerenderFinalStatus::kCrossSiteNavigation, - attributes, ukm::kInvalidSourceId); - + RecordFailedPrerenderFinalStatus( + PrerenderCancellationReason( + PrerenderFinalStatus::kCrossSiteNavigation), + attributes); if (attempt) attempt->SetEligibility(PreloadingEligibility::kCrossOrigin); return RenderFrameHost::kNoFrameTreeNodeId; @@ -169,10 +175,10 @@ IsSameSiteCrossOriginForSpeculationRulesPrerender2Enabled() && !attributes.initiator_origin.value().IsSameOriginWith( attributes.prerendering_url)) { - RecordPrerenderFinalStatus( - PrerenderFinalStatus::kSameSiteCrossOriginNavigation, attributes, - ukm::kInvalidSourceId); - + RecordFailedPrerenderFinalStatus( + PrerenderCancellationReason( + PrerenderFinalStatus::kSameSiteCrossOriginNavigation), + attributes); if (attempt) attempt->SetEligibility(PreloadingEligibility::kCrossOrigin); return RenderFrameHost::kNoFrameTreeNodeId; @@ -182,8 +188,9 @@ // Disallow all pages that have an effective URL like host apps and NTP. if (SiteInstanceImpl::HasEffectiveURL(web_contents.GetBrowserContext(), web_contents.GetURL())) { - RecordPrerenderFinalStatus(PrerenderFinalStatus::kHasEffectiveUrl, - attributes, ukm::kInvalidSourceId); + RecordFailedPrerenderFinalStatus( + PrerenderCancellationReason(PrerenderFinalStatus::kHasEffectiveUrl), + attributes); if (attempt) attempt->SetEligibility(PreloadingEligibility::kHasEffectiveUrl); return RenderFrameHost::kNoFrameTreeNodeId; @@ -237,13 +244,13 @@ // experiment groups for analysis. To prevent this we set // TriggeringOutcome to kFailure and look into the failure reason to // learn more. - attempt->SetFailureReason( - ToPreloadingFailureReason( - PrerenderFinalStatus::kMaxNumOfRunningPrerendersExceeded)); + attempt->SetFailureReason(ToPreloadingFailureReason( + PrerenderFinalStatus::kMaxNumOfRunningPrerendersExceeded)); } - RecordPrerenderFinalStatus( - PrerenderFinalStatus::kMaxNumOfRunningPrerendersExceeded, attributes, - ukm::kInvalidSourceId); + RecordFailedPrerenderFinalStatus( + PrerenderCancellationReason( + PrerenderFinalStatus::kMaxNumOfRunningPrerendersExceeded), + attributes); return RenderFrameHost::kNoFrameTreeNodeId; } @@ -299,6 +306,28 @@ return frame_tree_node_id; } +int PrerenderHostRegistry::CreateAndStartHostForNewTab( + const PrerenderAttributes& attributes, + WebContents& web_contents) { + DCHECK(base::FeatureList::IsEnabled(blink::features::kPrerender2InNewTab)); + std::string recorded_url = + attributes.initiator_origin.has_value() + ? attributes.initiator_origin.value().GetURL().spec() + : "(empty_url)"; + TRACE_EVENT2("navigation", + "PrerenderHostRegistry::CreateAndStartHostForNewTab", + "attributes", attributes, "initiator_origin", recorded_url); + + auto handle = std::make_unique<PrerenderNewTabHandle>( + attributes, *web_contents.GetBrowserContext()); + int prerender_host_id = handle->StartPrerendering(); + if (prerender_host_id == RenderFrameHost::kNoFrameTreeNodeId) + return RenderFrameHost::kNoFrameTreeNodeId; + prerender_new_tab_handle_by_frame_tree_node_id_[prerender_host_id] = + std::move(handle); + return prerender_host_id; +} + int PrerenderHostRegistry::StartPrerendering(int frame_tree_node_id) { if (frame_tree_node_id == RenderFrameHost::kNoFrameTreeNodeId) { DCHECK(base::FeatureList::IsEnabled( @@ -381,20 +410,37 @@ for (int host_id : frame_tree_node_ids) { // Look up the id in the non-reserved host map. - auto iter = prerender_host_by_frame_tree_node_id_.find(host_id); - if (iter == prerender_host_by_frame_tree_node_id_.end()) - continue; + if (auto iter = prerender_host_by_frame_tree_node_id_.find(host_id); + iter != prerender_host_by_frame_tree_node_id_.end()) { + if (running_prerender_host_id_ == host_id) + running_prerender_host_id_ = RenderFrameHost::kNoFrameTreeNodeId; - if (running_prerender_host_id_ == host_id) - running_prerender_host_id_ = RenderFrameHost::kNoFrameTreeNodeId; + // Remove the prerender host from the host map so that it's not used for + // activation during asynchronous deletion. + std::unique_ptr<PrerenderHost> prerender_host = std::move(iter->second); + prerender_host_by_frame_tree_node_id_.erase(iter); - // Remove the prerender host from the host map so that it's not used for - // activation during asynchronous deletion. - std::unique_ptr<PrerenderHost> prerender_host = std::move(iter->second); - prerender_host_by_frame_tree_node_id_.erase(iter); + // Asynchronously delete the prerender host. + ScheduleToDeleteAbandonedHost(std::move(prerender_host), + PrerenderCancellationReason(final_status)); + } - // Asynchronously delete the prerender host. - ScheduleToDeleteAbandonedHost(std::move(prerender_host), final_status); + if (base::FeatureList::IsEnabled(blink::features::kPrerender2InNewTab)) { + // Look up the id in the prerender-in-new-tab handle map. + if (auto iter = + prerender_new_tab_handle_by_frame_tree_node_id_.find(host_id); + iter != prerender_new_tab_handle_by_frame_tree_node_id_.end()) { + // The host should be driven by PrerenderHostRegistry associated with + // the new tab. + DCHECK_NE(running_prerender_host_id_, host_id); + + std::unique_ptr<PrerenderNewTabHandle> handle = std::move(iter->second); + prerender_new_tab_handle_by_frame_tree_node_id_.erase(iter); + handle->CancelPrerendering(final_status); + } + } else { + DCHECK(prerender_new_tab_handle_by_frame_tree_node_id_.empty()); + } } // Start another prerender if the running prerender is cancelled. @@ -422,30 +468,42 @@ // Look up the id in the non-reserved host map, remove it from the map, and // record the cancellation reason. - auto iter = prerender_host_by_frame_tree_node_id_.find(frame_tree_node_id); - if (iter == prerender_host_by_frame_tree_node_id_.end()) - return false; + if (auto iter = + prerender_host_by_frame_tree_node_id_.find(frame_tree_node_id); + iter != prerender_host_by_frame_tree_node_id_.end()) { + std::unique_ptr<PrerenderHost> prerender_host = std::move(iter->second); + prerender_host_by_frame_tree_node_id_.erase(iter); - reason.ReportMetrics(iter->second->trigger_type(), - iter->second->embedder_histogram_suffix()); + reason.ReportMetrics(prerender_host->trigger_type(), + prerender_host->embedder_histogram_suffix()); - // Remove the prerender host from the host map so that it's not used for - // activation during asynchronous deletion. + // Asynchronously delete the prerender host. + ScheduleToDeleteAbandonedHost(std::move(prerender_host), reason); - std::unique_ptr<PrerenderHost> prerender_host = std::move(iter->second); - prerender_host_by_frame_tree_node_id_.erase(iter); + // Start another prerender if the running prerender is cancelled. + if (running_prerender_host_id_ == frame_tree_node_id) { + running_prerender_host_id_ = RenderFrameHost::kNoFrameTreeNodeId; + StartPrerendering(RenderFrameHost::kNoFrameTreeNodeId); + } - // Asynchronously delete the prerender host. - ScheduleToDeleteAbandonedHost(std::move(prerender_host), - reason.final_status()); - - // Start another prerender if the running prerender is cancelled. - if (running_prerender_host_id_ == frame_tree_node_id) { - running_prerender_host_id_ = RenderFrameHost::kNoFrameTreeNodeId; - StartPrerendering(RenderFrameHost::kNoFrameTreeNodeId); + return true; } - return true; + if (base::FeatureList::IsEnabled(blink::features::kPrerender2InNewTab)) { + // Look up the id in the prerender new-tab handle map, remove it from the + // map, and record the cancellation reason. + if (auto iter = prerender_new_tab_handle_by_frame_tree_node_id_.find( + frame_tree_node_id); + iter != prerender_new_tab_handle_by_frame_tree_node_id_.end()) { + iter->second->CancelPrerendering(reason.final_status()); + prerender_new_tab_handle_by_frame_tree_node_id_.erase(iter); + return true; + } + } else { + DCHECK(prerender_new_tab_handle_by_frame_tree_node_id_.empty()); + } + + return false; } void PrerenderHostRegistry::CancelAllHosts(PrerenderFinalStatus final_status) { @@ -455,9 +513,15 @@ auto prerender_host_map = std::move(prerender_host_by_frame_tree_node_id_); for (auto& iter : prerender_host_map) { std::unique_ptr<PrerenderHost> prerender_host = std::move(iter.second); - ScheduleToDeleteAbandonedHost(std::move(prerender_host), final_status); + ScheduleToDeleteAbandonedHost(std::move(prerender_host), + PrerenderCancellationReason(final_status)); } + auto prerender_new_tab_handle_map = + std::move(prerender_new_tab_handle_by_frame_tree_node_id_); + for (auto& iter : prerender_new_tab_handle_map) + iter.second->CancelPrerendering(final_status); + pending_prerenders_.clear(); } @@ -561,6 +625,32 @@ return reserved_prerender_host_.get(); } +std::unique_ptr<WebContentsImpl> +PrerenderHostRegistry::TakePreCreatedWebContentsForNewTabIfExists( + const mojom::CreateNewWindowParams& create_new_window_params, + const WebContents::CreateParams& web_contents_create_params) { + DCHECK(base::FeatureList::IsEnabled(blink::features::kPrerender2InNewTab)); + + // Don't serve a prerendered page if the window needs the opener or is created + // for non-regular navigations. + if (!create_new_window_params.opener_suppressed || + create_new_window_params.is_form_submission || + create_new_window_params.pip_options) { + return nullptr; + } + + for (auto& iter : prerender_new_tab_handle_by_frame_tree_node_id_) { + std::unique_ptr<WebContentsImpl> web_contents = + iter.second->TakeWebContentsIfAvailable(create_new_window_params, + web_contents_create_params); + if (web_contents) { + prerender_new_tab_handle_by_frame_tree_node_id_.erase(iter); + return web_contents; + } + } + return nullptr; +} + std::vector<FrameTree*> PrerenderHostRegistry::GetPrerenderFrameTrees() { std::vector<FrameTree*> result; for (auto& i : prerender_host_by_frame_tree_node_id_) { @@ -578,6 +668,11 @@ if (iter.second->GetInitialUrl() == prerendering_url) return iter.second.get(); } + for (auto& iter : prerender_new_tab_handle_by_frame_tree_node_id_) { + PrerenderHost* host = iter.second->GetPrerenderHostForTesting(); // IN-TEST + if (host && host->GetInitialUrl() == prerendering_url) + return host; + } return nullptr; } @@ -590,7 +685,8 @@ // Asynchronously delete the prerender host. ScheduleToDeleteAbandonedHost( std::move(iter.second), - PrerenderFinalStatus::kCancelAllHostsForTesting); + PrerenderCancellationReason( + PrerenderFinalStatus::kCancelAllHostsForTesting)); } // After we're done scheduling deletion, clear the map and the pending queue. @@ -770,6 +866,10 @@ cancelled_prerenders.push_back(host_id); } } + for (const auto& [host_id, _] : + prerender_new_tab_handle_by_frame_tree_node_id_) { + cancelled_prerenders.push_back(host_id); + } CancelHosts(cancelled_prerenders, PrerenderFinalStatus::kTriggerDestroyed); pending_prerenders_.clear(); @@ -778,8 +878,8 @@ void PrerenderHostRegistry::ScheduleToDeleteAbandonedHost( std::unique_ptr<PrerenderHost> prerender_host, - PrerenderFinalStatus final_status) { - prerender_host->RecordFinalStatus(PassKey(), final_status); + const PrerenderCancellationReason& cancellation_reason) { + prerender_host->RecordFailedFinalStatus(PassKey(), cancellation_reason); // Asynchronously delete the prerender host. to_be_deleted_hosts_.push_back(std::move(prerender_host)); @@ -820,6 +920,8 @@ if (host_by_id.second->trigger_type() == trigger_type) ++trigger_type_count; } + // TODO(crbug.com/1350676): Make this function care about + // `prerender_new_tab_handle_by_frame_tree_node_id_` as well. switch (trigger_type) { case PrerenderTriggerType::kSpeculationRule: @@ -866,7 +968,7 @@ private_footprint_total_kb += pmd.os_dump().private_footprint_kb; } - // TODO(crbug.com/1273341): Finalize the threshold after the experiment + // TODO(crbug.com/1382697): Finalize the threshold after the experiment // completes. The default acceptable percent is 10% of the system memory. int acceptable_percent_of_system_memory = base::GetFieldTrialParamByFeatureAsInt(
diff --git a/content/browser/preloading/prerender/prerender_host_registry.h b/content/browser/preloading/prerender/prerender_host_registry.h index 28eaedad..28791ee 100644 --- a/content/browser/preloading/prerender/prerender_host_registry.h +++ b/content/browser/preloading/prerender/prerender_host_registry.h
@@ -20,7 +20,9 @@ #include "content/browser/preloading/prerender/prerender_host.h" #include "content/browser/renderer_host/back_forward_cache_impl.h" #include "content/common/content_export.h" +#include "content/common/frame.mojom.h" #include "content/public/browser/visibility.h" +#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_observer.h" #include "services/resource_coordinator/public/cpp/memory_instrumentation/global_memory_dump.h" #include "third_party/blink/public/common/tokens/tokens.h" @@ -29,6 +31,7 @@ namespace content { +class PrerenderNewTabHandle; class RenderFrameHostImpl; class PrerenderCancellationReason; @@ -92,6 +95,14 @@ WebContents& web_contents, PreloadingAttempt* preloading_attempt = nullptr); + // Creates and starts a host in a new WebContents so that a navigation in a + // new tab will be able to activate it. PrerenderHostRegistry associated with + // the new WebContents manages the started host, and `this` + // PrerenderHostRegistry manages PrerenderNewTabHandle that owns the + // WebContents (see `prerender_new_tab_handle_by_frame_tree_node_id_`). + int CreateAndStartHostForNewTab(const PrerenderAttributes& attributes, + WebContents& web_contents); + // Cancels the host registered for `frame_tree_node_id`. The host is // immediately removed from the map of non-reserved hosts but asynchronously // destroyed so that prerendered pages can cancel themselves without concern @@ -156,6 +167,13 @@ // does not match any reserved host. PrerenderHost* FindReservedHostById(int frame_tree_node_id); + // Returns the ownership of a pre-created WebContentsImpl that contains a + // prerendered page that corresponds to the given params for a new tab + // navigation, if it exists. + std::unique_ptr<WebContentsImpl> TakePreCreatedWebContentsForNewTabIfExists( + const mojom::CreateNewWindowParams& create_new_window_params, + const WebContents::CreateParams& web_contents_create_params); + // Returns the FrameTrees owned by this registry's prerender hosts. std::vector<FrameTree*> GetPrerenderFrameTrees(); @@ -193,7 +211,7 @@ void ScheduleToDeleteAbandonedHost( std::unique_ptr<PrerenderHost> prerender_host, - PrerenderFinalStatus final_status); + const PrerenderCancellationReason& cancellation_reason); void DeleteAbandonedHosts(); void NotifyTrigger(const GURL& url); @@ -248,6 +266,10 @@ // The host that is reserved for activation. std::unique_ptr<PrerenderHost> reserved_prerender_host_; + // Handles that manage WebContents for prerendering in new tabs. + base::flat_map<int, std::unique_ptr<PrerenderNewTabHandle>> + prerender_new_tab_handle_by_frame_tree_node_id_; + // Hosts that are scheduled to be deleted asynchronously. // Design note: PrerenderHostRegistry should explicitly manage the hosts to be // deleted instead of depending on the deletion helpers like DeleteSoon() to
diff --git a/content/browser/preloading/prerender/prerender_host_unittest.cc b/content/browser/preloading/prerender/prerender_host_unittest.cc index fe6ea34..1c5293cc 100644 --- a/content/browser/preloading/prerender/prerender_host_unittest.cc +++ b/content/browser/preloading/prerender/prerender_host_unittest.cc
@@ -106,11 +106,10 @@ class PrerenderHostTest : public RenderViewHostImplTestHarness { public: PrerenderHostTest() { - scoped_feature_list_.InitWithFeatures( - {blink::features::kPrerender2}, + scoped_feature_list_.InitAndDisableFeature( // Disable the memory requirement of Prerender2 so the test can run on // any bot. - {blink::features::kPrerender2MemoryControls}); + blink::features::kPrerender2MemoryControls); } ~PrerenderHostTest() override = default; @@ -539,8 +538,7 @@ public: PrerenderHostInBackgroundTest() { scoped_feature_list_.InitWithFeatures( - {blink::features::kPrerender2, - // Enable to run prerenderings in the background. + {// Enable to run prerenderings in the background. blink::features::kPrerender2InBackground}, // Disable the memory requirement of Prerender2 so the test can run on // any bot.
diff --git a/content/browser/preloading/prerender/prerender_metrics.cc b/content/browser/preloading/prerender/prerender_metrics.cc index 958971f..40e93e1 100644 --- a/content/browser/preloading/prerender/prerender_metrics.cc +++ b/content/browser/preloading/prerender/prerender_metrics.cc
@@ -103,6 +103,16 @@ } } +void RecordPrerenderFinalStatusUma( + PrerenderFinalStatus final_status, + PrerenderTriggerType trigger_type, + const std::string& embedder_histogram_suffix) { + base::UmaHistogramEnumeration( + GenerateHistogramName("Prerender.Experimental.PrerenderHostFinalStatus", + trigger_type, embedder_histogram_suffix), + final_status); +} + } // namespace // static @@ -162,6 +172,23 @@ } } +std::string PrerenderCancellationReason::ToDevtoolReasonString() const { + switch (final_status_) { + case PrerenderFinalStatus::kInactivePageRestriction: + DCHECK(absl::holds_alternative<uint64_t>(explanation_)); + // TODO(https://crbug.com/1328365): It seems we have to return an integer. + // And devtool has to handle it based on the enum.xml, as the content + // layer cannot know about the enums added by the embedder layer. + return ""; + case PrerenderFinalStatus::kMojoBinderPolicy: + DCHECK(absl::holds_alternative<std::string>(explanation_)); + return absl::get<std::string>(explanation_); + default: + DCHECK(absl::holds_alternative<absl::monostate>(explanation_)); + return ""; + } +} + void RecordPrerenderTriggered(ukm::SourceId ukm_id) { ukm::builders::PrerenderPageLoad(ukm_id).SetTriggeredPrerender(true).Record( ukm::UkmRecorder::Get()); @@ -177,47 +204,56 @@ delta); } -void RecordPrerenderFinalStatus(PrerenderFinalStatus status, - const PrerenderAttributes& attributes, - ukm::SourceId prerendered_ukm_id) { - base::UmaHistogramEnumeration( - GenerateHistogramName("Prerender.Experimental.PrerenderHostFinalStatus", - attributes.trigger_type, - attributes.embedder_histogram_suffix), - status); +void RecordFailedPrerenderFinalStatus( + const PrerenderCancellationReason& cancellation_reason, + const PrerenderAttributes& attributes) { + DCHECK_NE(cancellation_reason.final_status(), + PrerenderFinalStatus::kActivated); + RecordPrerenderFinalStatusUma(cancellation_reason.final_status(), + attributes.trigger_type, + attributes.embedder_histogram_suffix); if (attributes.initiator_ukm_id != ukm::kInvalidSourceId) { // `initiator_ukm_id` must be valid for the speculation rules. DCHECK_EQ(attributes.trigger_type, PrerenderTriggerType::kSpeculationRule); ukm::builders::PrerenderPageLoad(attributes.initiator_ukm_id) - .SetFinalStatus(static_cast<int>(status)) + .SetFinalStatus(static_cast<int>(cancellation_reason.final_status())) + .Record(ukm::UkmRecorder::Get()); + } + + // Browser initiated prerendering doesn't report cancellation reasons to the + // DevTools as it doesn't have the initiator frame associated with DevTools + // agents. + if (!attributes.IsBrowserInitiated()) { + auto* ftn = FrameTreeNode::GloballyFindByID( + attributes.initiator_frame_tree_node_id); + DCHECK(ftn); + // TODO(https://crbug.com/1332377): Discuss with devtools to finalize the + // message protocol. + devtools_instrumentation::DidCancelPrerender( + attributes.prerendering_url, ftn, cancellation_reason.final_status(), + cancellation_reason.ToDevtoolReasonString()); + } +} + +void ReportSuccessActivation(const PrerenderAttributes& attributes, + ukm::SourceId prerendered_ukm_id) { + RecordPrerenderFinalStatusUma(PrerenderFinalStatus::kActivated, + attributes.trigger_type, + attributes.embedder_histogram_suffix); + if (attributes.initiator_ukm_id != ukm::kInvalidSourceId) { + // `initiator_ukm_id` must be valid only for the speculation rules. + DCHECK_EQ(attributes.trigger_type, PrerenderTriggerType::kSpeculationRule); + ukm::builders::PrerenderPageLoad(attributes.initiator_ukm_id) + .SetFinalStatus(static_cast<int>(PrerenderFinalStatus::kActivated)) .Record(ukm::UkmRecorder::Get()); } if (prerendered_ukm_id != ukm::kInvalidSourceId) { - // `prerendered_ukm_id` must be valid only when the prerendered page gets - // activated. - DCHECK_EQ(status, PrerenderFinalStatus::kActivated); ukm::builders::PrerenderPageLoad(prerendered_ukm_id) - .SetFinalStatus(static_cast<int>(status)) + .SetFinalStatus(static_cast<int>(PrerenderFinalStatus::kActivated)) .Record(ukm::UkmRecorder::Get()); } - - // The kActivated case is recorded in `PrerenderHost::Activate`, and the - // kMojoBinderPolicy case is recorded in - // RenderFrameHostImpl::CancelPrerenderingByMojoBinderPolicy for storing the - // interface detail. Browser initiated prerendering doesn't report - // cancellation reasons to the DevTools as it doesn't have the initiator frame - // associated with DevTools agents. - if (!attributes.IsBrowserInitiated() && - status != PrerenderFinalStatus::kActivated && - status != PrerenderFinalStatus::kMojoBinderPolicy) { - auto* ftn = FrameTreeNode::GloballyFindByID( - attributes.initiator_frame_tree_node_id); - DCHECK(ftn); - devtools_instrumentation::DidCancelPrerender(attributes.prerendering_url, - ftn, status, ""); - } } void RecordPrerenderActivationNavigationParamsMatch(
diff --git a/content/browser/preloading/prerender/prerender_metrics.h b/content/browser/preloading/prerender/prerender_metrics.h index 7b5e927..b09b85c 100644 --- a/content/browser/preloading/prerender/prerender_metrics.h +++ b/content/browser/preloading/prerender/prerender_metrics.h
@@ -66,11 +66,15 @@ PrerenderCancellationReason(PrerenderCancellationReason&& reason); + // Reports UMA and UKM metrics. void ReportMetrics(PrerenderTriggerType trigger_type, const std::string& embedder_histogram_suffix) const; PrerenderFinalStatus final_status() const { return final_status_; } + // This is mainly used for displaying a detailed reason on devtools panel. + std::string ToDevtoolReasonString() const; + private: PrerenderCancellationReason(PrerenderFinalStatus final_status, DetailedReasonVariant explanation); @@ -108,13 +112,17 @@ PrerenderTriggerType trigger_type, const std::string& embedder_histogram_suffix); -// Records the status to UMA and UKM, and reports the status other than -// kActivated to DevTools. In the attributes, `initiator_ukm_id` represents the -// page that starts prerendering. `prerendered_ukm_id` represents the -// prerendered page and is valid after the page is activated. -void RecordPrerenderFinalStatus(PrerenderFinalStatus status, - const PrerenderAttributes& attributes, - ukm::SourceId prerendered_ukm_id); +// Used by failing prerender attempts. Records the status to UMA and UKM, and +// reports the failing reason to devtools. In the attributes, `initiator_ukm_id` +// represents the page that starts prerendering. +void RecordFailedPrerenderFinalStatus( + const PrerenderCancellationReason& cancellation_reason, + const PrerenderAttributes& attributes); + +// Records a success activation to UMA and UKM. +// `prerendered_ukm_id` is the UKM ID of the activated page. +void ReportSuccessActivation(const PrerenderAttributes& attributes, + ukm::SourceId prerendered_ukm_id); // Records which navigation parameters are different between activation and // initial prerender navigation when activation fails.
diff --git a/content/browser/preloading/prerender/prerender_new_tab_handle.cc b/content/browser/preloading/prerender/prerender_new_tab_handle.cc new file mode 100644 index 0000000..2e4e954 --- /dev/null +++ b/content/browser/preloading/prerender/prerender_new_tab_handle.cc
@@ -0,0 +1,146 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/preloading/prerender/prerender_new_tab_handle.h" + +#include "content/browser/preloading/prerender/prerender_host.h" +#include "content/browser/preloading/prerender/prerender_host_registry.h" +#include "content/public/browser/web_contents_delegate.h" + +namespace content { + +// This is used as the delegate of WebContents created for a new tab where +// prerendering runs. +class PrerenderNewTabHandle::WebContentsDelegateImpl + : public WebContentsDelegate { + public: + WebContentsDelegateImpl() = default; + ~WebContentsDelegateImpl() override = default; + + bool IsPrerender2Supported(WebContents& web_contents) override { + // TODO(crbug.com/1350676): Accordingly check the user preference etc like + // the regular WebContentsDelegate implementation. + return true; + } + + // TODO(crbug.com/1350676): Investigate if we have to override other + // functions on WebContentsDelegateImpl. +}; + +PrerenderNewTabHandle::PrerenderNewTabHandle( + const PrerenderAttributes& attributes, + BrowserContext& browser_context) + : attributes_(attributes), web_contents_create_params_(&browser_context) { + DCHECK(base::FeatureList::IsEnabled(blink::features::kPrerender2InNewTab)); + DCHECK(!attributes.IsBrowserInitiated()); + + auto* initiator_render_frame_host = RenderFrameHostImpl::FromFrameToken( + attributes_.initiator_process_id, + attributes_.initiator_frame_token.value()); + + // Create a new WebContents for prerendering in a new tab. + // TODO(crbug.com/1350676): Pass the same creation parameters as + // WebContentsImpl::CreateNewWindow(). Also, set SessionStorageNamespace. + web_contents_create_params_.opener_render_process_id = + initiator_render_frame_host->GetProcess()->GetID(); + web_contents_create_params_.opener_render_frame_id = + initiator_render_frame_host->GetRoutingID(); + web_contents_create_params_.opener_suppressed = true; + // TODO(crbug.com/1350676): Consider sharing a pre-created WebContents + // instance among multiple new-tab-prerenders as an optimization. + web_contents_ = base::WrapUnique(static_cast<WebContentsImpl*>( + WebContents::Create(web_contents_create_params_).release())); + + // The delegate is swapped with a proper one on activation. + web_contents_delegate_ = std::make_unique<WebContentsDelegateImpl>(); + web_contents_->SetDelegate(web_contents_delegate_.get()); + + // In the current implementation, WebContentsImpl needs to be visible to start + // prerendering (see the check in PrerenderHostRegistry::CreateAndStartHost), + // but actually this WebContents is not visible to users. This seems + // inconsistent. + // TODO(crbug.com/1350676): Set the visibility of this WebContents to HIDDEN + // until activation and let the WebContents run prerendering even in HIDDEN. + // To achieve this, we have to modify the check in PrerenderHostRegistry, and + // set `web_contents_create_params_.initially_hidden` above. + DCHECK_EQ(web_contents_->GetVisibility(), Visibility::VISIBLE); +} + +PrerenderNewTabHandle::~PrerenderNewTabHandle() { + if (web_contents_) + web_contents_->SetDelegate(nullptr); +} + +int PrerenderNewTabHandle::StartPrerendering() { + // TODO(crbug.com/1350676): Pass a valid PreloadingAttempt. + prerender_host_id_ = GetPrerenderHostRegistry().CreateAndStartHost( + attributes_, *web_contents_, /*preloading_attempt=*/nullptr); + return prerender_host_id_; +} + +void PrerenderNewTabHandle::CancelPrerendering( + PrerenderFinalStatus final_status) { + GetPrerenderHostRegistry().CancelHost(prerender_host_id_, final_status); +} + +std::unique_ptr<WebContentsImpl> +PrerenderNewTabHandle::TakeWebContentsIfAvailable( + const mojom::CreateNewWindowParams& create_new_window_params, + const WebContents::CreateParams& web_contents_create_params) { + PrerenderHost* host = + GetPrerenderHostRegistry().FindNonReservedHostById(prerender_host_id_); + if (!host) { + // The host was already canceled, for example, due to disallowed feature + // usage in the prerendered page, while this PrerenderNewTabHandle is still + // alive. + return nullptr; + } + if (host->GetInitialUrl() != create_new_window_params.target_url) { + // The host is not eligible for the target URL. + return nullptr; + } + + // Verify the opener frame is the same with the frame that triggered + // prerendering. + if (web_contents_create_params_.opener_render_process_id != + web_contents_create_params.opener_render_process_id) { + return nullptr; + } + if (web_contents_create_params_.opener_render_frame_id != + web_contents_create_params.opener_render_frame_id) { + return nullptr; + } + + // TODO(crbug.com/1350676): Consider supporting activation for non-empty + // `main_frame_name`. + DCHECK(web_contents_create_params_.main_frame_name.empty()); + if (web_contents_create_params_.main_frame_name != + web_contents_create_params.main_frame_name) { + return nullptr; + } + + // TODO(crbug.com/1350676): Compare other parameters on CreateNewWindowParams + // and WebContents::CreateParams. Also, we could have some guard to make sure + // that parameters newly added to WebContents::CreateParams are accordingly + // handled here with an approach similar to SameSizeAsDocumentLoader. + + DCHECK(web_contents_); + web_contents_->SetDelegate(nullptr); + return std::move(web_contents_); +} + +PrerenderHost* PrerenderNewTabHandle::GetPrerenderHostForTesting() { + PrerenderHostRegistry& registry = GetPrerenderHostRegistry(); + PrerenderHost* host = registry.FindNonReservedHostById(prerender_host_id_); + if (host) + return host; + return registry.FindReservedHostById(prerender_host_id_); +} + +PrerenderHostRegistry& PrerenderNewTabHandle::GetPrerenderHostRegistry() { + DCHECK(web_contents_); + return *web_contents_->GetPrerenderHostRegistry(); +} + +} // namespace content
diff --git a/content/browser/preloading/prerender/prerender_new_tab_handle.h b/content/browser/preloading/prerender/prerender_new_tab_handle.h new file mode 100644 index 0000000..85d77d2 --- /dev/null +++ b/content/browser/preloading/prerender/prerender_new_tab_handle.h
@@ -0,0 +1,86 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_PRELOADING_PRERENDER_PRERENDER_NEW_TAB_HANDLE_H_ +#define CONTENT_BROWSER_PRELOADING_PRERENDER_PRERENDER_NEW_TAB_HANDLE_H_ + +#include "content/browser/preloading/prerender/prerender_attributes.h" +#include "content/browser/preloading/prerender/prerender_final_status.h" +#include "content/browser/web_contents/web_contents_impl.h" +#include "content/common/frame.mojom.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/render_frame_host.h" + +namespace content { + +class PrerenderHost; +class PrerenderHostRegistry; + +// PrerenderNewTabHandle creates a new WebContentsImpl instance, starts +// prerendering on that, and keeps the instance until the prerendered page is +// activated for navigation or cancelled for some reason. By starting +// prerendering in a new WebContentsImpl instance, this can serve a prerendered +// page to navigation in a new tab different from a tab of the page that +// triggered prerendering. +// +// PrerenderHostRegistry instantiates and owns PrerenderNewTabHandle in response +// to prerendering requests via Speculation Rules API. When navigation is about +// to start for a new tab, the navigation asks PrerenderHostRegistry if there is +// a PrerenderNewTabHandle instance that has a pre-created WebContentsImpl +// suitable for this navigation. If it's found, the navigation takes over the +// ownership of the pre-created WebContentsImpl instance and destroys the +// handle. +class PrerenderNewTabHandle { + public: + PrerenderNewTabHandle(const PrerenderAttributes& attributes, + BrowserContext& browser_context); + ~PrerenderNewTabHandle(); + + // Starts prerendering in `web_contents_`. Returns the root FrameTreeNode id + // of the prerendered page, which can be used as the id of PrerenderHost, on + // success. Returns RenderFrameHost::kNoFrameTreeNodeId on failure. + int StartPrerendering(); + + // Cancels prerendering started in `web_contents_`. + void CancelPrerendering(PrerenderFinalStatus final_status); + + // Passes the ownership of `web_contents_` to the caller if it's available for + // new tab navigation with given params. + std::unique_ptr<WebContentsImpl> TakeWebContentsIfAvailable( + const mojom::CreateNewWindowParams& create_new_window_params, + const WebContents::CreateParams& web_contents_create_params); + + // Returns PrerenderHost that `web_contents_` is hosting. + PrerenderHost* GetPrerenderHostForTesting(); + + private: + PrerenderHostRegistry& GetPrerenderHostRegistry(); + + const PrerenderAttributes attributes_; + + // Used for creating WebContentsImpl that contains a prerendered page for a + // new tab navigation. + WebContents::CreateParams web_contents_create_params_; + + // Contains a prerendered page for a new tab navigation. This is valid until + // TakeWebContentsIfAvailable() is called. + std::unique_ptr<WebContentsImpl> web_contents_; + + // This is a tentative instance of WebContentsDelegate for `web_contents_` + // until prerender activation. The delegate of `web_contents_` will be swapped + // with a proper one on prerender page activation. + // + // Note: WebContentsDelegate of the initiator WebContentsImpl is not available + // for `web_contents_`. This is because WebContentsDelegate can be specific to + // a tab, and `web_contents_` will be placed in a different tab from the + // initiator's tab. + class WebContentsDelegateImpl; + std::unique_ptr<WebContentsDelegateImpl> web_contents_delegate_; + + int prerender_host_id_ = RenderFrameHost::kNoFrameTreeNodeId; +}; + +} // namespace content + +#endif // CONTENT_BROWSER_PRELOADING_PRERENDER_PRERENDER_NEW_TAB_HANDLE_H_
diff --git a/content/browser/preloading/prerenderer.cc b/content/browser/preloading/prerenderer.cc index 0bfae120..6ce81ef 100644 --- a/content/browser/preloading/prerenderer.cc +++ b/content/browser/preloading/prerenderer.cc
@@ -5,8 +5,11 @@ #include "content/browser/preloading/prerenderer.h" #include "content/browser/preloading/preloading.h" +#include "content/browser/preloading/prerender/prerender_attributes.h" +#include "content/browser/preloading/prerender/prerender_final_status.h" #include "content/browser/preloading/prerender/prerender_host_registry.h" #include "content/browser/preloading/prerender/prerender_navigation_utils.h" +#include "content/browser/preloading/prerender/prerender_new_tab_handle.h" #include "content/browser/renderer_host/render_frame_host_delegate.h" #include "content/public/browser/web_contents.h" @@ -222,30 +225,60 @@ } } - // TODO(crbug.com/1354049): Pass `target_browsing_context_name_hint` to - // start prerendering in a new tab. Referrer referrer(*(it->referrer)); - int prerender_host_id = registry_->CreateAndStartHost( - PrerenderAttributes(it->url, PrerenderTriggerType::kSpeculationRule, - /*embedder_histogram_suffix=*/"", referrer, - rfhi.GetLastCommittedOrigin(), - rfhi.GetLastCommittedURL(), - rfhi.GetProcess()->GetID(), rfhi.GetFrameToken(), - rfhi.GetFrameTreeNodeId(), - rfhi.GetPageUkmSourceId(), ui::PAGE_TRANSITION_LINK, - /*url_match_predicate=*/absl::nullopt), - *web_contents, /*preloading_attempt=*/preloading_attempt); + PrerenderAttributes attributes( + it->url, PrerenderTriggerType::kSpeculationRule, + /*embedder_histogram_suffix=*/"", referrer, + rfhi.GetLastCommittedOrigin(), rfhi.GetLastCommittedURL(), + rfhi.GetProcess()->GetID(), rfhi.GetFrameToken(), + rfhi.GetFrameTreeNodeId(), rfhi.GetPageUkmSourceId(), + ui::PAGE_TRANSITION_LINK, + /*url_match_predicate=*/absl::nullopt); + // TODO(crbug.com/1354049): Handle the case where multiple speculation rules // have the same URL but its `target_browsing_context_name_hint` is // different. In the current implementation, only the first rule is // triggered. - started_prerenders_.insert(end, {.url = it->url, - .referrer = referrer, - .prerender_host_id = prerender_host_id}); + switch (it->target_browsing_context_name_hint) { + case blink::mojom::SpeculationTargetHint::kBlank: { + if (base::FeatureList::IsEnabled( + blink::features::kPrerender2InNewTab)) { + // `preloading_attempt` is not available for prerendering in a new tab + // as it's associated with the current WebContents. + // TODO(crbug.com/1350676): Create new PreloadAttempt associated with + // WebContents for prerendering. + int prerender_host_id = + registry_->CreateAndStartHostForNewTab(attributes, *web_contents); + started_prerenders_.insert(end, + {.url = it->url, + .referrer = referrer, + .prerender_host_id = prerender_host_id}); - // Start to observe PrerenderHost to get the information about FinalStatus. - observers_.push_back(std::make_unique<PrerenderHostObserver>( - registry_->FindNonReservedHostById(prerender_host_id))); + // TODO(crbug.com/1350676): Observe PrerenderHost created for + // prerendering in a new tab like the kNoHint and kSelf cases. + break; + } + // Handle the rule as kNoHint if the prerender-in-new-tab is not + // enabled. + [[fallthrough]]; + } + case blink::mojom::SpeculationTargetHint::kNoHint: + case blink::mojom::SpeculationTargetHint::kSelf: { + int prerender_host_id = registry_->CreateAndStartHost( + attributes, *web_contents, + /*preloading_attempt=*/preloading_attempt); + started_prerenders_.insert(end, + {.url = it->url, + .referrer = referrer, + .prerender_host_id = prerender_host_id}); + + // Start to observe PrerenderHost to get the information about + // FinalStatus. + observers_.push_back(std::make_unique<PrerenderHostObserver>( + registry_->FindNonReservedHostById(prerender_host_id))); + break; + } + } } }
diff --git a/content/browser/push_messaging/push_messaging_router.cc b/content/browser/push_messaging/push_messaging_router.cc index 25a3d89..2af71ab 100644 --- a/content/browser/push_messaging/push_messaging_router.cc +++ b/content/browser/push_messaging/push_messaging_router.cc
@@ -176,7 +176,7 @@ if (payload) event_metadata["Payload"] = *payload; devtools_context->LogBackgroundServiceEvent( - service_worker->registration_id(), service_worker->key().origin(), + service_worker->registration_id(), service_worker->key(), DevToolsBackgroundService::kPushMessaging, "Push event dispatched", message_id, event_metadata); } @@ -242,7 +242,7 @@ push_event_status != blink::mojom::PushEventStatus::SERVICE_WORKER_ERROR) { devtools_context->LogBackgroundServiceEvent( - service_worker->registration_id(), service_worker->key().origin(), + service_worker->registration_id(), service_worker->key(), DevToolsBackgroundService::kPushMessaging, "Push event completed", message_id, {{"Status", status_description}}); }
diff --git a/content/browser/renderer_host/frame_tree_node.cc b/content/browser/renderer_host/frame_tree_node.cc index d02d8fc..e264e93 100644 --- a/content/browser/renderer_host/frame_tree_node.cc +++ b/content/browser/renderer_host/frame_tree_node.cc
@@ -575,10 +575,6 @@ // The RenderFrameHostManager should clean up any speculative RenderFrameHost // it created for the navigation. Also register that the load stopped. DidStopLoading(); - // TODO(https://crbug.com/1220337): This might accidentally delete an - // unrelated speculative RenderFrameHost that is pending commit. Check if the - // speculative RenderFrameHost is really associated with the deleted - // NavigationRequest first before deleting. render_manager_.DiscardSpeculativeRFHIfUnused(reason); }
diff --git a/content/browser/renderer_host/frame_tree_node.h b/content/browser/renderer_host/frame_tree_node.h index a37471c..512fff9 100644 --- a/content/browser/renderer_host/frame_tree_node.h +++ b/content/browser/renderer_host/frame_tree_node.h
@@ -319,9 +319,10 @@ // Resets the navigation request owned by `this` (which shouldn't have reached // the "pending commit" stage yet) and any state created by it, including the - // speculative RenderFrameHost. Note that this does not affect navigations - // that have reached the "pending commit" stage, which are owned by their - // corresponding RenderFrameHosts instead. + // speculative RenderFrameHost (if there are no other navigations associated + // with it). Note that this does not affect navigations that have reached the + // "pending commit" stage, which are owned by their corresponding + // RenderFrameHosts instead. void ResetNavigationRequest(NavigationDiscardReason reason); // Similar to `ResetNavigationRequest()`, but keeps the state created by the
diff --git a/content/browser/renderer_host/media/fuchsia_media_codec_provider_impl.cc b/content/browser/renderer_host/media/fuchsia_media_codec_provider_impl.cc index 3ee1398..38ffb8a 100644 --- a/content/browser/renderer_host/media/fuchsia_media_codec_provider_impl.cc +++ b/content/browser/renderer_host/media/fuchsia_media_codec_provider_impl.cc
@@ -8,8 +8,10 @@ #include <lib/fit/function.h> #include <lib/sys/cpp/component_context.h> +#include "base/command_line.h" #include "base/fuchsia/fuchsia_logging.h" #include "base/fuchsia/process_context.h" +#include "media/base/media_switches.h" #include "media/base/supported_video_decoder_config.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -17,6 +19,34 @@ namespace { +absl::optional<std::string> GetMimeTypeForVideoCodec(media::VideoCodec codec) { + switch (codec) { + case media::VideoCodec::kH264: + return "video/h264"; + case media::VideoCodec::kVP8: + return "video/vp8"; + case media::VideoCodec::kVP9: + return "video/vp9"; + case media::VideoCodec::kHEVC: + return "video/hevc"; + case media::VideoCodec::kAV1: + return "video/av1"; + + case media::VideoCodec::kVC1: + case media::VideoCodec::kMPEG2: + case media::VideoCodec::kMPEG4: + case media::VideoCodec::kTheora: + case media::VideoCodec::kDolbyVision: + return absl::nullopt; + + case media::VideoCodec::kUnknown: + break; + } + + NOTREACHED(); + return absl::nullopt; +} + // fuchsia::mediacodec::CodecDescription does not provide enough codec info // to determine if a media::VideoDecoderConfig is supported. The constant and // the helper function below is to make a safe assumption that converts the type @@ -66,6 +96,61 @@ receivers_.Add(this, std::move(receiver)); } +// media::mojom::FuchsiaMediaCodecProvider implementation. +void FuchsiaMediaCodecProviderImpl::CreateVideoDecoder( + media::VideoCodec codec, + media::mojom::VideoDecoderSecureMemoryMode secure_mode, + fidl::InterfaceRequest<fuchsia::media::StreamProcessor> + stream_processor_request) { + fuchsia::mediacodec::CreateDecoder_Params decoder_params; + + // Set format details ordinal to 0. Decoder doesn't change the format, so + // the value doesn't matter. + decoder_params.mutable_input_details()->set_format_details_version_ordinal(0); + + auto mime_type = GetMimeTypeForVideoCodec(codec); + if (!mime_type) { + // Drop `stream_processor_request` if the codec is not supported. + return; + } + decoder_params.mutable_input_details()->set_mime_type(mime_type.value()); + + switch (secure_mode) { + case media::mojom::VideoDecoderSecureMemoryMode::CLEAR: + // Use defaults for non-secure mode. + break; + + case media::mojom::VideoDecoderSecureMemoryMode::SECURE: + decoder_params.set_secure_input_mode( + fuchsia::mediacodec::SecureMemoryMode::ON); + decoder_params.set_secure_output_mode( + fuchsia::mediacodec::SecureMemoryMode::ON); + break; + + case media::mojom::VideoDecoderSecureMemoryMode::CLEAR_INPUT: + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kForceProtectedVideoOutputBuffers)) { + decoder_params.set_secure_output_mode( + fuchsia::mediacodec::SecureMemoryMode::ON); + } + break; + } + + // Video demuxers return each video frame in a separate packet. This field + // must be set to get frame timestamps on the decoder output. + decoder_params.set_promise_separate_access_units_on_input(true); + + // We use `fuchsia.mediacodec` only for hardware decoders. Renderer will + // handle software decoding if hardware decoder is not available. + decoder_params.set_require_hw(true); + + auto decoder_factory = base::ComponentContextForProcess() + ->svc() + ->Connect<fuchsia::mediacodec::CodecFactory>(); + decoder_factory->CreateDecoder(std::move(decoder_params), + std::move(stream_processor_request)); +} + void FuchsiaMediaCodecProviderImpl::GetSupportedVideoDecoderConfigs( GetSupportedVideoDecoderConfigsCallback callback) { EnsureCodecFactory(); @@ -76,6 +161,8 @@ } } +// End of media::mojom::FuchsiaMediaCodecProvider implementation. + void FuchsiaMediaCodecProviderImpl::EnsureCodecFactory() { if (codec_factory_) return;
diff --git a/content/browser/renderer_host/media/fuchsia_media_codec_provider_impl.h b/content/browser/renderer_host/media/fuchsia_media_codec_provider_impl.h index 8bb18bd3..c728ed3a 100644 --- a/content/browser/renderer_host/media/fuchsia_media_codec_provider_impl.h +++ b/content/browser/renderer_host/media/fuchsia_media_codec_provider_impl.h
@@ -35,6 +35,11 @@ mojo::PendingReceiver<media::mojom::FuchsiaMediaCodecProvider> receiver); // media::mojom::FuchsiaMediaCodecProvider implementation. + void CreateVideoDecoder( + media::VideoCodec codec, + media::mojom::VideoDecoderSecureMemoryMode secure_mode, + fidl::InterfaceRequest<fuchsia::media::StreamProcessor> + stream_processor_request) final; void GetSupportedVideoDecoderConfigs( GetSupportedVideoDecoderConfigsCallback callback) final;
diff --git a/content/browser/renderer_host/media/media_resource_provider_fuchsia.cc b/content/browser/renderer_host/media/media_resource_provider_fuchsia.cc index a71650e5..9f60a19 100644 --- a/content/browser/renderer_host/media/media_resource_provider_fuchsia.cc +++ b/content/browser/renderer_host/media/media_resource_provider_fuchsia.cc
@@ -7,52 +7,14 @@ #include <fuchsia/mediacodec/cpp/fidl.h> #include <lib/sys/cpp/component_context.h> -#include "base/bind.h" -#include "base/command_line.h" -#include "base/fuchsia/process_context.h" -#include "content/public/browser/browser_context.h" #include "content/public/browser/provision_fetcher_factory.h" #include "content/public/browser/render_frame_host.h" -#include "content/public/browser/render_process_host.h" #include "content/public/browser/storage_partition.h" -#include "media/base/media_switches.h" #include "media/base/provision_fetcher.h" #include "media/fuchsia/cdm/service/fuchsia_cdm_manager.h" namespace content { -namespace { - -absl::optional<std::string> GetMimeTypeForVideoCodec(media::VideoCodec codec) { - switch (codec) { - case media::VideoCodec::kH264: - return "video/h264"; - case media::VideoCodec::kVP8: - return "video/vp8"; - case media::VideoCodec::kVP9: - return "video/vp9"; - case media::VideoCodec::kHEVC: - return "video/hevc"; - case media::VideoCodec::kAV1: - return "video/av1"; - - case media::VideoCodec::kVC1: - case media::VideoCodec::kMPEG2: - case media::VideoCodec::kMPEG4: - case media::VideoCodec::kTheora: - case media::VideoCodec::kDolbyVision: - return absl::nullopt; - - case media::VideoCodec::kUnknown: - break; - } - - NOTREACHED(); - return absl::nullopt; -} - -} // namespace - // static void MediaResourceProviderFuchsia::Bind( content::RenderFrameHost* frame_host, @@ -91,58 +53,4 @@ key_system, origin(), std::move(create_fetcher_cb), std::move(request)); } -void MediaResourceProviderFuchsia::CreateVideoDecoder( - media::VideoCodec codec, - media::mojom::VideoDecoderSecureMemoryMode secure_mode, - fidl::InterfaceRequest<fuchsia::media::StreamProcessor> - stream_processor_request) { - fuchsia::mediacodec::CreateDecoder_Params decoder_params; - - // Set format details ordinal to 0. Decoder doesn't change the format, so - // the value doesn't matter. - decoder_params.mutable_input_details()->set_format_details_version_ordinal(0); - - auto mime_type = GetMimeTypeForVideoCodec(codec); - if (!mime_type) { - // Drop `stream_processor_request` if the codec is not supported. - return; - } - decoder_params.mutable_input_details()->set_mime_type(mime_type.value()); - - switch (secure_mode) { - case media::mojom::VideoDecoderSecureMemoryMode::CLEAR: - // Use defaults for non-secure mode. - break; - - case media::mojom::VideoDecoderSecureMemoryMode::SECURE: - decoder_params.set_secure_input_mode( - fuchsia::mediacodec::SecureMemoryMode::ON); - decoder_params.set_secure_output_mode( - fuchsia::mediacodec::SecureMemoryMode::ON); - break; - - case media::mojom::VideoDecoderSecureMemoryMode::CLEAR_INPUT: - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kForceProtectedVideoOutputBuffers)) { - decoder_params.set_secure_output_mode( - fuchsia::mediacodec::SecureMemoryMode::ON); - } - break; - } - - // Video demuxers return each video frame in a separate packet. This field - // must be set to get frame timestamps on the decoder output. - decoder_params.set_promise_separate_access_units_on_input(true); - - // We use `fuchsia.mediacodec` only for hardware decoders. Renderer will - // handle software decoding if hardware decoder is not available. - decoder_params.set_require_hw(true); - - auto decoder_factory = base::ComponentContextForProcess() - ->svc() - ->Connect<fuchsia::mediacodec::CodecFactory>(); - decoder_factory->CreateDecoder(std::move(decoder_params), - std::move(stream_processor_request)); -} - } // namespace content
diff --git a/content/browser/renderer_host/media/media_resource_provider_fuchsia.h b/content/browser/renderer_host/media/media_resource_provider_fuchsia.h index 4acb5075..55bd4c7 100644 --- a/content/browser/renderer_host/media/media_resource_provider_fuchsia.h +++ b/content/browser/renderer_host/media/media_resource_provider_fuchsia.h
@@ -36,11 +36,6 @@ const std::string& key_system, fidl::InterfaceRequest<fuchsia::media::drm::ContentDecryptionModule> request) final; - void CreateVideoDecoder( - media::VideoCodec codec, - media::mojom::VideoDecoderSecureMemoryMode secure_mode, - fidl::InterfaceRequest<fuchsia::media::StreamProcessor> - stream_processor_request) final; }; } // namespace content
diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc index 99ffae0b..c08dd18 100644 --- a/content/browser/renderer_host/media/media_stream_manager.cc +++ b/content/browser/renderer_host/media/media_stream_manager.cc
@@ -727,7 +727,12 @@ MediaStreamRequestType request_type, const StreamControls& stream_controls, MediaDeviceSaltAndOrigin salt_and_origin, - DeviceStoppedCallback device_stopped_cb = DeviceStoppedCallback()) + DeviceStoppedCallback device_stopped_cb = DeviceStoppedCallback(), + DeviceChangedCallback device_changed_cb = DeviceChangedCallback(), + DeviceRequestStateChangeCallback device_request_state_change_cb = + DeviceRequestStateChangeCallback(), + DeviceCaptureHandleChangeCallback device_capture_handle_change_cb = + DeviceCaptureHandleChangeCallback()) : requesting_process_id(requesting_process_id), requesting_frame_id(requesting_frame_id), requester_id(requester_id), @@ -737,6 +742,11 @@ std::move(audio_stream_selection_info_ptr)), salt_and_origin(std::move(salt_and_origin)), device_stopped_cb(std::move(device_stopped_cb)), + device_changed_cb(std::move(device_changed_cb)), + device_request_state_change_cb( + std::move(device_request_state_change_cb)), + device_capture_handle_change_cb( + std::move(device_capture_handle_change_cb)), should_stop_in_future_( /*size=*/static_cast<size_t>(MediaStreamType::NUM_MEDIA_TYPES), /*value=*/false), @@ -753,6 +763,12 @@ video_type_(MediaStreamType::NO_SERVICE), target_process_id_(-1), target_frame_id_(-1) { + DCHECK(request_type == blink::MEDIA_GENERATE_STREAM || + request_type == blink::MEDIA_GET_OPEN_DEVICE || + (device_changed_cb.is_null() && + device_request_state_change_cb.is_null() && + device_capture_handle_change_cb.is_null())); + SendLogMessage(base::StringPrintf( "DR::DeviceRequest({requesting_process_id=%d}, " "{requesting_frame_id=%d}, {requester_id=%d}, {request_type=%s})", @@ -1319,10 +1335,10 @@ DCHECK_CURRENTLY_ON(BrowserThread::IO); SendLogMessage(GetGenerateStreamsLogString(render_process_id, render_frame_id, requester_id, page_request_id)); - std::unique_ptr<DeviceRequest> request = CreateDeviceRequest( + std::unique_ptr<DeviceRequest> request = std::make_unique<DeviceRequest>( render_process_id, render_frame_id, requester_id, page_request_id, - controls, blink::MEDIA_GENERATE_STREAM, std::move(salt_and_origin), user_gesture, std::move(audio_stream_selection_info_ptr), + blink::MEDIA_GENERATE_STREAM, controls, std::move(salt_and_origin), std::move(device_stopped_cb), std::move(device_changed_cb), std::move(device_request_state_change_cb), std::move(device_capture_handle_change_cb)); @@ -1369,11 +1385,11 @@ DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(base::FeatureList::IsEnabled(features::kMediaStreamTrackTransfer)); - std::unique_ptr<DeviceRequest> request = CreateDeviceRequest( + std::unique_ptr<DeviceRequest> request = std::make_unique<DeviceRequest>( render_process_id, render_frame_id, requester_id, page_request_id, - StreamControls(), blink::MEDIA_GET_OPEN_DEVICE, - std::move(salt_and_origin), /*user_gesture=*/false, - /*audio_stream_selection_info_ptr=*/nullptr, std::move(device_stopped_cb), + /*user_gesture=*/false, /*audio_stream_selection_info_ptr=*/nullptr, + blink::MEDIA_GET_OPEN_DEVICE, StreamControls(), + std::move(salt_and_origin), std::move(device_stopped_cb), std::move(device_changed_cb), std::move(device_request_state_change_cb), std::move(device_capture_handle_change_cb)); @@ -1901,36 +1917,6 @@ request_video_input, label)); } -std::unique_ptr<MediaStreamManager::DeviceRequest> -MediaStreamManager::CreateDeviceRequest( - int render_process_id, - int render_frame_id, - int requester_id, - int page_request_id, - const blink::StreamControls& controls, - blink::MediaStreamRequestType type, - MediaDeviceSaltAndOrigin salt_and_origin, - bool user_gesture, - blink::mojom::StreamSelectionInfoPtr audio_stream_selection_info_ptr, - DeviceStoppedCallback device_stopped_cb, - DeviceChangedCallback device_changed_cb, - DeviceRequestStateChangeCallback device_request_state_change_cb, - DeviceCaptureHandleChangeCallback device_capture_handle_change_cb) { - DCHECK(type == blink::MEDIA_GENERATE_STREAM || - type == blink::MEDIA_GET_OPEN_DEVICE); - - auto request = std::make_unique<DeviceRequest>( - render_process_id, render_frame_id, requester_id, page_request_id, - user_gesture, std::move(audio_stream_selection_info_ptr), type, controls, - std::move(salt_and_origin), std::move(device_stopped_cb)); - request->device_changed_cb = std::move(device_changed_cb); - request->device_request_state_change_cb = - std::move(device_request_state_change_cb); - request->device_capture_handle_change_cb = - std::move(device_capture_handle_change_cb); - return request; -} - std::string MediaStreamManager::AddRequest( std::unique_ptr<DeviceRequest> request) { DCHECK_CURRENTLY_ON(BrowserThread::IO);
diff --git a/content/browser/renderer_host/media/media_stream_manager.h b/content/browser/renderer_host/media/media_stream_manager.h index 9b9da35c..0c90782 100644 --- a/content/browser/renderer_host/media/media_stream_manager.h +++ b/content/browser/renderer_host/media/media_stream_manager.h
@@ -508,25 +508,6 @@ MediaStreamProvider* GetDeviceManager( blink::mojom::MediaStreamType stream_type) const; void StartEnumeration(DeviceRequest* request, const std::string& label); - // Creates and returns a DeviceRequest of type |type|. |type| should be either - // blink::MEDIA_GENERATE_STREAM or blink::MEDIA_GET_OPEN_DEVICE. - // TODO(crbug.com/1288839): Once all device-related callbacks are packed in a - // single struct, delete this function and replace its usage with - // make_unique<DeviceRequest> calls. - static std::unique_ptr<DeviceRequest> CreateDeviceRequest( - int render_process_id, - int render_frame_id, - int requester_id, - int page_request_id, - const blink::StreamControls& controls, - blink::MediaStreamRequestType type, - MediaDeviceSaltAndOrigin salt_and_origin, - bool user_gesture, - blink::mojom::StreamSelectionInfoPtr audio_stream_selection_info_ptr, - DeviceStoppedCallback device_stopped_cb, - DeviceChangedCallback device_changed_cb, - DeviceRequestStateChangeCallback device_request_state_change_cb, - DeviceCaptureHandleChangeCallback device_capture_handle_change_cb); std::string AddRequest(std::unique_ptr<DeviceRequest> request); DeviceRequest* FindRequest(const std::string& label) const; // Clones an existing device identified by |existing_device_session_id| and
diff --git a/content/browser/renderer_host/navigation_controller_impl_browsertest.cc b/content/browser/renderer_host/navigation_controller_impl_browsertest.cc index b53ccaffa..0a1f6c7 100644 --- a/content/browser/renderer_host/navigation_controller_impl_browsertest.cc +++ b/content/browser/renderer_host/navigation_controller_impl_browsertest.cc
@@ -22184,6 +22184,64 @@ EXPECT_FALSE(a3_navigation.was_committed()); } +// Tests that calling FrameTreeNode::ResetNavigationRequest() cancels the +// navigation owned by the FrameTreeNode but won't reset a speculative RFH that +// has a pending commit navigation, even if it was used by the deleted +// navigation. +IN_PROC_BROWSER_TEST_P(NavigationControllerBrowserTest, + ResetNavigationRequestWontDeletePendingCommitRFH) { + GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html")); + GURL url_b1(embedded_test_server()->GetURL("b.com", "/title1.html")); + GURL url_b2(embedded_test_server()->GetURL("b.com", "/title2.html")); + // Load `main_url`. + EXPECT_TRUE(NavigateToURL(shell(), main_url)); + FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) + ->GetPrimaryFrameTree() + .root(); + RenderFrameHostImplWrapper rfh_a(current_main_frame_host()); + + // Start the cross-site navigation to `url_b1`. Then, start a cross-site + // navigation to `url_b2` after the `url_b1` navigation is in the + // "pending commit" stage, so that both navigations can exist at the same + // time (the previous NavigationRequest had already been moved to the + //"pending commit" speculative RFH, and they both use the same speculative + // RFH). + TestNavigationManager b1_nav(shell()->web_contents(), url_b1); + TestNavigationManager b2_nav(shell()->web_contents(), url_b2); + // Start the navigation to `url_b1` then drop its DidCommit message from the + // renderer, so that it will stay in the "pending commit" stage for the rest + // of the test. Then, start a navigation to `url_b2`. + DidCommitNavigationCanceller ignore_b1_commit( + shell()->web_contents(), url_b1, + base::BindLambdaForTesting([&]() { shell()->LoadURL(url_b2); })); + shell()->LoadURL(url_b1); + // Assert tht the `url_b1` navigation had started. + EXPECT_TRUE(b1_nav.WaitForResponse()); + EXPECT_EQ(b1_nav.GetNavigationHandle(), root->navigation_request()); + + b1_nav.ResumeNavigation(); + // Assert that the `url_b2` navigation had started, and didn't cancel the + // `url_b1` navigation. + EXPECT_TRUE(b2_nav.WaitForRequestStart()); + EXPECT_EQ(b2_nav.GetNavigationHandle(), root->navigation_request()); + EXPECT_TRUE(b1_nav.GetNavigationHandle()); + + // Cancel the navigation to `url_b2` by calling ResetNavigationRequest(). + // This shouldn't cancel the navigation to `url_b1`. + root->ResetNavigationRequest(NavigationDiscardReason::kCancelled); + b2_nav.WaitForNavigationFinished(); + EXPECT_FALSE(b2_nav.was_committed()); + EXPECT_FALSE(b2_nav.GetNavigationHandle()); + + // Assert that the `url_b1` navigation and the speculative RenderFrameHost is + // still around. Note that we can't wait for the navigation to finish here + // because we've dropped the DidCommit message for this navigation. + EXPECT_TRUE(b1_nav.GetNavigationHandle()); + EXPECT_TRUE(root->render_manager()->speculative_frame_host()); + EXPECT_EQ(b1_nav.GetNavigationHandle()->GetRenderFrameHost(), + root->render_manager()->speculative_frame_host()); +} + INSTANTIATE_TEST_SUITE_P( All, NavigationControllerAlertDialogBrowserTest,
diff --git a/content/browser/renderer_host/page_lifecycle_state_manager.h b/content/browser/renderer_host/page_lifecycle_state_manager.h index 4c9f41a..f73e821 100644 --- a/content/browser/renderer_host/page_lifecycle_state_manager.h +++ b/content/browser/renderer_host/page_lifecycle_state_manager.h
@@ -118,7 +118,7 @@ blink::mojom::PagehideDispatch pagehide_dispatch_ = blink::mojom::PagehideDispatch::kNotDispatched; - raw_ptr<RenderViewHostImpl> render_view_host_impl_; + const raw_ptr<RenderViewHostImpl> render_view_host_impl_; // This is the per-page state computed based on web contents / tab lifecycle // states, i.e. |is_set_frozen_called_|, |is_in_back_forward_cache_| and
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc index bba11fe..d27e145d 100644 --- a/content/browser/renderer_host/render_frame_host_impl.cc +++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -10268,8 +10268,6 @@ // A prerendered page is identified by its root FrameTreeNode id, so if this // RenderFrameHost is in any way embedded, we need to iterate up to the // prerender root. - // TODO(https://crbug.com/1363996): Move the devtools logic to - // PrerenderHostRegistry, as it knows the detailed cancellation reason now. FrameTreeNode* outermost_frame = GetOutermostMainFrameOrEmbedder()->frame_tree_node(); PrerenderHost* prerender_host = @@ -10285,19 +10283,6 @@ // prerendering, as it could mean an interface request is never resolved for // an active page. DCHECK(canceled); - - FrameTreeNode* prerender_initiator_frame = FrameTreeNode::GloballyFindByID( - prerender_host->initiator_frame_tree_node_id()); - // The prerender initiator frame is used to report the cancellation to - // DevTools. When a prerender is canceled, we use the prerender initiator - // frame's DevTools agent instead of the cancelled prerendered frame's. This - // is because DevTools agent gets attached to a frame when it becomes active, - // so a canceled prerendered frame won't have a Devtools agent attached. - if (prerender_initiator_frame) { - devtools_instrumentation::DidCancelPrerender( - prerender_host->prerendering_url(), prerender_initiator_frame, - PrerenderFinalStatus::kMojoBinderPolicy, interface_name); - } } void RenderFrameHostImpl::RendererWillActivateForPrerendering() {
diff --git a/content/browser/renderer_host/render_frame_host_manager.cc b/content/browser/renderer_host/render_frame_host_manager.cc index bd0c76f..7436b8a 100644 --- a/content/browser/renderer_host/render_frame_host_manager.cc +++ b/content/browser/renderer_host/render_frame_host_manager.cc
@@ -1640,13 +1640,12 @@ frame_tree_node_->navigation_request()->set_net_error(net::ERR_ABORTED); frame_tree_node_->ResetNavigationRequest( NavigationDiscardReason::kRenderProcessGone); - } else { - // If we are far enough into the navigation that - // TransferNavigationRequestOwnership has already been called then the - // FrameTreeNode no longer owns the NavigationRequest and we need to clean - // up the speculative RenderFrameHost. - DiscardSpeculativeRFH(NavigationDiscardReason::kRenderProcessGone); } + // It's possible that we are far enough into the navigation that + // TransferNavigationRequestOwnership has already been called then the + // FrameTreeNode no longer owns the NavigationRequest and we need to clean + // up the speculative RenderFrameHost. + DiscardSpeculativeRFH(NavigationDiscardReason::kRenderProcessGone); } } @@ -3622,13 +3621,6 @@ // order to receive the IPC. DCHECK(pending_rfh->IsRenderFrameLive()); - // We should not have a pending bfcache entry unless bfcache or prerendering - // is enabled. Note that in prerendering, the prerendering page information is - // stored in `pending_stored_page` prior to activating the page - // (despite the "bfcache" name). - DCHECK(!pending_stored_page || IsBackForwardCacheEnabled() || - blink::features::IsPrerender2Enabled()); - #if BUILDFLAG(IS_MAC) // The old RenderWidgetHostView will be hidden before the new // RenderWidgetHostView takes its contents. Ensure that Cocoa sees this as
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index a07e4a3..72d890f 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -221,7 +221,9 @@ #include "content/browser/font_service.h" // nogncheck #include "third_party/blink/public/mojom/memory_usage_monitor_linux.mojom.h" // nogncheck +#include "content/browser/media/video_encode_accelerator_provider_launcher.h" #include "content/public/browser/stable_video_decoder_factory.h" +#include "media/mojo/mojom/video_encode_accelerator.mojom.h" #endif #if BUILDFLAG(IS_MAC) @@ -1230,7 +1232,26 @@ ConnectToFontService(std::move(font_receiver)); return; } -#endif + + if (base::FeatureList::IsEnabled(media::kUseOutOfProcessVideoEncoding)) { + if (auto r = + receiver.As<media::mojom::VideoEncodeAcceleratorProvider>()) { + if (!video_encode_accelerator_factory_remote_.is_bound()) { + LaunchVideoEncodeAcceleratorProviderFactory( + video_encode_accelerator_factory_remote_ + .BindNewPipeAndPassReceiver()); + video_encode_accelerator_factory_remote_.reset_on_disconnect(); + } + + if (!video_encode_accelerator_factory_remote_.is_bound()) + return; + + video_encode_accelerator_factory_remote_ + ->CreateVideoEncodeAcceleratorProvider(std::move(r)); + return; + } + } +#endif // (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) #if BUILDFLAG(IS_WIN) if (auto r = receiver.As<mojom::FontCacheWin>()) { @@ -1294,6 +1315,11 @@ const base::WeakPtr<RenderProcessHostImpl> weak_host_; std::unique_ptr<service_manager::BinderRegistry> binders_; mojo::Receiver<mojom::ChildProcessHost> receiver_{this}; + +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) + mojo::Remote<media::mojom::VideoEncodeAcceleratorProviderFactory> + video_encode_accelerator_factory_remote_; +#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) }; // static
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h index 036d20f5..9b677de 100644 --- a/content/browser/renderer_host/render_process_host_impl.h +++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -627,6 +627,14 @@ void BindPushMessaging( mojo::PendingReceiver<blink::mojom::PushMessaging> receiver); +#if BUILDFLAG(IS_FUCHSIA) + // Binds |receiver| to the FuchsiaMediaCodecProvider instance owned by the + // render process host, and is used by workers via BrowserInterfaceBroker. + void BindMediaCodecProvider( + mojo::PendingReceiver<media::mojom::FuchsiaMediaCodecProvider> receiver) + override; +#endif + // Binds |receiver| to a OneShotBackgroundSyncService instance owned by the // StoragePartition associated with the render process host, and is used by // frames and service workers via BrowserInterfaceBroker. @@ -837,10 +845,6 @@ void BindPluginRegistry( mojo::PendingReceiver<blink::mojom::PluginRegistry> receiver); #endif -#if BUILDFLAG(IS_FUCHSIA) - void BindMediaCodecProvider( - mojo::PendingReceiver<media::mojom::FuchsiaMediaCodecProvider> receiver); -#endif // blink::mojom::DomStorageProvider: void BindDomStorage(
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 6d5e376..716fb529 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -78,6 +78,7 @@ #include "content/browser/preloading/prerender/prerender_final_status.h" #include "content/browser/preloading/prerender/prerender_host_registry.h" #include "content/browser/preloading/prerender/prerender_metrics.h" +#include "content/browser/preloading/prerender/prerender_new_tab_handle.h" #include "content/browser/renderer_host/agent_scheduling_group_host.h" #include "content/browser/renderer_host/cross_process_frame_connector.h" #include "content/browser/renderer_host/frame_token_message_queue.h" @@ -3996,17 +3997,41 @@ params.pip_options->lock_aspect_ratio; } + // Check whether there is an available prerendered page for this navigation if + // this is not for guest. If it exists, take WebContents pre-created for + // hosting the prerendered page instead of creating new WebContents. + // TODO(crbug.com/1350676): Instead of filtering out the guest case here, + // check it and drop prerender requests before starting prerendering. std::unique_ptr<WebContentsImpl> new_contents; - if (!is_guest) { - create_params.context = view_->GetNativeView(); - new_contents = WebContentsImpl::Create(create_params); - } else { - new_contents = GetBrowserPluginGuest()->CreateNewGuestWindow(create_params); + if (base::FeatureList::IsEnabled(blink::features::kPrerender2InNewTab) && + !is_guest) { + new_contents = + GetPrerenderHostRegistry()->TakePreCreatedWebContentsForNewTabIfExists( + params, create_params); + if (new_contents) { + // The SiteInstance of the pre-created WebContents should be in a + // different BrowsingInstance from the source SiteInstance, while they + // should be in the same StoragePartition. + SiteInstanceImpl* new_site_instance = new_contents->GetSiteInstance(); + DCHECK(!new_site_instance->IsRelatedSiteInstance(source_site_instance)); + DCHECK_EQ(new_site_instance->GetStoragePartitionConfig(), + source_site_instance->GetStoragePartitionConfig()); + } } - auto* new_contents_impl = new_contents.get(); - new_contents_impl->GetController().SetSessionStorageNamespace( - partition_config, session_storage_namespace); + if (!new_contents) { + if (!is_guest) { + create_params.context = view_->GetNativeView(); + new_contents = WebContentsImpl::Create(create_params); + } else { + new_contents = + GetBrowserPluginGuest()->CreateNewGuestWindow(create_params); + } + new_contents->GetController().SetSessionStorageNamespace( + partition_config, session_storage_namespace); + } + + auto* new_contents_impl = new_contents.get(); // If the new frame has a name, make sure any SiteInstances that can find // this named frame have proxies for it. Must be called after
diff --git a/content/browser/worker_host/dedicated_worker_host.cc b/content/browser/worker_host/dedicated_worker_host.cc index 03f11e68..88b6228 100644 --- a/content/browser/worker_host/dedicated_worker_host.cc +++ b/content/browser/worker_host/dedicated_worker_host.cc
@@ -56,10 +56,6 @@ #include "third_party/blink/public/common/tokens/tokens.h" #include "third_party/blink/public/mojom/loader/fetch_client_settings_object.mojom.h" -#if BUILDFLAG(IS_FUCHSIA) -#include "content/browser/renderer_host/media/media_resource_provider_fuchsia.h" -#endif - namespace content { DedicatedWorkerHost::DedicatedWorkerHost( @@ -767,24 +763,6 @@ } #endif -#if BUILDFLAG(IS_FUCHSIA) -void DedicatedWorkerHost::BindFuchsiaMediaResourceProvider( - mojo::PendingReceiver<media::mojom::FuchsiaMediaResourceProvider> - receiver) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - RenderFrameHostImpl* ancestor_render_frame_host = - RenderFrameHostImpl::FromID(ancestor_render_frame_host_id_); - if (!ancestor_render_frame_host) { - // The ancestor frame may have already been closed. In that case, the worker - // will soon be terminated too, so abort the connection. - return; - } - - MediaResourceProviderFuchsia::Bind(ancestor_render_frame_host, - std::move(receiver)); -} -#endif // BUILDFLAG(IS_FUCHSIA) - void DedicatedWorkerHost::CreateBucketManagerHost( mojo::PendingReceiver<blink::mojom::BucketManagerHost> receiver) { GetProcessHost()->BindBucketManagerHost(GetWeakPtr(), std::move(receiver));
diff --git a/content/browser/worker_host/dedicated_worker_host.h b/content/browser/worker_host/dedicated_worker_host.h index 3995641..0600560 100644 --- a/content/browser/worker_host/dedicated_worker_host.h +++ b/content/browser/worker_host/dedicated_worker_host.h
@@ -48,10 +48,6 @@ #include "third_party/blink/public/mojom/serial/serial.mojom-forward.h" #endif -#if BUILDFLAG(IS_FUCHSIA) -#include "media/fuchsia/mojom/fuchsia_media_resource_provider.mojom.h" -#endif - namespace network { struct CrossOriginEmbedderPolicy; @@ -155,11 +151,6 @@ void BindSerialService( mojo::PendingReceiver<blink::mojom::SerialService> receiver); #endif -#if BUILDFLAG(IS_FUCHSIA) - void BindFuchsiaMediaResourceProvider( - mojo::PendingReceiver<media::mojom::FuchsiaMediaResourceProvider> - receiver); -#endif // PlzDedicatedWorker: void StartScriptLoad(
diff --git a/content/gpu/gpu_service_factory.cc b/content/gpu/gpu_service_factory.cc index 1788987c..00d0f79 100644 --- a/content/gpu/gpu_service_factory.cc +++ b/content/gpu/gpu_service_factory.cc
@@ -10,6 +10,7 @@ #include "base/task/single_thread_task_runner.h" #include "base/task/thread_pool.h" #include "build/build_config.h" +#include "gpu/ipc/service/gpu_memory_buffer_factory.h" #include "media/media_buildflags.h" #if BUILDFLAG(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn index b7864d0..f2beaef 100644 --- a/content/public/browser/BUILD.gn +++ b/content/public/browser/BUILD.gn
@@ -598,6 +598,7 @@ if (is_fuchsia) { sources += [ "ax_inspect_factory_fuchsia.cc" ] + deps += [ "//media/fuchsia/mojom:fuchsia_media_resource_provider" ] } if (is_win) {
diff --git a/content/public/browser/devtools_background_services_context.h b/content/public/browser/devtools_background_services_context.h index 65db294..90abc27d 100644 --- a/content/public/browser/devtools_background_services_context.h +++ b/content/public/browser/devtools_background_services_context.h
@@ -11,9 +11,9 @@ #include "content/common/content_export.h" -namespace url { -class Origin; -} // namespace url +namespace blink { +class StorageKey; +} // namespace blink namespace content { @@ -46,13 +46,14 @@ virtual bool IsRecording(DevToolsBackgroundService service) = 0; // Logs the event if recording for |service| is enabled. + // |storage_key| refers to the storage partition the event belongs to. // |event_name| is a description of the event. // |instance_id| is for tracking events related to the same feature instance. // Any additional useful information relating to the feature can be sent via // |event_metadata|. Called from the UI thread. virtual void LogBackgroundServiceEvent( uint64_t service_worker_registration_id, - const url::Origin& origin, + blink::StorageKey storage_key, DevToolsBackgroundService service, const std::string& event_name, const std::string& instance_id,
diff --git a/content/public/browser/render_process_host.h b/content/public/browser/render_process_host.h index 4eb9778..d23c5cc 100644 --- a/content/public/browser/render_process_host.h +++ b/content/public/browser/render_process_host.h
@@ -58,6 +58,10 @@ #include "media/mojo/mojom/stable/stable_video_decoder.mojom-forward.h" #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) +#if BUILDFLAG(IS_FUCHSIA) +#include "media/fuchsia/mojom/fuchsia_media_resource_provider.mojom-forward.h" +#endif + class GURL; namespace base { @@ -599,6 +603,11 @@ receiver) = 0; virtual void BindVideoDecodePerfHistory( mojo::PendingReceiver<media::mojom::VideoDecodePerfHistory> receiver) = 0; +#if BUILDFLAG(IS_FUCHSIA) + virtual void BindMediaCodecProvider( + mojo::PendingReceiver<media::mojom::FuchsiaMediaCodecProvider> + receiver) = 0; +#endif virtual void CreateOneShotSyncService( const url::Origin& origin, mojo::PendingReceiver<blink::mojom::OneShotBackgroundSyncService>
diff --git a/content/public/test/mock_render_process_host.h b/content/public/test/mock_render_process_host.h index ec86363..2465c5b7 100644 --- a/content/public/test/mock_render_process_host.h +++ b/content/public/test/mock_render_process_host.h
@@ -242,6 +242,11 @@ const blink::StorageKey& storage_key, mojo::PendingReceiver<blink::mojom::QuotaManagerHost> receiver) override { } +#if BUILDFLAG(IS_FUCHSIA) + void BindMediaCodecProvider( + mojo::PendingReceiver<media::mojom::FuchsiaMediaCodecProvider> receiver) + override {} +#endif void CreateLockManager( const blink::StorageKey& storage_key, mojo::PendingReceiver<blink::mojom::LockManager> receiver) override {}
diff --git a/content/public/test/prerender_test_util.cc b/content/public/test/prerender_test_util.cc index 711bc6a..ea82bc3 100644 --- a/content/public/test/prerender_test_util.cc +++ b/content/public/test/prerender_test_util.cc
@@ -38,6 +38,19 @@ document.head.appendChild(script); })"; +constexpr char kAddSpeculationRuleWithTargetHintScript[] = R"({ + const script = document.createElement('script'); + script.type = 'speculationrules'; + script.text = `{ + "prerender": [{ + "source": "list", + "urls": [$1], + "target_hint": $2 + }] + }`; + document.head.appendChild(script); + })"; + PrerenderHostRegistry& GetPrerenderHostRegistry(WebContents* web_contents) { EXPECT_TRUE(content::BrowserThread::CurrentlyOn(BrowserThread::UI)); return *static_cast<WebContentsImpl*>(web_contents) @@ -339,6 +352,22 @@ base::UTF8ToUTF16(script), base::NullCallback()); } +void PrerenderTestHelper::AddPrerenderWithTargetHintAsync( + const GURL& prerendering_url, + const std::string& target_hint) { + TRACE_EVENT("test", "PrerenderTestHelper::AddPrerenderWithTargetHintAsync", + "prerendering_url", prerendering_url, "target_hint", target_hint); + EXPECT_TRUE(content::BrowserThread::CurrentlyOn(BrowserThread::UI)); + std::string script = JsReplace(kAddSpeculationRuleWithTargetHintScript, + prerendering_url, target_hint); + + // Have to use ExecuteJavaScriptForTests instead of ExecJs/EvalJs here, + // because some test pages have ContentSecurityPolicy and EvalJs cannot work + // with it. See the quick migration guide for EvalJs for more information. + GetWebContents()->GetPrimaryMainFrame()->ExecuteJavaScriptForTests( + base::UTF8ToUTF16(script), base::NullCallback()); +} + std::unique_ptr<PrerenderHandle> PrerenderTestHelper::AddEmbedderTriggeredPrerenderAsync( const GURL& prerendering_url,
diff --git a/content/public/test/prerender_test_util.h b/content/public/test/prerender_test_util.h index 34203ebd..634e53ae 100644 --- a/content/public/test/prerender_test_util.h +++ b/content/public/test/prerender_test_util.h
@@ -129,6 +129,8 @@ // the completion of prerendering. int AddPrerender(const GURL& prerendering_url); void AddPrerenderAsync(const GURL& prerendering_url); + void AddPrerenderWithTargetHintAsync(const GURL& prerendering_url, + const std::string& target_hint); // Adds multiple URLs to the speculation rules at the same time. This function // doesn't wait for the completion of prerendering.
diff --git a/content/renderer/media/media_factory.cc b/content/renderer/media/media_factory.cc index 79eb20c..b9e7ba8 100644 --- a/content/renderer/media/media_factory.cc +++ b/content/renderer/media/media_factory.cc
@@ -826,13 +826,13 @@ external_decoder_factory = std::make_unique<media::MojoDecoderFactory>(interface_factory); #elif BUILDFLAG(IS_FUCHSIA) - mojo::PendingRemote<media::mojom::FuchsiaMediaResourceProvider> - media_resource_provider; + mojo::PendingRemote<media::mojom::FuchsiaMediaCodecProvider> + media_codec_provider; interface_broker_->GetInterface( - media_resource_provider.InitWithNewPipeAndPassReceiver()); + media_codec_provider.InitWithNewPipeAndPassReceiver()); external_decoder_factory = std::make_unique<media::FuchsiaDecoderFactory>( - std::move(media_resource_provider), /*allow_overlay=*/true); + std::move(media_codec_provider), /*allow_overlay=*/true); #endif decoder_factory_ = std::make_unique<media::DefaultDecoderFactory>( std::move(external_decoder_factory));
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index fae03026..411d630 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -1091,8 +1091,18 @@ mojo::PendingRemote<media::mojom::VideoEncodeAcceleratorProvider> vea_provider; + +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) + if (base::FeatureList::IsEnabled(media::kUseOutOfProcessVideoEncoding)) { + BindHostReceiver(vea_provider.InitWithNewPipeAndPassReceiver()); + } else { + gpu_->CreateVideoEncodeAcceleratorProvider( + vea_provider.InitWithNewPipeAndPassReceiver()); + } +#else gpu_->CreateVideoEncodeAcceleratorProvider( vea_provider.InitWithNewPipeAndPassReceiver()); +#endif gpu_factories_.push_back(GpuVideoAcceleratorFactoriesImpl::Create( std::move(gpu_channel_host),
diff --git a/content/utility/BUILD.gn b/content/utility/BUILD.gn index 5db9a92..c23c361 100644 --- a/content/utility/BUILD.gn +++ b/content/utility/BUILD.gn
@@ -99,13 +99,9 @@ deps += [ "//gpu/config", "//media/gpu/sandbox", + "//media/mojo/services", "//third_party/angle:angle_gpu_info_util", ] - - if ((is_linux || is_chromeos_ash) && (use_vaapi || use_v4l2_codec)) { - # To allow creating media::StableVideoDecoderFactoryService objects. - deps += [ "//media/mojo/services" ] - } } if (is_chromeos_ash && is_chrome_branded) {
diff --git a/content/utility/services.cc b/content/utility/services.cc index 8a573d13..d095345 100644 --- a/content/utility/services.cc +++ b/content/utility/services.cc
@@ -65,6 +65,7 @@ #endif // BUILDFLAG(IS_WIN) #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) +#include "media/mojo/services/mojo_video_encode_accelerator_provider_factory.h" #include "sandbox/linux/services/libc_interceptor.h" #include "sandbox/policy/mojom/sandbox.mojom.h" #include "sandbox/policy/sandbox_type.h" @@ -323,6 +324,17 @@ #endif // (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_ASH)) && // (BUILDFLAG(USE_VAAPI) || BUILDFLAG(USE_V4L2_CODEC)) +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) +auto RunVideoEncodeAcceleratorProviderFactory( + mojo::PendingReceiver<media::mojom::VideoEncodeAcceleratorProviderFactory> + receiver) { + auto factory = + std::make_unique<media::MojoVideoEncodeAcceleratorProviderFactory>(); + factory->BindReceiver(std::move(receiver)); + return factory; +} +#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) + } // namespace void RegisterIOThreadServices(mojo::ServiceFactory& services) { @@ -371,6 +383,10 @@ #endif // (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_ASH)) && // (BUILDFLAG(USE_VAAPI) || BUILDFLAG(USE_V4L2_CODEC)) +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) + services.Add(RunVideoEncodeAcceleratorProviderFactory); +#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) + #if BUILDFLAG(ENABLE_ACCESSIBILITY_SERVICE) if (::features::IsAccessibilityServiceEnabled()) services.Add(RunAccessibilityService);
diff --git a/docs/how_to_add_your_feature_flag.md b/docs/how_to_add_your_feature_flag.md index d04e6df1..ec9e039 100644 --- a/docs/how_to_add_your_feature_flag.md +++ b/docs/how_to_add_your_feature_flag.md
@@ -60,7 +60,7 @@ ## Step 2: Adding the feature flag to the chrome://flags UI. *** promo -Googlers: Read also [Chrome Feature Flag in chrome://flags](http/go/finch-feature-api#chrome-feature-flag-in-chromeflags). +Googlers: Read also [Chrome Feature Flag in chrome://flags](http://go/finch-feature-api#chrome-feature-flag-in-chromeflags). *** *** promo
diff --git a/docs/user_handle_mapping.md b/docs/user_handle_mapping.md index c4a53da..9ea5e1b 100644 --- a/docs/user_handle_mapping.md +++ b/docs/user_handle_mapping.md
@@ -11,6 +11,7 @@ | dbaron | ldavidbaron | | dom | domfarolino | | dougt | dft | +| dsv | dsv, danilsomsikov | | eaugusti | eaugustine | | eroman | ericroman | | evan | evanm |
diff --git a/extensions/browser/api/management/management_api.cc b/extensions/browser/api/management/management_api.cc index d2e2f08..b4427c47 100644 --- a/extensions/browser/api/management/management_api.cc +++ b/extensions/browser/api/management/management_api.cc
@@ -350,8 +350,8 @@ return; } - const base::DictionaryValue* parsed_manifest; - if (!result->GetAsDictionary(&parsed_manifest)) { + const base::Value::Dict* parsed_manifest = result->GetIfDict(); + if (!parsed_manifest) { Respond(Error(keys::kManifestParseError)); Release(); return; @@ -360,7 +360,8 @@ std::string error; scoped_refptr<Extension> extension = Extension::Create(base::FilePath(), ManifestLocation::kInvalidLocation, - *parsed_manifest, Extension::NO_FLAGS, &error); + base::DictAdapterForMigration(*parsed_manifest), + Extension::NO_FLAGS, &error); // TODO(lazyboy): Do we need to use |error|? if (!extension) { Respond(Error(keys::kExtensionCreateError));
diff --git a/extensions/browser/app_window/app_window_geometry_cache.cc b/extensions/browser/app_window/app_window_geometry_cache.cc index d437d5e..eba2594 100644 --- a/extensions/browser/app_window/app_window_geometry_cache.cc +++ b/extensions/browser/app_window/app_window_geometry_cache.cc
@@ -212,46 +212,36 @@ // overwrite that information since it is probably the result of an // application starting up very quickly. const std::string& window_id = item.first; - auto cached_window = extension_data.find(window_id); - if (cached_window == extension_data.end()) { - const base::DictionaryValue* stored_window; - if (item.second.GetAsDictionary(&stored_window)) { - WindowData& window_data = extension_data[window_id]; + if (extension_data.find(window_id) != extension_data.end()) + continue; - if (absl::optional<int> i = stored_window->FindIntKey("x")) - window_data.bounds.set_x(*i); - if (absl::optional<int> i = stored_window->FindIntKey("y")) - window_data.bounds.set_y(*i); - if (absl::optional<int> i = stored_window->FindIntKey("w")) - window_data.bounds.set_width(*i); - if (absl::optional<int> i = stored_window->FindIntKey("h")) - window_data.bounds.set_height(*i); - if (absl::optional<int> i = - stored_window->FindIntKey("screen_bounds_x")) { - window_data.screen_bounds.set_x(*i); - } - if (absl::optional<int> i = - stored_window->FindIntKey("screen_bounds_y")) { - window_data.screen_bounds.set_y(*i); - } - if (absl::optional<int> i = - stored_window->FindIntKey("screen_bounds_w")) { - window_data.screen_bounds.set_width(*i); - } - if (absl::optional<int> i = - stored_window->FindIntKey("screen_bounds_h")) { - window_data.screen_bounds.set_height(*i); - } - if (absl::optional<int> i = stored_window->FindIntKey("state")) { - window_data.window_state = static_cast<ui::WindowShowState>(*i); - } - if (const std::string* ts_as_string = - stored_window->FindStringKey("ts")) { - int64_t ts; - if (base::StringToInt64(*ts_as_string, &ts)) { - window_data.last_change = base::Time::FromInternalValue(ts); - } - } + const base::Value::Dict* stored_window = item.second.GetIfDict(); + if (!stored_window) + continue; + + WindowData& window_data = extension_data[window_id]; + if (absl::optional<int> i = stored_window->FindInt("x")) + window_data.bounds.set_x(*i); + if (absl::optional<int> i = stored_window->FindInt("y")) + window_data.bounds.set_y(*i); + if (absl::optional<int> i = stored_window->FindInt("w")) + window_data.bounds.set_width(*i); + if (absl::optional<int> i = stored_window->FindInt("h")) + window_data.bounds.set_height(*i); + if (absl::optional<int> i = stored_window->FindInt("screen_bounds_x")) + window_data.screen_bounds.set_x(*i); + if (absl::optional<int> i = stored_window->FindInt("screen_bounds_y")) + window_data.screen_bounds.set_y(*i); + if (absl::optional<int> i = stored_window->FindInt("screen_bounds_w")) + window_data.screen_bounds.set_width(*i); + if (absl::optional<int> i = stored_window->FindInt("screen_bounds_h")) + window_data.screen_bounds.set_height(*i); + if (absl::optional<int> i = stored_window->FindInt("state")) + window_data.window_state = static_cast<ui::WindowShowState>(*i); + if (const std::string* ts_as_string = stored_window->FindString("ts")) { + int64_t ts; + if (base::StringToInt64(*ts_as_string, &ts)) { + window_data.last_change = base::Time::FromInternalValue(ts); } } }
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h index d7b66a27..74bbc5d 100644 --- a/extensions/browser/extension_function_histogram_value.h +++ b/extensions/browser/extension_function_histogram_value.h
@@ -1168,7 +1168,7 @@ INPUT_IME_DEACTIVATE = 1107, ENTERPRISE_PLATFORMKEYS_CHALLENGEMACHINEKEY = 1108, ENTERPRISE_PLATFORMKEYS_CHALLENGEUSERKEY = 1109, - INPUTMETHODPRIVATE_NOTIFYIMEMENUITEMACTIVATED = 1110, + DELETED_INPUTMETHODPRIVATE_NOTIFYIMEMENUITEMACTIVATED = 1110, INPUT_IME_SHOWWINDOW = 1111, INPUT_IME_HIDEWINDOW = 1112, INPUTMETHODPRIVATE_SHOWINPUTVIEW = 1113,
diff --git a/extensions/browser/extension_prefs.cc b/extensions/browser/extension_prefs.cc index 7e44e715..4647a32 100644 --- a/extensions/browser/extension_prefs.cc +++ b/extensions/browser/extension_prefs.cc
@@ -310,8 +310,7 @@ std::unique_ptr<prefs::DictionaryValueUpdate> extension; if (!dict->GetDictionary(extension_id_, &extension)) { // Extension pref does not exist, create it. - extension = dict->SetDictionary( - extension_id_, std::make_unique<base::DictionaryValue>()); + extension = dict->SetDictionary(extension_id_, base::Value::Dict()); } return extension; } @@ -358,7 +357,7 @@ if (dict->GetDictionary(key_, &key_value)) return key_value; - return dict->SetDictionary(key_, std::make_unique<base::DictionaryValue>()); + return dict->SetDictionary(key_, base::Value::Dict()); } ExtensionPrefs::ScopedListUpdate::ScopedListUpdate( @@ -2382,18 +2381,19 @@ if (ruleset_install_prefs.empty()) { extension_dict->Remove(kDNRStaticRulesetPref); } else { - auto ruleset_prefs = std::make_unique<base::DictionaryValue>(); + base::Value::Dict ruleset_prefs; for (const declarative_net_request::RulesetInstallPref& install_pref : ruleset_install_prefs) { std::string id_key = base::NumberToString(install_pref.ruleset_id.value()); - DCHECK(!ruleset_prefs->FindKey(id_key)); - auto* ruleset_dict = ruleset_prefs->SetKey( - id_key, base::Value(base::Value::Type::DICTIONARY)); - if (install_pref.checksum) - ruleset_dict->SetIntKey(kDNRChecksumKey, *install_pref.checksum); - ruleset_dict->SetBoolKey(kDNRIgnoreRulesetKey, install_pref.ignored); + base::Value::Dict ruleset_dict; + ruleset_dict.Set(kDNRIgnoreRulesetKey, install_pref.ignored); + if (install_pref.checksum) + ruleset_dict.Set(kDNRChecksumKey, *install_pref.checksum); + + DCHECK(!ruleset_prefs.Find(id_key)); + ruleset_prefs.Set(id_key, std::move(ruleset_dict)); } extension_dict->SetDictionary(kDNRStaticRulesetPref,
diff --git a/extensions/browser/extensions_browser_interface_binders.cc b/extensions/browser/extensions_browser_interface_binders.cc index 79d18fdf..ebcaa70 100644 --- a/extensions/browser/extensions_browser_interface_binders.cc +++ b/extensions/browser/extensions_browser_interface_binders.cc
@@ -7,6 +7,7 @@ #include <string> #include "base/bind.h" +#include "content/public/browser/browser_context.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "extensions/browser/mojo/keep_alive_impl.h"
diff --git a/extensions/common/manifest_test.cc b/extensions/common/manifest_test.cc index a09d4afd..dd15eb4 100644 --- a/extensions/common/manifest_test.cc +++ b/extensions/common/manifest_test.cc
@@ -55,10 +55,8 @@ // Calling LocalizeExtension at this point mirrors file_util::LoadExtension. if (manifest_path.value().find(FILE_PATH_LITERAL("localized")) != std::string::npos) { - base::DictionaryValue* manifest_dictionary = nullptr; - manifest->GetAsDictionary(&manifest_dictionary); extension_l10n_util::LocalizeExtension( - extension_path, &manifest_dictionary->GetDict(), + extension_path, manifest->GetIfDict(), extension_l10n_util::GzippedMessagesPermission::kDisallow, error); } @@ -128,12 +126,9 @@ const base::Value& value = manifest.GetManifest(test_data_dir, error); if (value.is_none()) return nullptr; - DCHECK(value.is_dict()); - const base::DictionaryValue* dictionary_manifest = nullptr; - value.GetAsDictionary(&dictionary_manifest); return Extension::Create(test_data_dir.DirName(), location, - *dictionary_manifest, flags, GetTestExtensionID(), - error); + base::DictAdapterForMigration(value.GetDict()), + flags, GetTestExtensionID(), error); } scoped_refptr<Extension> ManifestTest::LoadAndExpectSuccess(
diff --git a/extensions/common/permissions/usb_device_permission_data.cc b/extensions/common/permissions/usb_device_permission_data.cc index 33836635..8e7a669cf 100644 --- a/extensions/common/permissions/usb_device_permission_data.cc +++ b/extensions/common/permissions/usb_device_permission_data.cc
@@ -28,10 +28,10 @@ const char kInterfaceClassKey[] = "interfaceClass"; bool ExtractFromDict(const std::string& key, - const base::DictionaryValue* dict_value, + const base::Value::Dict* dict_value, int max, int* value) { - absl::optional<int> temp = dict_value->FindIntKey(key); + absl::optional<int> temp = dict_value->FindInt(key); if (!temp) { *value = UsbDevicePermissionData::SPECIAL_VALUE_ANY; return true; @@ -97,8 +97,8 @@ if (!value) return false; - const base::DictionaryValue* dict_value; - if (!value->GetAsDictionary(&dict_value)) + const base::Value::Dict* dict_value = value->GetIfDict(); + if (!dict_value) return false; const int kMaxId = std::numeric_limits<uint16_t>::max();
diff --git a/extensions/renderer/bindings/argument_spec.cc b/extensions/renderer/bindings/argument_spec.cc index eadd7ec..ff6f599 100644 --- a/extensions/renderer/bindings/argument_spec.cc +++ b/extensions/renderer/bindings/argument_spec.cc
@@ -77,108 +77,105 @@ } // namespace -ArgumentSpec::ArgumentSpec(const base::Value& value) { - const base::DictionaryValue* dict = nullptr; - CHECK(value.GetAsDictionary(&dict)); - optional_ = dict->FindBoolKey("optional").value_or(optional_); - dict->GetString("name", &name_); +ArgumentSpec::ArgumentSpec(const base::Value& value) + : ArgumentSpec(value.GetDict()) {} + +ArgumentSpec::ArgumentSpec(const base::Value::Dict& dict) { + optional_ = dict.FindBool("optional").value_or(optional_); + if (const std::string* name = dict.FindString("name")) + name_ = *name; InitializeType(dict); } ArgumentSpec::ArgumentSpec(ArgumentType type) : type_(type) {} -void ArgumentSpec::InitializeType(const base::DictionaryValue* dict) { - std::string ref_string; - if (dict->GetString("$ref", &ref_string)) { - ref_ = std::move(ref_string); +void ArgumentSpec::InitializeType(const base::Value::Dict& dict) { + if (const std::string* ref_string = dict.FindString("$ref")) { + ref_ = *ref_string; type_ = ArgumentType::REF; return; } - { - const base::ListValue* choices = nullptr; - if (dict->GetList("choices", &choices)) { - DCHECK(!choices->GetList().empty()); - type_ = ArgumentType::CHOICES; - choices_.reserve(choices->GetList().size()); - for (const auto& choice : choices->GetList()) - choices_.push_back(std::make_unique<ArgumentSpec>(choice)); - return; - } + if (const base::Value::List* choices = dict.FindList("choices")) { + DCHECK(!choices->empty()); + type_ = ArgumentType::CHOICES; + choices_.reserve(choices->size()); + for (const auto& choice : *choices) + choices_.push_back(std::make_unique<ArgumentSpec>(choice)); + return; } - std::string type_string; - CHECK(dict->GetString("type", &type_string)); - if (type_string == "integer") + const std::string* type_string = dict.FindString("type"); + CHECK(type_string); + if (*type_string == "integer") type_ = ArgumentType::INTEGER; - else if (type_string == "number") + else if (*type_string == "number") type_ = ArgumentType::DOUBLE; - else if (type_string == "object") + else if (*type_string == "object") type_ = ArgumentType::OBJECT; - else if (type_string == "array") + else if (*type_string == "array") type_ = ArgumentType::LIST; - else if (type_string == "boolean") + else if (*type_string == "boolean") type_ = ArgumentType::BOOLEAN; - else if (type_string == "string") + else if (*type_string == "string") type_ = ArgumentType::STRING; - else if (type_string == "binary") + else if (*type_string == "binary") type_ = ArgumentType::BINARY; - else if (type_string == "any") + else if (*type_string == "any") type_ = ArgumentType::ANY; - else if (type_string == "function") + else if (*type_string == "function") type_ = ArgumentType::FUNCTION; else NOTREACHED(); - if (absl::optional<int> minimum = dict->FindIntKey("minimum")) + if (absl::optional<int> minimum = dict.FindInt("minimum")) minimum_ = *minimum; - if (absl::optional<int> maximum = dict->FindIntKey("maximum")) + if (absl::optional<int> maximum = dict.FindInt("maximum")) maximum_ = *maximum; - absl::optional<int> min_length = dict->FindIntKey("minLength"); + absl::optional<int> min_length = dict.FindInt("minLength"); if (!min_length) - min_length = dict->FindIntKey("minItems"); + min_length = dict.FindInt("minItems"); if (min_length) { DCHECK_GE(*min_length, 0); min_length_ = *min_length; } - absl::optional<int> max_length = dict->FindIntKey("maxLength"); + absl::optional<int> max_length = dict.FindInt("maxLength"); if (!max_length) - max_length = dict->FindIntKey("maxItems"); + max_length = dict.FindInt("maxItems"); if (max_length) { DCHECK_GE(*max_length, 0); max_length_ = *max_length; } if (type_ == ArgumentType::OBJECT) { - const base::DictionaryValue* properties_value = nullptr; - if (dict->GetDictionary("properties", &properties_value)) { - for (const auto item : properties_value->GetDict()) { + if (const base::Value::Dict* properties_value = + dict.FindDict("properties")) { + for (const auto item : *properties_value) { properties_[item.first] = std::make_unique<ArgumentSpec>(item.second); } } - const base::DictionaryValue* additional_properties_value = nullptr; - if (dict->GetDictionary("additionalProperties", - &additional_properties_value)) { + + if (const base::Value::Dict* additional_properties_value = + dict.FindDict("additionalProperties")) { additional_properties_ = std::make_unique<ArgumentSpec>(*additional_properties_value); // Additional properties are always optional. additional_properties_->optional_ = true; } } else if (type_ == ArgumentType::LIST) { - const base::DictionaryValue* item_value = nullptr; - CHECK(dict->GetDictionary("items", &item_value)); + const base::Value::Dict* item_value = dict.FindDict("items"); + CHECK(item_value); list_element_type_ = std::make_unique<ArgumentSpec>(*item_value); } else if (type_ == ArgumentType::STRING) { // Technically, there's no reason enums couldn't be other objects (e.g. // numbers), but right now they seem to be exclusively strings. We could // always update this if need be. - const base::ListValue* enums = nullptr; - if (dict->GetList("enum", &enums)) { - CHECK(!enums->GetList().empty()); - for (const base::Value& value : enums->GetList()) { + if (const base::Value::List* enums = dict.FindList("enum")) { + CHECK(!enums->empty()); + for (const base::Value& value : *enums) { const std::string* enum_str = value.GetIfString(); // Enum entries come in two versions: a list of possible strings, and // a dictionary with a field 'name'. @@ -191,20 +188,18 @@ } } } else if (type_ == ArgumentType::FUNCTION) { - serialize_function_ = - dict->FindBoolKey("serializableFunction").value_or(false); + serialize_function_ = dict.FindBool("serializableFunction").value_or(false); } // Check if we should preserve null in objects. Right now, this is only used // on arguments of type object and any (in fact, it's only used in the storage // API), but it could potentially make sense for lists or functions as well. if (type_ == ArgumentType::OBJECT || type_ == ArgumentType::ANY) - preserve_null_ = dict->FindBoolKey("preserveNull").value_or(preserve_null_); + preserve_null_ = dict.FindBool("preserveNull").value_or(preserve_null_); if (type_ == ArgumentType::OBJECT || type_ == ArgumentType::BINARY) { - std::string instance_of; - if (dict->GetString("isInstanceOf", &instance_of)) - instance_of_ = instance_of; + if (const std::string* instance_of = dict.FindString("isInstanceOf")) + instance_of_ = *instance_of; } }
diff --git a/extensions/renderer/bindings/argument_spec.h b/extensions/renderer/bindings/argument_spec.h index 90796cf3..e16a6a5 100644 --- a/extensions/renderer/bindings/argument_spec.h +++ b/extensions/renderer/bindings/argument_spec.h
@@ -12,14 +12,10 @@ #include <vector> #include "base/strings/string_piece.h" +#include "base/values.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "v8/include/v8.h" -namespace base { -class DictionaryValue; -class Value; -} - namespace extensions { class APITypeReferenceMap; @@ -46,6 +42,7 @@ // TODO(devlin): We should strongly think about generating these instead of // populating them at runtime. explicit ArgumentSpec(const base::Value& value); + explicit ArgumentSpec(const base::Value::Dict& dict); explicit ArgumentSpec(ArgumentType type); ArgumentSpec(const ArgumentSpec&) = delete; @@ -116,7 +113,7 @@ private: // Initializes this object according to |type_string| and |dict|. - void InitializeType(const base::DictionaryValue* dict); + void InitializeType(const base::Value::Dict& dict); // Conversion functions. These should only be used if the spec is of the given // type (otherwise, they will DCHECK).
diff --git a/gpu/command_buffer/service/shared_image/d3d_image_backing.cc b/gpu/command_buffer/service/shared_image/d3d_image_backing.cc index 374c5cc..51b2565f 100644 --- a/gpu/command_buffer/service/shared_image/d3d_image_backing.cc +++ b/gpu/command_buffer/service/shared_image/d3d_image_backing.cc
@@ -23,7 +23,6 @@ #include "third_party/libyuv/include/libyuv/planar_functions.h" #include "ui/gfx/buffer_format_util.h" #include "ui/gl/gl_bindings.h" -#include "ui/gl/gl_image_shared_memory.h" #include "ui/gl/scoped_restore_texture.h" #include "ui/gl/trace_util.h"
diff --git a/gpu/command_buffer/service/shared_image/egl_image_backing_factory_unittest.cc b/gpu/command_buffer/service/shared_image/egl_image_backing_factory_unittest.cc index 106e18b2..7ae7e31 100644 --- a/gpu/command_buffer/service/shared_image/egl_image_backing_factory_unittest.cc +++ b/gpu/command_buffer/service/shared_image/egl_image_backing_factory_unittest.cc
@@ -38,7 +38,6 @@ #include "ui/gl/buffer_format_utils.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_context.h" -#include "ui/gl/gl_image_shared_memory.h" #include "ui/gl/gl_image_stub.h" #include "ui/gl/gl_surface.h" #include "ui/gl/gl_utils.h"
diff --git a/gpu/command_buffer/service/shared_image/gl_image_pbuffer_backing.cc b/gpu/command_buffer/service/shared_image/gl_image_pbuffer_backing.cc index 2ed9573..9afd2e1d 100644 --- a/gpu/command_buffer/service/shared_image/gl_image_pbuffer_backing.cc +++ b/gpu/command_buffer/service/shared_image/gl_image_pbuffer_backing.cc
@@ -18,15 +18,12 @@ #include "ui/gl/gl_fence.h" #include "ui/gl/gl_gl_api_implementation.h" #include "ui/gl/gl_implementation.h" -#include "ui/gl/scoped_binders.h" #include "ui/gl/trace_util.h" namespace gpu { namespace { -using ScopedRestoreTexture = GLTextureImageBackingHelper::ScopedRestoreTexture; - using InitializeGLTextureParams = GLTextureImageBackingHelper::InitializeGLTextureParams; @@ -60,7 +57,6 @@ surface_origin, alpha_type, usage, params)); shared_image->passthrough_texture_ = std::move(wrapped_gl_texture); - shared_image->image_bind_or_copy_needed_ = false; return shared_image; } @@ -107,16 +103,8 @@ } if (passthrough_texture_) { - if (have_context) { - if (!passthrough_texture_->is_bind_pending()) { - const GLenum target = GetGLTarget(); - gl::ScopedTextureBinder binder(target, - passthrough_texture_->service_id()); - image_->ReleaseTexImage(target); - } - } else { + if (!have_context) passthrough_texture_->MarkContextLost(); - } passthrough_texture_.reset(); } } @@ -132,7 +120,7 @@ } scoped_refptr<gfx::NativePixmap> GLImagePbufferBacking::GetNativePixmap() { - return image_->GetNativePixmap(); + return nullptr; } void GLImagePbufferBacking::OnMemoryDump( @@ -150,7 +138,6 @@ pmd->CreateSharedGlobalAllocatorDump(service_guid); pmd->AddOwnershipEdge(client_guid, service_guid, kOwningEdgeImportance); } - image_->OnMemoryDump(pmd, client_tracing_id, dump_name); } SharedImageBackingType GLImagePbufferBacking::GetType() const { @@ -237,12 +224,12 @@ gl::GLFence::CreateFromGpuFence(*in_fence.get()); egl_fence->ServerWait(); } - image_bind_or_copy_needed_ = true; } bool GLImagePbufferBacking::GLTextureImageRepresentationBeginAccess( bool readonly) { - return BindOrCopyImageIfNeeded(); + passthrough_texture_->set_is_bind_pending(false); + return true; } void GLImagePbufferBacking::GLTextureImageRepresentationEndAccess( @@ -254,47 +241,4 @@ // lifetime, and releases it in its destructor. } -bool GLImagePbufferBacking::BindOrCopyImageIfNeeded() { - // This is called by code that has retained the GL texture. - DCHECK(passthrough_texture_); - if (!image_bind_or_copy_needed_) - return true; - - const GLenum target = GetGLTarget(); - gl::GLApi* api = gl::g_current_gl_context; - ScopedRestoreTexture scoped_restore(api, target); - api->glBindTextureFn(target, GetGLServiceId()); - - // Un-bind the GLImage from the texture if it is currently bound. - if (image_->ShouldBindOrCopy() == gl::GLImage::BIND) { - bool is_bound = !passthrough_texture_->is_bind_pending(); - if (is_bound) - image_->ReleaseTexImage(target); - } - - // Bind or copy the GLImage to the texture. - gles2::Texture::ImageState new_state = gles2::Texture::UNBOUND; - if (image_->ShouldBindOrCopy() == gl::GLImage::BIND) { - if (!image_->BindTexImage(target)) { - LOG(ERROR) << "Failed to bind GLImage to target"; - return false; - } - new_state = gles2::Texture::BOUND; - } else { - ScopedUnpackState scoped_unpack_state( - /*uploading_data=*/true); - if (!image_->CopyTexImage(target)) { - LOG(ERROR) << "Failed to copy GLImage to target"; - return false; - } - new_state = gles2::Texture::COPIED; - } - DCHECK(new_state == gles2::Texture::BOUND || - new_state == gles2::Texture::COPIED); - passthrough_texture_->set_is_bind_pending(false); - - image_bind_or_copy_needed_ = false; - return true; -} - } // namespace gpu
diff --git a/gpu/command_buffer/service/shared_image/gl_image_pbuffer_backing.h b/gpu/command_buffer/service/shared_image/gl_image_pbuffer_backing.h index 6807d40..fa03d55 100644 --- a/gpu/command_buffer/service/shared_image/gl_image_pbuffer_backing.h +++ b/gpu/command_buffer/service/shared_image/gl_image_pbuffer_backing.h
@@ -95,11 +95,6 @@ scoped_refptr<GLImagePbuffer> image_; - // If |image_bind_or_copy_needed_| is true, then either bind or copy |image_| - // to the GL texture, and un-set |image_bind_or_copy_needed_|. - bool BindOrCopyImageIfNeeded(); - bool image_bind_or_copy_needed_ = true; - void ReleaseGLTexture(bool have_context); const GLTextureImageBackingHelper::InitializeGLTextureParams gl_params_;
diff --git a/infra/config/chops-weetbix-dev.cfg b/infra/config/chops-weetbix-dev.cfg new file mode 100644 index 0000000..07e05c1 --- /dev/null +++ b/infra/config/chops-weetbix-dev.cfg
@@ -0,0 +1,77 @@ +# Schema for this config file: ProjectConfig in: +# https://luci-config.appspot.com/schemas/projects:luci-analysis.cfg + +bug_filing_threshold { + # Do not file bugs for now. +} + +clustering { + test_name_rules { + name: "Blink Web Tests" + # To match blink_web_tests as well as webgpu_blink_web_tests and any others. + pattern: "^ninja://:(?P<target>\\w*blink_web_tests)/(virtual/[^/]+/)?(?P<test>([^/]+/)+[^/]+\\.[a-zA-Z]+).*$" + like_template: "ninja://:${target}/%${test}%" + } + test_name_rules { + name: "Google Test (Value-parameterized)" + pattern: "^ninja:(?P<target>[\\w/]+:\\w+)/(\\w+/)?(?P<suite>\\w+)\\.(?P<test>\\w+)/[\\w.]+$" + like_template: "ninja:${target}/%${suite}.${test}%" + } + test_name_rules { + name: "Google Test (Type-parameterized)" + pattern: "^ninja:(?P<target>[\\w/]+:\\w+)/(\\w+/)?(?P<suite>\\w+)/\\w+\\.(?P<test>\\w+)$" + like_template: "ninja:${target}/%${suite}/%.${test}" + } + test_name_rules { + name: "JUnit Test (Parameterized)" + # Matches parameterized JUnit tests like: + # ninja://android_webview/test:webview_instrumentation_test_apk/org.chromium.android_webview.test.MyTest#testFoo__parameter1 + # Also matches tests parameterized with different command line flags, + # as constructed by https://source.chromium.org/chromium/chromium/src/+/main:build/android/pylib/instrumentation/instrumentation_test_instance.py?q=%22def%20GetUniqueTestName(%22 + # E.g. ninja://chrome/android:chrome_public_test_apk/org.chromium.chrome.browser.omnibox.OmniboxTest#testDefaultText_with___disable_features=SpannableInlineAutocomplete + pattern: "^ninja:(?P<target>[\\w/]+:\\w+)/(?P<class>[\\w$.]+)#(?P<test>\\w+?)(?P<sep>__|_with_)[\\w.=,]+$" + like_template: "ninja:${target}/${class}#${test}${sep}%" + } +} + +monorail { + project: "chromium" + default_field_values { + # Type field. + field_id: 10 + value: "Bug" + } + priority_field_id: 11 + priorities { + priority: "0" + threshold { + presubmit_runs_failed { + one_day: 20 + } + } + } + priorities { + priority: "1" + threshold { + presubmit_runs_failed { + one_day: 10 + } + } + } + priorities { + priority: "2" + threshold { + # Clusters which fail to meet this threshold will be closed. + presubmit_runs_failed { + seven_day: 1 + } + critical_failures_exonerated { + seven_day: 1 + } + } + } + priority_hysteresis_percent: 50 + monorail_hostname: "monorail-staging.appspot.com" + display_prefix: "crbug.com" +} +
diff --git a/infra/config/dev.star b/infra/config/dev.star index 96fdc62..a617c30b 100755 --- a/infra/config/dev.star +++ b/infra/config/dev.star
@@ -20,6 +20,7 @@ lucicfg.config( config_dir = "generated", tracked_files = [ + "luci/chops-weetbix-dev.cfg", "luci/cr-buildbucket-dev.cfg", "luci/luci-analysis-dev.cfg", "luci/luci-logdog-dev.cfg", @@ -36,4 +37,9 @@ data = io.read_file("luci-analysis-dev.cfg"), ) +lucicfg.emit( + dest = "luci/chops-weetbix-dev.cfg", + data = io.read_file("chops-weetbix-dev.cfg"), +) + branches.exec("//dev/dev.star")
diff --git a/infra/config/dev/dev.star b/infra/config/dev/dev.star index 89a7ba44..03e9809 100644 --- a/infra/config/dev/dev.star +++ b/infra/config/dev/dev.star
@@ -46,21 +46,6 @@ roles = "role/analysis.editor", groups = ["project-chromium-committers", "googlers"], ), - # Roles for Weetbix. - # TODO(b/243488110): Delete when renaming to - # LUCI Analysis complete. - luci.binding( - roles = "role/weetbix.reader", - groups = "all", - ), - luci.binding( - roles = "role/weetbix.queryUser", - groups = "authenticated-users", - ), - luci.binding( - roles = "role/weetbix.editor", - groups = ["project-chromium-committers", "googlers"], - ), ], )
diff --git a/infra/config/generated/luci/chops-weetbix-dev.cfg b/infra/config/generated/luci/chops-weetbix-dev.cfg new file mode 100644 index 0000000..07e05c1 --- /dev/null +++ b/infra/config/generated/luci/chops-weetbix-dev.cfg
@@ -0,0 +1,77 @@ +# Schema for this config file: ProjectConfig in: +# https://luci-config.appspot.com/schemas/projects:luci-analysis.cfg + +bug_filing_threshold { + # Do not file bugs for now. +} + +clustering { + test_name_rules { + name: "Blink Web Tests" + # To match blink_web_tests as well as webgpu_blink_web_tests and any others. + pattern: "^ninja://:(?P<target>\\w*blink_web_tests)/(virtual/[^/]+/)?(?P<test>([^/]+/)+[^/]+\\.[a-zA-Z]+).*$" + like_template: "ninja://:${target}/%${test}%" + } + test_name_rules { + name: "Google Test (Value-parameterized)" + pattern: "^ninja:(?P<target>[\\w/]+:\\w+)/(\\w+/)?(?P<suite>\\w+)\\.(?P<test>\\w+)/[\\w.]+$" + like_template: "ninja:${target}/%${suite}.${test}%" + } + test_name_rules { + name: "Google Test (Type-parameterized)" + pattern: "^ninja:(?P<target>[\\w/]+:\\w+)/(\\w+/)?(?P<suite>\\w+)/\\w+\\.(?P<test>\\w+)$" + like_template: "ninja:${target}/%${suite}/%.${test}" + } + test_name_rules { + name: "JUnit Test (Parameterized)" + # Matches parameterized JUnit tests like: + # ninja://android_webview/test:webview_instrumentation_test_apk/org.chromium.android_webview.test.MyTest#testFoo__parameter1 + # Also matches tests parameterized with different command line flags, + # as constructed by https://source.chromium.org/chromium/chromium/src/+/main:build/android/pylib/instrumentation/instrumentation_test_instance.py?q=%22def%20GetUniqueTestName(%22 + # E.g. ninja://chrome/android:chrome_public_test_apk/org.chromium.chrome.browser.omnibox.OmniboxTest#testDefaultText_with___disable_features=SpannableInlineAutocomplete + pattern: "^ninja:(?P<target>[\\w/]+:\\w+)/(?P<class>[\\w$.]+)#(?P<test>\\w+?)(?P<sep>__|_with_)[\\w.=,]+$" + like_template: "ninja:${target}/${class}#${test}${sep}%" + } +} + +monorail { + project: "chromium" + default_field_values { + # Type field. + field_id: 10 + value: "Bug" + } + priority_field_id: 11 + priorities { + priority: "0" + threshold { + presubmit_runs_failed { + one_day: 20 + } + } + } + priorities { + priority: "1" + threshold { + presubmit_runs_failed { + one_day: 10 + } + } + } + priorities { + priority: "2" + threshold { + # Clusters which fail to meet this threshold will be closed. + presubmit_runs_failed { + seven_day: 1 + } + critical_failures_exonerated { + seven_day: 1 + } + } + } + priority_hysteresis_percent: 50 + monorail_hostname: "monorail-staging.appspot.com" + display_prefix: "crbug.com" +} +
diff --git a/infra/config/generated/luci/luci-analysis-dev.cfg b/infra/config/generated/luci/luci-analysis-dev.cfg index c963118..e013c8c 100644 --- a/infra/config/generated/luci/luci-analysis-dev.cfg +++ b/infra/config/generated/luci/luci-analysis-dev.cfg
@@ -1,5 +1,5 @@ # Schema for this config file: ProjectConfig in: -# https://luci-config.appspot.com/schemas/projects:chops-weetbix.cfg +# https://luci-config.appspot.com/schemas/projects:luci-analysis.cfg bug_filing_threshold { presubmit_runs_failed {
diff --git a/infra/config/generated/luci/realms-dev.cfg b/infra/config/generated/luci/realms-dev.cfg index cae22d5..82905ac 100644 --- a/infra/config/generated/luci/realms-dev.cfg +++ b/infra/config/generated/luci/realms-dev.cfg
@@ -59,19 +59,6 @@ role: "role/swarming.taskTriggerer" principals: "group:mdb/chrome-troopers" } - bindings { - role: "role/weetbix.editor" - principals: "group:googlers" - principals: "group:project-chromium-committers" - } - bindings { - role: "role/weetbix.queryUser" - principals: "group:authenticated-users" - } - bindings { - role: "role/weetbix.reader" - principals: "group:all" - } } realms { name: "ci"
diff --git a/infra/config/luci-analysis-dev.cfg b/infra/config/luci-analysis-dev.cfg index c963118..e013c8c 100644 --- a/infra/config/luci-analysis-dev.cfg +++ b/infra/config/luci-analysis-dev.cfg
@@ -1,5 +1,5 @@ # Schema for this config file: ProjectConfig in: -# https://luci-config.appspot.com/schemas/projects:chops-weetbix.cfg +# https://luci-config.appspot.com/schemas/projects:luci-analysis.cfg bug_filing_threshold { presubmit_runs_failed {
diff --git a/ios/chrome/app/resources/chrome_localize_strings_config.plist b/ios/chrome/app/resources/chrome_localize_strings_config.plist index a6c456c..6f4d6c23 100644 --- a/ios/chrome/app/resources/chrome_localize_strings_config.plist +++ b/ios/chrome/app/resources/chrome_localize_strings_config.plist
@@ -54,6 +54,7 @@ <string>IDS_IOS_KEYBOARD_SHOW_READING_LIST</string> <string>IDS_IOS_KEYBOARD_GO_TO_TAB_GRID</string> <string>IDS_IOS_KEYBOARD_CLEAR_BROWSING_DATA</string> + <string>IDS_IOS_KEYBOARD_FIND</string> <string>IDS_IOS_UI_BLOCKED_USE_OTHER_WINDOW_DESCRIPTION</string> <string>IDS_IOS_UI_BLOCKED_USE_OTHER_WINDOW_SWITCH_WINDOW_ACTION</string> </array>
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd index b737b56..fc70827 100644 --- a/ios/chrome/app/strings/ios_strings.grd +++ b/ios/chrome/app/strings/ios_strings.grd
@@ -1276,6 +1276,9 @@ <message name="IDS_IOS_KEYBOARD_CLOSE_TAB" desc="Title of the keyboard shortcut to close the current tab." meaning="Used as a command title in the iPad command menu."> Close Tab </message> + <message name="IDS_IOS_KEYBOARD_FIND" desc="The default title of the keyboard shortcut to search." meaning="Used as a command title in the iPad command menu."> + Find + </message> <message name="IDS_IOS_KEYBOARD_FIND_IN_PAGE" desc="The title of the keyboard shortcut to search in the current page." meaning="Used as a command title in the iPad command menu."> Find in Page… </message> @@ -1333,6 +1336,9 @@ <message name="IDS_IOS_KEYBOARD_REPORT_AN_ISSUE" desc="The title of the keyboard shortcut to open the form to report an issue." meaning="Used as a command title in the iPad command menu."> Report an Issue… </message> + <message name="IDS_IOS_KEYBOARD_SEARCH_TABS" desc="In Title Case: Title of the keyboard shortcut that open the search tab menu in tab grid." meaning="Used as a command title in the iPad command menu."> + Search Tabs… + </message> <message name="IDS_IOS_KEYBOARD_SHOW_BOOKMARKS" desc="In Title Case: Title of the keyboard shortcut that shows the list of bookmarks." meaning="Used as a command title in the iPad command menu."> Show Bookmarks </message>
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_KEYBOARD_FIND.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_KEYBOARD_FIND.png.sha1 new file mode 100644 index 0000000..214e557 --- /dev/null +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_KEYBOARD_FIND.png.sha1
@@ -0,0 +1 @@ +593a7cc70c94672027e54afe0990966fffd9bb4b \ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_KEYBOARD_SEARCH_TABS.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_KEYBOARD_SEARCH_TABS.png.sha1 new file mode 100644 index 0000000..214e557 --- /dev/null +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_KEYBOARD_SEARCH_TABS.png.sha1
@@ -0,0 +1 @@ +593a7cc70c94672027e54afe0990966fffd9bb4b \ No newline at end of file
diff --git a/ios/chrome/browser/ui/browser_view/BUILD.gn b/ios/chrome/browser/ui/browser_view/BUILD.gn index 495c517..5e81aaa0 100644 --- a/ios/chrome/browser/ui/browser_view/BUILD.gn +++ b/ios/chrome/browser/ui/browser_view/BUILD.gn
@@ -261,6 +261,7 @@ "//components/prefs:test_support", "//components/search_engines", "//components/sessions", + "//ios/chrome/app/strings", "//ios/chrome/browser/bookmarks", "//ios/chrome/browser/browser_state:test_support", "//ios/chrome/browser/download",
diff --git a/ios/chrome/browser/ui/browser_view/key_commands_provider.mm b/ios/chrome/browser/ui/browser_view/key_commands_provider.mm index c76253db..571f17c 100644 --- a/ios/chrome/browser/ui/browser_view/key_commands_provider.mm +++ b/ios/chrome/browser/ui/browser_view/key_commands_provider.mm
@@ -234,6 +234,17 @@ return [super canPerformAction:action withSender:sender]; } +// Changes the title to display the most appropriate string in the shortcut +// menu. +- (void)validateCommand:(UICommand*)command { + if (command.action == @selector(keyCommand_find)) { + command.discoverabilityTitle = + l10n_util::GetNSStringWithFixup(IDS_IOS_KEYBOARD_FIND_IN_PAGE); + } else { + return [super validateCommand:command]; + } +} + #pragma mark - Key Command Actions - (void)keyCommand_openNewTab {
diff --git a/ios/chrome/browser/ui/browser_view/key_commands_provider_unittest.mm b/ios/chrome/browser/ui/browser_view/key_commands_provider_unittest.mm index 6279d9e..fc0b2d6 100644 --- a/ios/chrome/browser/ui/browser_view/key_commands_provider_unittest.mm +++ b/ios/chrome/browser/ui/browser_view/key_commands_provider_unittest.mm
@@ -29,6 +29,7 @@ #import "ios/chrome/browser/web/web_navigation_util.h" #import "ios/chrome/browser/web_state_list/web_state_list.h" #import "ios/chrome/browser/web_state_list/web_state_opener.h" +#import "ios/chrome/grit/ios_strings.h" #import "ios/web/common/uikit_ui_util.h" #import "ios/web/find_in_page/find_in_page_manager_impl.h" #import "ios/web/public/test/fakes/fake_navigation_context.h" @@ -39,6 +40,7 @@ #import "third_party/ocmock/OCMock/OCMock.h" #import "third_party/ocmock/gtest_support.h" #import "third_party/ocmock/ocmock_extensions.h" +#import "ui/base/l10n/l10n_util.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -860,4 +862,26 @@ EXPECT_EQ(navigation_manager->GetLastCommittedItemIndex(), initial_index); } +#pragma mark - Validate + +TEST_F(KeyCommandsProviderTest, ValidateCommands) { + // Open a tab. + web::FakeWebState* web_state = InsertNewWebState(0); + web::FindInPageManagerImpl::CreateForWebState(web_state); + FindTabHelper::CreateForWebState(web_state); + + // Can Find in Page. + web_state->SetContentIsHTML(true); + EXPECT_TRUE(CanPerform(@"keyCommand_find")); + + for (UIKeyCommand* command in provider_.keyCommands) { + [provider_ validateCommand:command]; + if (command.action == @selector(keyCommand_find)) { + EXPECT_TRUE([command.discoverabilityTitle + isEqualToString:l10n_util::GetNSStringWithFixup( + IDS_IOS_KEYBOARD_FIND_IN_PAGE)]); + } + } +} + } // namespace
diff --git a/ios/chrome/browser/ui/keyboard/UIKeyCommand+Chrome.mm b/ios/chrome/browser/ui/keyboard/UIKeyCommand+Chrome.mm index 3e2863f4..78e6a0a 100644 --- a/ios/chrome/browser/ui/keyboard/UIKeyCommand+Chrome.mm +++ b/ios/chrome/browser/ui/keyboard/UIKeyCommand+Chrome.mm
@@ -81,7 +81,7 @@ return [self cr_commandWithInput:@"f" modifierFlags:Command action:@selector(keyCommand_find) - titleIDAsString:@"IDS_IOS_KEYBOARD_FIND_IN_PAGE"]; + titleIDAsString:@"IDS_IOS_KEYBOARD_FIND"]; } + (UIKeyCommand*)cr_findNext {
diff --git a/ios/chrome/browser/ui/keyboard/UIKeyCommand+ChromeTest.mm b/ios/chrome/browser/ui/keyboard/UIKeyCommand+ChromeTest.mm index e6746c0..59e385f4 100644 --- a/ios/chrome/browser/ui/keyboard/UIKeyCommand+ChromeTest.mm +++ b/ios/chrome/browser/ui/keyboard/UIKeyCommand+ChromeTest.mm
@@ -64,7 +64,7 @@ Verify(UIKeyCommand.cr_reopenLastClosedTab, @"⇧⌘T", @"keyCommand_reopenLastClosedTab", IDS_IOS_KEYBOARD_REOPEN_CLOSED_TAB); Verify(UIKeyCommand.cr_find, @"⌘F", @"keyCommand_find", - IDS_IOS_KEYBOARD_FIND_IN_PAGE); + IDS_IOS_KEYBOARD_FIND); Verify(UIKeyCommand.cr_findNext, @"⌘G", @"keyCommand_findNext", IDS_IOS_KEYBOARD_FIND_NEXT); Verify(UIKeyCommand.cr_findPrevious, @"⇧⌘G", @"keyCommand_findPrevious",
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm b/ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm index 2c97c9c..e3802c3 100644 --- a/ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm +++ b/ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm
@@ -443,7 +443,12 @@ // or if the user pastes some text in. Let's loosen this test to allow // multiple characters, as long as the "old range" ends at the end of the // permanent text. - if ([new_text length] == 1 && range.location == [field_.text length]) { + NSString* userText = field_.text; + if (base::FeatureList::IsEnabled(kIOSNewOmniboxImplementation)) { + userText = field_.userText; + } + + if (new_text.length == 1 && range.location == userText.length) { old_range = NSMakeRange(field_.text.length, field_.autocompleteText.length); }
diff --git a/ios/chrome/browser/ui/tab_switcher/pinned_tabs/pinned_tabs_view_controller.mm b/ios/chrome/browser/ui/tab_switcher/pinned_tabs/pinned_tabs_view_controller.mm index 8b56ed5..2b3a5c3a 100644 --- a/ios/chrome/browser/ui/tab_switcher/pinned_tabs/pinned_tabs_view_controller.mm +++ b/ios/chrome/browser/ui/tab_switcher/pinned_tabs/pinned_tabs_view_controller.mm
@@ -38,6 +38,9 @@ NSLayoutConstraint* _dragEnabledConstraint; NSLayoutConstraint* _defaultConstraint; + // Background color of the view. + UIColor* _backgroundColor; + // Tracks if the view is available. It does not track if the view is visible. BOOL _available; } @@ -54,27 +57,9 @@ - (void)viewDidLoad { [super viewDidLoad]; - self.overrideUserInterfaceStyle = UIUserInterfaceStyleDark; _available = YES; - UICollectionView* collectionView = self.collectionView; - [collectionView registerClass:[PinnedCell class] - forCellWithReuseIdentifier:kPinnedCellIdentifier]; - collectionView.backgroundColor = [UIColor colorNamed:kPrimaryBackgroundColor]; - collectionView.layer.cornerRadius = kPinnedViewCornerRadius; - collectionView.translatesAutoresizingMaskIntoConstraints = NO; - collectionView.dragDelegate = self; - collectionView.dropDelegate = self; - collectionView.dragInteractionEnabled = YES; - - self.view = collectionView; - - _dragEnabledConstraint = [collectionView.heightAnchor - constraintEqualToConstant:kPinnedViewDragEnabledHeight]; - _defaultConstraint = [collectionView.heightAnchor - constraintEqualToConstant:kPinnedViewDefaultHeight]; - _defaultConstraint.active = YES; - + [self configureCollectionView]; [self populateFakeItems]; } @@ -89,8 +74,8 @@ } completion:nil]; - self.collectionView.backgroundColor = - [UIColor colorNamed:kPrimaryBackgroundColor]; + self.collectionView.backgroundColor = _backgroundColor; + self.collectionView.backgroundView.hidden = NO; } - (void)pinnedTabsAvailable:(BOOL)available { @@ -179,12 +164,13 @@ - (void)collectionView:(UICollectionView*)collectionView dropSessionDidEnter:(id<UIDropSession>)session { self.collectionView.backgroundColor = [UIColor colorNamed:kBlueColor]; + self.collectionView.backgroundView.hidden = YES; } - (void)collectionView:(UICollectionView*)collectionView dropSessionDidExit:(id<UIDropSession>)session { - self.collectionView.backgroundColor = - [UIColor colorNamed:kPrimaryBackgroundColor]; + self.collectionView.backgroundColor = _backgroundColor; + self.collectionView.backgroundView.hidden = NO; } - (UICollectionViewDropProposal*) @@ -210,6 +196,47 @@ #pragma mark - Private +// Configures the collectionView. +- (void)configureCollectionView { + self.overrideUserInterfaceStyle = UIUserInterfaceStyleDark; + + UICollectionView* collectionView = self.collectionView; + [collectionView registerClass:[PinnedCell class] + forCellWithReuseIdentifier:kPinnedCellIdentifier]; + collectionView.layer.cornerRadius = kPinnedViewCornerRadius; + collectionView.translatesAutoresizingMaskIntoConstraints = NO; + collectionView.dragDelegate = self; + collectionView.dropDelegate = self; + collectionView.dragInteractionEnabled = YES; + + self.view = collectionView; + + // Only apply the blur if transparency effects are not disabled. + if (!UIAccessibilityIsReduceTransparencyEnabled()) { + _backgroundColor = [UIColor clearColor]; + + UIBlurEffect* blurEffect = + [UIBlurEffect effectWithStyle:UIBlurEffectStyleSystemThinMaterialDark]; + UIVisualEffectView* blurEffectView = + [[UIVisualEffectView alloc] initWithEffect:blurEffect]; + + blurEffectView.frame = collectionView.bounds; + blurEffectView.autoresizingMask = + UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + + collectionView.backgroundView = blurEffectView; + } else { + _backgroundColor = [UIColor colorNamed:kPrimaryBackgroundColor]; + } + collectionView.backgroundColor = _backgroundColor; + + _dragEnabledConstraint = [collectionView.heightAnchor + constraintEqualToConstant:kPinnedViewDragEnabledHeight]; + _defaultConstraint = [collectionView.heightAnchor + constraintEqualToConstant:kPinnedViewDefaultHeight]; + _defaultConstraint.active = YES; +} + // Configures `cell`'s title synchronously, and favicon asynchronously with // information from `item`. Updates the `cell`'s theme to this view controller's // theme.
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/BUILD.gn b/ios/chrome/browser/ui/tab_switcher/tab_grid/BUILD.gn index 9b3b82e2..53b3d3da 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/BUILD.gn +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/BUILD.gn
@@ -189,6 +189,7 @@ "//components/sessions", "//components/sync_preferences:test_support", "//components/unified_consent:unified_consent", + "//ios/chrome/app/strings", "//ios/chrome/browser/bookmarks", "//ios/chrome/browser/browser_state:test_support", "//ios/chrome/browser/commerce:commerce", @@ -208,6 +209,7 @@ "//ios/chrome/browser/tabs:tabs_internal", "//ios/chrome/browser/ui:feature_flags", "//ios/chrome/browser/ui/commands", + "//ios/chrome/browser/ui/gestures", "//ios/chrome/browser/ui/keyboard:features", "//ios/chrome/browser/ui/main", "//ios/chrome/browser/ui/main:scene_state_header",
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.h b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.h index cde730d5..27c7627 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.h +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.h
@@ -94,7 +94,8 @@ KeyCommandActions, LayoutSwitcherProvider, TabGridPaging, - ThumbStripSupporting> + ThumbStripSupporting, + ViewRevealingAnimatee> @property(nonatomic, weak) id<ApplicationCommands> handler; @property(nonatomic, weak) id<IncognitoReauthCommands> reauthHandler;
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.mm index ad89ca9..0595797 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.mm
@@ -137,8 +137,7 @@ SuggestedActionsDelegate, UIGestureRecognizerDelegate, UIScrollViewAccessibilityDelegate, - UISearchBarDelegate, - ViewRevealingAnimatee> + UISearchBarDelegate> // Whether the view is visible. Bookkeeping is based on `-viewWillAppear:` and // `-viewWillDisappear methods. Note that the `Did` methods are not reliably // called (e.g., edge case in multitasking). @@ -2647,9 +2646,21 @@ sel_isEqual(action, @selector(keyCommand_openNewIncognitoTab))) { return self.currentPage != TabGridPageRemoteTabs; } + if (sel_isEqual(action, @selector(keyCommand_find))) { + return self.currentState == ViewRevealState::Revealed; + } return [super canPerformAction:action withSender:sender]; } +- (void)validateCommand:(UICommand*)command { + if (command.action == @selector(keyCommand_find)) { + command.discoverabilityTitle = + l10n_util::GetNSStringWithFixup(IDS_IOS_KEYBOARD_SEARCH_TABS); + } else { + return [super validateCommand:command]; + } +} + - (void)keyCommand_openNewTab { base::RecordAction(base::UserMetricsAction("MobileKeyCommandOpenNewTab")); [self openNewTabInCurrentPageForKeyboardCommand]; @@ -2667,4 +2678,9 @@ [self openNewIncognitoTabForKeyboardCommand]; } +- (void)keyCommand_find { + base::RecordAction(base::UserMetricsAction("MobileKeyCommandSearchTabs")); + [self searchButtonTapped:nil]; +} + @end
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller_unittest.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller_unittest.mm index 9439ece..3f7277d 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller_unittest.mm
@@ -10,8 +10,11 @@ #import "base/test/metrics/user_action_tester.h" #import "base/test/scoped_feature_list.h" +#import "ios/chrome/browser/ui/gestures/view_revealing_vertical_pan_handler.h" #import "ios/chrome/browser/ui/keyboard/features.h" +#import "ios/chrome/grit/ios_strings.h" #import "testing/platform_test.h" +#import "ui/base/l10n/l10n_util.h" namespace { @@ -104,18 +107,61 @@ // Checks that TabGridViewController implements the following actions. TEST_F(TabGridViewControllerTest, ImplementsActions) { + // Load the view. + std::ignore = view_controller_.view; [view_controller_ keyCommand_openNewTab]; [view_controller_ keyCommand_openNewRegularTab]; [view_controller_ keyCommand_openNewIncognitoTab]; + [view_controller_ keyCommand_find]; } // Checks that metrics are correctly reported. TEST_F(TabGridViewControllerTest, Metrics) { + // Load the view. + std::ignore = view_controller_.view; ExpectUMA(@"keyCommand_openNewTab", "MobileKeyCommandOpenNewTab"); ExpectUMA(@"keyCommand_openNewRegularTab", "MobileKeyCommandOpenNewRegularTab"); ExpectUMA(@"keyCommand_openNewIncognitoTab", "MobileKeyCommandOpenNewIncognitoTab"); + ExpectUMA(@"keyCommand_find", "MobileKeyCommandSearchTabs"); +} + +// This test ensure 2 things: +// * the key command find is available when the tab grid is currently visible, +// * the key command associated title is correct. +TEST_F(TabGridViewControllerTest, ValidateCommand_find) { + // Load the view. + std::ignore = view_controller_.view; + EXPECT_FALSE(CanPerform(@"keyCommand_find")); + // Create a view revealing vertical pan handler. + ViewRevealingVerticalPanHandler* pan_handler = + [[ViewRevealingVerticalPanHandler alloc] + initWithPeekedHeight:212.0f + baseViewHeight:800.0f + initialState:ViewRevealState::Peeked]; + + // Displays the tab grid. + [pan_handler addAnimatee:view_controller_]; + [pan_handler setNextState:ViewRevealState::Revealed + animated:NO + trigger:ViewRevealTrigger::Unknown]; + + // Ensures that the command is available. + EXPECT_TRUE(CanPerform(@"keyCommand_find")); + id findTarget = [view_controller_ targetForAction:@selector(keyCommand_find) + withSender:nil]; + EXPECT_EQ(findTarget, view_controller_); + + // Ensures that the title is correct. + for (UIKeyCommand* command in view_controller_.keyCommands) { + [view_controller_ validateCommand:command]; + if (command.action == @selector(keyCommand_find)) { + EXPECT_TRUE([command.discoverabilityTitle + isEqualToString:l10n_util::GetNSStringWithFixup( + IDS_IOS_KEYBOARD_SEARCH_TABS)]); + } + } } } // namespace
diff --git a/ios/web/navigation/crw_wk_navigation_handler.mm b/ios/web/navigation/crw_wk_navigation_handler.mm index a63c019..a3c4d5c 100644 --- a/ios/web/navigation/crw_wk_navigation_handler.mm +++ b/ios/web/navigation/crw_wk_navigation_handler.mm
@@ -211,8 +211,16 @@ const WKContentMode contentMode = userAgentType == web::UserAgentType::DESKTOP ? WKContentModeDesktop : WKContentModeMobile; + BOOL isMainFrameNavigationAction = [self isMainFrameNavigationAction:action]; auto decisionHandler = ^(WKNavigationActionPolicy policy) { preferences.preferredContentMode = contentMode; + if (@available(iOS 16.0, *)) { + if ((policy == WKNavigationActionPolicyAllow) && + isMainFrameNavigationAction) { + UMA_HISTOGRAM_BOOLEAN("IOS.MainFrameNavigationIsInLockdownMode", + preferences.lockdownModeEnabled); + } + } handler(policy, preferences); }; @@ -256,7 +264,6 @@ ui::PageTransition transition = [self pageTransitionFromNavigationType:action.navigationType]; - BOOL isMainFrameNavigationAction = [self isMainFrameNavigationAction:action]; if (isMainFrameNavigationAction) { web::NavigationContextImpl* context = [self contextForPendingMainFrameNavigationWithURL:requestURL];
diff --git a/media/filters/offloading_video_decoder.cc b/media/filters/offloading_video_decoder.cc index 609e9cb7..fd67c591 100644 --- a/media/filters/offloading_video_decoder.cc +++ b/media/filters/offloading_video_decoder.cc
@@ -13,6 +13,7 @@ #include "base/task/sequenced_task_runner.h" #include "base/task/thread_pool.h" #include "media/base/bind_to_current_loop.h" +#include "media/base/cdm_context.h" #include "media/base/decoder_buffer.h" #include "media/base/video_frame.h"
diff --git a/media/fuchsia/mojom/fuchsia_media_resource_provider.mojom b/media/fuchsia/mojom/fuchsia_media_resource_provider.mojom index 2bc4129..d743a90 100644 --- a/media/fuchsia/mojom/fuchsia_media_resource_provider.mojom +++ b/media/fuchsia/mojom/fuchsia_media_resource_provider.mojom
@@ -37,17 +37,16 @@ // `key_system`. Implementation should make sure the persistent storage is // isolated per web origin. CreateCdm(string key_system, CdmRequest cdm_request); - - // Create connection to fuchsia::media::StreamProcessor for the specified - // `codec`. - // TODO(crbug.com/1198266): Move this to the new FuchsiaMediaCodecProvider. - CreateVideoDecoder(VideoCodec codec, VideoDecoderSecureMemoryMode secure_mode, - StreamProcessorRequest stream_processor_request); }; // Interface implemented in the browser process and bound once per set of // GpuVideoAcceleratorFactories in the renderer to get hardware codec resources. interface FuchsiaMediaCodecProvider { + // Create connection to fuchsia::media::StreamProcessor for the specified + // `codec`. + CreateVideoDecoder(VideoCodec codec, VideoDecoderSecureMemoryMode secure_mode, + StreamProcessorRequest stream_processor_request); + // Returns video decoder configs that are supported by the driver-based local // codec factory. GetSupportedVideoDecoderConfigs() =>
diff --git a/media/fuchsia/video/fuchsia_decoder_factory.cc b/media/fuchsia/video/fuchsia_decoder_factory.cc index d180491..98672b497 100644 --- a/media/fuchsia/video/fuchsia_decoder_factory.cc +++ b/media/fuchsia/video/fuchsia_decoder_factory.cc
@@ -12,7 +12,7 @@ namespace media { FuchsiaDecoderFactory::FuchsiaDecoderFactory( - mojo::PendingRemote<media::mojom::FuchsiaMediaResourceProvider> + mojo::PendingRemote<media::mojom::FuchsiaMediaCodecProvider> resource_provider, bool allow_overlays) : resource_provider_(std::move(resource_provider)),
diff --git a/media/fuchsia/video/fuchsia_decoder_factory.h b/media/fuchsia/video/fuchsia_decoder_factory.h index ac3b3cb..adfc2a5 100644 --- a/media/fuchsia/video/fuchsia_decoder_factory.h +++ b/media/fuchsia/video/fuchsia_decoder_factory.h
@@ -14,7 +14,7 @@ class FuchsiaDecoderFactory final : public DecoderFactory { public: FuchsiaDecoderFactory( - mojo::PendingRemote<media::mojom::FuchsiaMediaResourceProvider> + mojo::PendingRemote<media::mojom::FuchsiaMediaCodecProvider> resource_provider, bool allow_overlays); ~FuchsiaDecoderFactory() final; @@ -33,7 +33,7 @@ std::vector<std::unique_ptr<VideoDecoder>>* video_decoders) override; private: - const mojo::SharedRemote<media::mojom::FuchsiaMediaResourceProvider> + const mojo::SharedRemote<media::mojom::FuchsiaMediaCodecProvider> resource_provider_; const bool allow_overlays_; };
diff --git a/media/fuchsia/video/fuchsia_video_decoder.cc b/media/fuchsia/video/fuchsia_video_decoder.cc index f20cdb5..103d6dd4 100644 --- a/media/fuchsia/video/fuchsia_video_decoder.cc +++ b/media/fuchsia/video/fuchsia_video_decoder.cc
@@ -224,11 +224,11 @@ FuchsiaVideoDecoder::FuchsiaVideoDecoder( scoped_refptr<viz::RasterContextProvider> raster_context_provider, - const mojo::SharedRemote<media::mojom::FuchsiaMediaResourceProvider>& - media_resource_provider, + const mojo::SharedRemote<media::mojom::FuchsiaMediaCodecProvider>& + media_codec_provider, bool allow_overlays) : raster_context_provider_(raster_context_provider), - media_resource_provider_(media_resource_provider), + media_codec_provider_(media_codec_provider), use_overlays_for_video_(allow_overlays && base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kUseOverlaysForVideo)), @@ -322,8 +322,8 @@ ReleaseOutputBuffers(); fuchsia::media::StreamProcessorPtr decoder; - media_resource_provider_->CreateVideoDecoder(config.codec(), secure_mode, - decoder.NewRequest()); + media_codec_provider_->CreateVideoDecoder(config.codec(), secure_mode, + decoder.NewRequest()); decoder_ = std::make_unique<StreamProcessorHelper>(std::move(decoder), this); current_config_ = config;
diff --git a/media/fuchsia/video/fuchsia_video_decoder.h b/media/fuchsia/video/fuchsia_video_decoder.h index 670b468..f116dca 100644 --- a/media/fuchsia/video/fuchsia_video_decoder.h +++ b/media/fuchsia/video/fuchsia_video_decoder.h
@@ -31,14 +31,18 @@ namespace media { +namespace mojom { +class FuchsiaMediaCodecProvider; +} // namespace mojom + class MEDIA_EXPORT FuchsiaVideoDecoder : public VideoDecoder, public SysmemBufferStream::Sink, public StreamProcessorHelper::Client { public: FuchsiaVideoDecoder( scoped_refptr<viz::RasterContextProvider> raster_context_provider, - const mojo::SharedRemote<media::mojom::FuchsiaMediaResourceProvider>& - media_resource_provider, + const mojo::SharedRemote<media::mojom::FuchsiaMediaCodecProvider>& + media_codec_provider, bool allow_overlays); ~FuchsiaVideoDecoder() override; @@ -116,8 +120,9 @@ void ReleaseOutputBuffers(); const scoped_refptr<viz::RasterContextProvider> raster_context_provider_; - const mojo::SharedRemote<media::mojom::FuchsiaMediaResourceProvider> - media_resource_provider_; + const mojo::SharedRemote<media::mojom::FuchsiaMediaCodecProvider> + media_codec_provider_; + const bool use_overlays_for_video_; OutputCB output_cb_;
diff --git a/media/fuchsia/video/fuchsia_video_decoder_unittest.cc b/media/fuchsia/video/fuchsia_video_decoder_unittest.cc index 92c2df9..99a1c74 100644 --- a/media/fuchsia/video/fuchsia_video_decoder_unittest.cc +++ b/media/fuchsia/video/fuchsia_video_decoder_unittest.cc
@@ -300,16 +300,10 @@ base::OnceClosure on_destroyed_; }; -class TestFuchsiaMediaResourceProvider - : public media::mojom::FuchsiaMediaResourceProvider { +class TestFuchsiaMediaCodecProvider + : public media::mojom::FuchsiaMediaCodecProvider { public: - // media::mojom::FuchsiaMediaResourceProvider implementation. - void CreateCdm( - const std::string& key_system, - fidl::InterfaceRequest<fuchsia::media::drm::ContentDecryptionModule> - request) final { - ADD_FAILURE(); - } + // media::mojom::FuchsiaMediaCodecProvider implementation. void CreateVideoDecoder( media::VideoCodec codec, media::mojom::VideoDecoderSecureMemoryMode secure_mode, @@ -346,7 +340,12 @@ std::move(stream_processor_request)); } - mojo::Receiver<media::mojom::FuchsiaMediaResourceProvider> receiver_{this}; + void GetSupportedVideoDecoderConfigs( + GetSupportedVideoDecoderConfigsCallback callback) final { + ADD_FAILURE(); + } + + mojo::Receiver<media::mojom::FuchsiaMediaCodecProvider> receiver_{this}; }; class FakeClientNativePixmap : public gfx::ClientNativePixmap { @@ -407,8 +406,8 @@ base::MakeRefCounted<TestRasterContextProvider>()) { auto decoder = std::make_unique<FuchsiaVideoDecoder>( raster_context_provider_.get(), - mojo::SharedRemote<media::mojom::FuchsiaMediaResourceProvider>( - test_media_resource_provider_.receiver_.BindNewPipeAndPassRemote()), + mojo::SharedRemote<media::mojom::FuchsiaMediaCodecProvider>( + test_media_codec_provider_.receiver_.BindNewPipeAndPassRemote()), /*allow_overlays=*/false); decoder->SetClientNativePixmapFactoryForTests( std::make_unique<FakeClientNativePixmapFactory>()); @@ -500,7 +499,7 @@ base::test::SingleThreadTaskEnvironment task_environment_{ base::test::SingleThreadTaskEnvironment::MainThreadType::IO}; - TestFuchsiaMediaResourceProvider test_media_resource_provider_; + TestFuchsiaMediaCodecProvider test_media_codec_provider_; scoped_refptr<TestRasterContextProvider> raster_context_provider_;
diff --git a/media/gpu/v4l2/test/vp8_decoder.cc b/media/gpu/v4l2/test/vp8_decoder.cc index 00ab7b9..873e2e0 100644 --- a/media/gpu/v4l2/test/vp8_decoder.cc +++ b/media/gpu/v4l2/test/vp8_decoder.cc
@@ -223,6 +223,50 @@ return v4l2_frame_headers; } +// Checks if the buffer slot holding the reference frame is not used by other +// frames +bool IsBufferSlotInUse( + const media::Vp8FrameHeader& frame_hdr, + const std::array<scoped_refptr<media::v4l2_test::MmapedBuffer>, + media::kNumVp8ReferenceBuffers>& ref_frames, + size_t curr_ref_frame_index) { + for (size_t i = 0; i < media::kNumVp8ReferenceBuffers; i++) { + // Skips |curr_ref_frame_index| to avoid comparing against itself and + // removing it + if (i == curr_ref_frame_index) + continue; + + bool is_frame_not_refreshed = false; + switch (i) { + case media::VP8_FRAME_ALTREF: + if (!frame_hdr.refresh_alternate_frame && + frame_hdr.copy_buffer_to_alternate == + media::Vp8FrameHeader::NO_ALT_REFRESH) + is_frame_not_refreshed = true; + break; + case media::VP8_FRAME_GOLDEN: + if (!frame_hdr.refresh_golden_frame && + frame_hdr.copy_buffer_to_golden == + media::Vp8FrameHeader::NO_GOLDEN_REFRESH) + is_frame_not_refreshed = true; + break; + case media::VP8_FRAME_LAST: + if (!frame_hdr.refresh_last) + is_frame_not_refreshed = true; + break; + default: + NOTREACHED() << "Invalid reference frame index"; + } + const bool is_candidate_in_use = + (ref_frames[i]->buffer_id() == + ref_frames[curr_ref_frame_index]->buffer_id()); + + if (is_frame_not_refreshed && is_candidate_in_use) + return true; + } + return false; +} + } // namespace namespace media { namespace v4l2_test { @@ -324,8 +368,42 @@ std::move(OUTPUT_queue), std::move(CAPTURE_queue))); } +void Vp8Decoder::UpdateReusableReferenceBufferSlots( + const Vp8FrameHeader& frame_hdr, + const size_t curr_ref_frame_index, + std::set<int>& reusable_buffer_slots) { + const uint16_t reusable_candidate_buffer_id = + ref_frames_[curr_ref_frame_index]->buffer_id(); + reusable_buffer_slots.insert(reusable_candidate_buffer_id); + + bool is_buffer_slot_copied = false; + switch (curr_ref_frame_index) { + case VP8_FRAME_ALTREF: + is_buffer_slot_copied = + frame_hdr.copy_buffer_to_golden == Vp8FrameHeader::COPY_ALT_TO_GOLDEN; + break; + case VP8_FRAME_GOLDEN: + is_buffer_slot_copied = frame_hdr.copy_buffer_to_alternate == + Vp8FrameHeader::COPY_GOLDEN_TO_ALT; + break; + case VP8_FRAME_LAST: + is_buffer_slot_copied = (frame_hdr.copy_buffer_to_alternate == + Vp8FrameHeader::COPY_LAST_TO_ALT) || + (frame_hdr.copy_buffer_to_golden == + Vp8FrameHeader::COPY_LAST_TO_GOLDEN); + break; + default: + NOTREACHED() << "Invalid reference frame index"; + } + const bool is_buffer_slot_in_use = + IsBufferSlotInUse(frame_hdr, ref_frames_, curr_ref_frame_index); + + if (is_buffer_slot_copied || is_buffer_slot_in_use) + reusable_buffer_slots.erase(reusable_candidate_buffer_id); +} + std::set<int> Vp8Decoder::RefreshReferenceSlots( - Vp8FrameHeader const& frame_hdr, + const Vp8FrameHeader& frame_hdr, MmapedBuffer* buffer, std::set<uint32_t> queued_buffer_indexes) { std::set<int> reusable_buffer_slots = {}; @@ -345,15 +423,21 @@ } if (frame_hdr.refresh_alternate_frame) { + UpdateReusableReferenceBufferSlots(frame_hdr, VP8_FRAME_ALTREF, + reusable_buffer_slots); ref_frames_[VP8_FRAME_ALTREF] = buffer; } else { switch (frame_hdr.copy_buffer_to_alternate) { case Vp8FrameHeader::COPY_LAST_TO_ALT: DCHECK(ref_frames_[VP8_FRAME_LAST]); + UpdateReusableReferenceBufferSlots(frame_hdr, VP8_FRAME_ALTREF, + reusable_buffer_slots); ref_frames_[VP8_FRAME_ALTREF] = ref_frames_[VP8_FRAME_LAST]; break; case Vp8FrameHeader::COPY_GOLDEN_TO_ALT: DCHECK(ref_frames_[VP8_FRAME_GOLDEN]); + UpdateReusableReferenceBufferSlots(frame_hdr, VP8_FRAME_ALTREF, + reusable_buffer_slots); ref_frames_[VP8_FRAME_ALTREF] = ref_frames_[VP8_FRAME_GOLDEN]; break; case Vp8FrameHeader::NO_ALT_REFRESH: @@ -366,15 +450,21 @@ } if (frame_hdr.refresh_golden_frame) { + UpdateReusableReferenceBufferSlots(frame_hdr, VP8_FRAME_GOLDEN, + reusable_buffer_slots); ref_frames_[VP8_FRAME_GOLDEN] = buffer; } else { switch (frame_hdr.copy_buffer_to_golden) { case Vp8FrameHeader::COPY_LAST_TO_GOLDEN: DCHECK(ref_frames_[VP8_FRAME_LAST]); + UpdateReusableReferenceBufferSlots(frame_hdr, VP8_FRAME_GOLDEN, + reusable_buffer_slots); ref_frames_[VP8_FRAME_GOLDEN] = ref_frames_[VP8_FRAME_LAST]; break; case Vp8FrameHeader::COPY_ALT_TO_GOLDEN: DCHECK(ref_frames_[VP8_FRAME_ALTREF]); + UpdateReusableReferenceBufferSlots(frame_hdr, VP8_FRAME_GOLDEN, + reusable_buffer_slots); ref_frames_[VP8_FRAME_GOLDEN] = ref_frames_[VP8_FRAME_ALTREF]; break; case Vp8FrameHeader::NO_GOLDEN_REFRESH: @@ -386,8 +476,11 @@ } } - if (frame_hdr.refresh_last) + if (frame_hdr.refresh_last) { + UpdateReusableReferenceBufferSlots(frame_hdr, VP8_FRAME_LAST, + reusable_buffer_slots); ref_frames_[VP8_FRAME_LAST] = buffer; + } DCHECK(ref_frames_[VP8_FRAME_LAST]);
diff --git a/media/gpu/v4l2/test/vp8_decoder.h b/media/gpu/v4l2/test/vp8_decoder.h index dd45891e..94d1957 100644 --- a/media/gpu/v4l2/test/vp8_decoder.h +++ b/media/gpu/v4l2/test/vp8_decoder.h
@@ -52,6 +52,12 @@ MmapedBuffer* buffer, std::set<uint32_t> queued_buffer_indexes); + // Manages buffers holding reference frames and return buffer indexes + // |reusable_buffer_slots| that can be reused in CAPTURE queue. + void UpdateReusableReferenceBufferSlots(Vp8FrameHeader const& frame_hdr, + size_t const curr_ref_frame_index, + std::set<int>& reusable_buffer_slots); + // Parser for the IVF stream to decode. const std::unique_ptr<IvfParser> ivf_parser_;
diff --git a/media/mojo/mojom/BUILD.gn b/media/mojo/mojom/BUILD.gn index 988ee25f..660e041 100644 --- a/media/mojo/mojom/BUILD.gn +++ b/media/mojo/mojom/BUILD.gn
@@ -104,6 +104,9 @@ } enabled_features = [] + if (is_linux || is_chromeos) { + enabled_features += [ "is_linux_or_chromeos" ] + } # Help select ServiceSandbox for media_service.mojom. if (mojo_media_host == "browser") {
diff --git a/media/mojo/mojom/video_encode_accelerator.mojom b/media/mojo/mojom/video_encode_accelerator.mojom index 4eccfbc..764f5382 100644 --- a/media/mojo/mojom/video_encode_accelerator.mojom +++ b/media/mojo/mojom/video_encode_accelerator.mojom
@@ -10,6 +10,7 @@ import "mojo/public/mojom/base/time.mojom"; import "ui/gfx/geometry/mojom/geometry.mojom"; import "media/mojo/mojom/video_encoder_info.mojom"; +import "sandbox/policy/mojom/sandbox.mojom"; // This file is the Mojo version of the media::VideoEncodeAccelerator interface // and describes the communication between a Client and a remote "service" @@ -64,6 +65,31 @@ => (array<VideoEncodeAcceleratorSupportedProfile> profiles); }; +// This interface allows the browser process to broker +// VideoEncodeAcceleratorProvider connection requests on behalf of a renderer. +// The browser creates the mojo pipe and gives the receiver to a utility +// process. The expected usage is as follows: +// +// 1) The browser process receives a request from a renderer process to bind a +// pending_receiver<VideoEncodeAcceleratorProvider>. +// +// 2) To satisfy that request, the browser process first starts a utility +// process that hosts a VideoEncodeAcceleratorProviderFactory if it hasn't +// already done so -- note that each renderer process should get its own +// corresponding utility process. +// +// 3) The browser process calls CreateVideoEncodeAcceleratorProvider() passing +// the pending_receiver<VideoEncodeAcceleratorProvider> received from the +// renderer process. +[EnableIf=is_linux_or_chromeos, +ServiceSandbox=sandbox.mojom.Sandbox.kHardwareVideoEncoding] +interface VideoEncodeAcceleratorProviderFactory { + // Creates a VideoEncodeAcceleratorProvider and should be called by the + // browser process. + CreateVideoEncodeAcceleratorProvider( + pending_receiver<VideoEncodeAcceleratorProvider> receiver); +}; + // This defines a mojo transport format used in the // mojo::VideoBitrateAllocation that corresponds to media::Bitrate::peak_bps_ struct VariableBitratePeak {
diff --git a/media/mojo/services/BUILD.gn b/media/mojo/services/BUILD.gn index 049f0646..b79cb992 100644 --- a/media/mojo/services/BUILD.gn +++ b/media/mojo/services/BUILD.gn
@@ -128,6 +128,13 @@ [ "//chromeos/components/cdm_factory_daemon:cdm_factory_daemon_gpu" ] } + if (is_linux || is_chromeos) { + sources += [ + "mojo_video_encode_accelerator_provider_factory.cc", + "mojo_video_encode_accelerator_provider_factory.h", + ] + } + if (is_android) { sources += [ "android_mojo_media_client.cc",
diff --git a/media/mojo/services/mojo_video_encode_accelerator_provider_factory.cc b/media/mojo/services/mojo_video_encode_accelerator_provider_factory.cc new file mode 100644 index 0000000..f872441 --- /dev/null +++ b/media/mojo/services/mojo_video_encode_accelerator_provider_factory.cc
@@ -0,0 +1,49 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/mojo/services/mojo_video_encode_accelerator_provider_factory.h" +#include "gpu/config/gpu_driver_bug_workarounds.h" +#include "gpu/config/gpu_info.h" +#include "gpu/config/gpu_preferences.h" +#include "media/base/media_log.h" +#include "media/gpu/gpu_video_encode_accelerator_factory.h" +#include "media/mojo/services/mojo_video_encode_accelerator_provider.h" + +namespace media { + +MojoVideoEncodeAcceleratorProviderFactory:: + MojoVideoEncodeAcceleratorProviderFactory() + : receiver_(this) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +} + +MojoVideoEncodeAcceleratorProviderFactory:: + ~MojoVideoEncodeAcceleratorProviderFactory() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +} + +void MojoVideoEncodeAcceleratorProviderFactory::BindReceiver( + mojo::PendingReceiver<mojom::VideoEncodeAcceleratorProviderFactory> + receiver) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(!receiver_.is_bound()); + receiver_.Bind(std::move(receiver)); +} + +void MojoVideoEncodeAcceleratorProviderFactory:: + CreateVideoEncodeAcceleratorProvider( + mojo::PendingReceiver<mojom::VideoEncodeAcceleratorProvider> receiver) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + // TODO(b/248540499): pass useful gpu::GpuPreferences, + // gpu::GpuDriverBugWorkarounds, and gpu::GPUInfo::GPUDevice instances. + std::unique_ptr<mojom::VideoEncodeAcceleratorProvider> provider = + std::make_unique<MojoVideoEncodeAcceleratorProvider>( + base::BindRepeating(&GpuVideoEncodeAcceleratorFactory::CreateVEA), + gpu::GpuPreferences(), gpu::GpuDriverBugWorkarounds(), + gpu::GPUInfo::GPUDevice()); + + video_encoder_providers_.Add(std::move(provider), std::move(receiver)); +} + +} // namespace media \ No newline at end of file
diff --git a/media/mojo/services/mojo_video_encode_accelerator_provider_factory.h b/media/mojo/services/mojo_video_encode_accelerator_provider_factory.h new file mode 100644 index 0000000..88f281bc --- /dev/null +++ b/media/mojo/services/mojo_video_encode_accelerator_provider_factory.h
@@ -0,0 +1,51 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_MOJO_SERVICES_MOJO_VIDEO_ENCODE_ACCELERATOR_PROVIDER_FACTORY_H_ +#define MEDIA_MOJO_SERVICES_MOJO_VIDEO_ENCODE_ACCELERATOR_PROVIDER_FACTORY_H_ + +#include "base/sequence_checker.h" +#include "media/mojo/mojom/video_encode_accelerator.mojom.h" +#include "media/mojo/services/media_mojo_export.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "mojo/public/cpp/bindings/unique_receiver_set.h" + +namespace media { + +// This class implements mojom::VideoEncodeAcceleratorProviderFactory and lives +// in a utility process. This class houses a UniqueReceiverSet of +// mojom::VideoEncodeAcceleratorProviders so that each utility process can have +// multiple encoder providers. +class MEDIA_MOJO_EXPORT MojoVideoEncodeAcceleratorProviderFactory + : public mojom::VideoEncodeAcceleratorProviderFactory { + public: + MojoVideoEncodeAcceleratorProviderFactory(); + MojoVideoEncodeAcceleratorProviderFactory( + const MojoVideoEncodeAcceleratorProviderFactory&) = delete; + MojoVideoEncodeAcceleratorProviderFactory& operator=( + const MojoVideoEncodeAcceleratorProviderFactory&) = delete; + ~MojoVideoEncodeAcceleratorProviderFactory() override; + + void BindReceiver( + mojo::PendingReceiver<mojom::VideoEncodeAcceleratorProviderFactory> + receiver); + + // mojom::VideoEncodeAcceleratorProviderFactory implementation. + void CreateVideoEncodeAcceleratorProvider( + mojo::PendingReceiver<mojom::VideoEncodeAcceleratorProvider> receiver) + override; + + private: + mojo::Receiver<mojom::VideoEncodeAcceleratorProviderFactory> receiver_ + GUARDED_BY_CONTEXT(sequence_checker_); + mojo::UniqueReceiverSet<mojom::VideoEncodeAcceleratorProvider> + video_encoder_providers_ GUARDED_BY_CONTEXT(sequence_checker_); + + SEQUENCE_CHECKER(sequence_checker_); +}; + +} // namespace media + +#endif // MEDIA_MOJO_SERVICES_MOJO_VIDEO_ENCODE_ACCELERATOR_PROVIDER_FACTORY_H_ \ No newline at end of file
diff --git a/mojo/public/tools/bindings/generators/ts_templates/module_definition.tmpl b/mojo/public/tools/bindings/generators/ts_templates/module_definition.tmpl index a42588c..e6c998c6 100644 --- a/mojo/public/tools/bindings/generators/ts_templates/module_definition.tmpl +++ b/mojo/public/tools/bindings/generators/ts_templates/module_definition.tmpl
@@ -38,18 +38,12 @@ {#--- Struct and Union forward declarations #} {% for struct in structs %} -/** - * @const { {$:!mojo.internal.MojomType}} - */ -export const {{struct.name}}Spec = - { $: /** @type {!mojo.internal.MojomType} */ ({}) }; +export const {{struct.name}}Spec: { $: mojo.internal.MojomType } = + { $: {} as unknown as mojo.internal.MojomType }; {% endfor %} {%- for union in unions %} -/** - * @const { {$:!mojo.internal.MojomType} } - */ -export const {{union.name}}Spec = - { $: /** @type {!mojo.internal.MojomType} */ ({}) }; +export const {{union.name}}Spec: { $: mojo.internal.MojomType } = + { $: {} as unknown as mojo.internal.MojomType }; {% endfor %} {#--- Struct definitions #}
diff --git a/mojo/public/tools/bindings/mojom.gni b/mojo/public/tools/bindings/mojom.gni index 080bcee7..f2c25813 100644 --- a/mojo/public/tools/bindings/mojom.gni +++ b/mojo/public/tools/bindings/mojom.gni
@@ -699,6 +699,8 @@ } action(parser_target_name) { + allow_remote = true + custom_processor = "mojom_parser" script = mojom_parser_script inputs = mojom_parser_sources + ply_sources + [ build_metadata_filename ] sources = sources_list @@ -714,7 +716,11 @@ foreach(source, sources_list) { filelist += [ rebase_path(source, root_build_dir) ] } - response_file_contents = filelist + + # Workaround for https://github.com/ninja-build/ninja/issues/1966. + rsp_file = "$target_gen_dir/${target_name}.rsp" + write_file(rsp_file, filelist) + inputs += [ rsp_file ] args = [ # Resolve relative input mojom paths against both the root src dir and @@ -727,7 +733,7 @@ "--output-root", rebase_path(root_gen_dir, root_build_dir), - "--mojom-file-list={{response_file_name}}", + "--mojom-file-list=" + rebase_path(rsp_file, root_build_dir), "--check-imports", rebase_path(build_metadata_filename, root_build_dir), @@ -834,6 +840,7 @@ } action(generator_cpp_message_ids_target_name) { + allow_remote = true script = mojom_generator_script inputs = mojom_generator_sources + jinja2_sources sources = sources_list + @@ -858,10 +865,13 @@ outputs += [ "$root_gen_dir/$base_path-shared-message-ids.h" ] } - response_file_contents = filelist + # Workaround for https://github.com/ninja-build/ninja/issues/1966. + rsp_file = "$target_gen_dir/${target_name}.rsp" + write_file(rsp_file, filelist) + inputs += [ rsp_file ] args += [ - "--filelist={{response_file_name}}", + "--filelist=" + rebase_path(rsp_file, root_build_dir), "--generate_non_variant_code", "--generate_message_ids", "-g", @@ -878,6 +888,7 @@ generator_shared_target_name = "${target_name}_shared__generator" action(generator_shared_target_name) { + allow_remote = true visibility = [ ":*" ] script = mojom_generator_script inputs = mojom_generator_sources + jinja2_sources @@ -911,10 +922,13 @@ ] } - response_file_contents = filelist + # Workaround for https://github.com/ninja-build/ninja/issues/1966. + rsp_file = "$target_gen_dir/${target_name}.rsp" + write_file(rsp_file, filelist) + inputs += [ rsp_file ] args += [ - "--filelist={{response_file_name}}", + "--filelist=" + rebase_path(rsp_file, root_build_dir), "--generate_non_variant_code", "-g", "c++", @@ -1004,6 +1018,7 @@ "${target_name}_mojolpm_proto_generator" action(generator_mojolpm_proto_target_name) { + allow_remote = true script = mojom_generator_script inputs = mojom_generator_sources + jinja2_sources sources = @@ -1043,10 +1058,13 @@ outputs += [ "$target_gen_dir/$source_file.mojolpm.proto" ] } - response_file_contents = filelist + # Workaround for https://github.com/ninja-build/ninja/issues/1966. + rsp_file = "$target_gen_dir/${target_name}.rsp" + write_file(rsp_file, filelist) + inputs += [ rsp_file ] args += [ - "--filelist={{response_file_name}}", + "--filelist=" + rebase_path(rsp_file, root_build_dir), "--generate_non_variant_code", "-g", "mojolpm", @@ -1262,6 +1280,7 @@ # TODO(crbug.com/1194274): Investigate nondeterminism in Py3 builds. action(generator_target_name) { + allow_remote = true visibility = [ ":*" ] script = mojom_generator_script inputs = mojom_generator_sources + jinja2_sources @@ -1310,10 +1329,12 @@ } } - response_file_contents = filelist - + # Workaround for https://github.com/ninja-build/ninja/issues/1966. + rsp_file = "$target_gen_dir/${target_name}.rsp" + write_file(rsp_file, filelist) + inputs += [ rsp_file ] args += [ - "--filelist={{response_file_name}}", + "--filelist=" + rebase_path("$rsp_file", root_build_dir), "-g", ] @@ -1472,6 +1493,7 @@ _mojom_target_name = target_name action(_typemap_validator_target_name) { + allow_remote = true script = "$mojom_generator_root/validate_typemap_config.py" inputs = [ _typemap_config_filename ] outputs = [ _typemap_stamp_filename ] @@ -1483,6 +1505,7 @@ } action(type_mappings_target_name) { + allow_remote = true inputs = mojom_generator_sources + jinja2_sources + [ _typemap_stamp_filename ] outputs = [ type_mappings_path ]
diff --git a/net/quic/quic_http3_logger.cc b/net/quic/quic_http3_logger.cc index bdc46c25..e6a450cf 100644 --- a/net/quic/quic_http3_logger.cc +++ b/net/quic/quic_http3_logger.cc
@@ -35,10 +35,6 @@ base::Value NetLogPriorityUpdateParams(const quic::PriorityUpdateFrame& frame) { base::Value::Dict dict; - dict.Set("type", frame.prioritized_element_type == - quic::PrioritizedElementType::REQUEST_STREAM - ? "request_stream" - : "push_stream"); dict.Set("prioritized_element_id", NetLogNumberValue(frame.prioritized_element_id)); dict.Set("priority_field_value", frame.priority_field_value);
diff --git a/net/quic/quic_test_packet_maker.cc b/net/quic/quic_test_packet_maker.cc index 45ccf57..d4c0aeaf 100644 --- a/net/quic/quic_test_packet_maker.cc +++ b/net/quic/quic_test_packet_maker.cc
@@ -1668,7 +1668,6 @@ spdy::SpdyPriority priority, quic::QuicStreamId stream_id) { quic::PriorityUpdateFrame priority_update; - priority_update.prioritized_element_type = quic::REQUEST_STREAM; priority_update.prioritized_element_id = stream_id; priority_update.priority_field_value = base::StrCat({"u=", base::NumberToString(priority)});
diff --git a/net/socket/websocket_transport_client_socket_pool.cc b/net/socket/websocket_transport_client_socket_pool.cc index ac1ec21..8d52c9b8 100644 --- a/net/socket/websocket_transport_client_socket_pool.cc +++ b/net/socket/websocket_transport_client_socket_pool.cc
@@ -161,7 +161,7 @@ ReleaseSocket(handle->group_id(), std::move(socket), handle->group_generation()); if (!DeleteJob(handle)) - pending_callbacks_.erase(handle); + pending_callbacks_.erase(reinterpret_cast<ClientSocketHandleID>(handle)); ActivateStalledRequest(); } @@ -230,7 +230,7 @@ const ClientSocketHandle* handle) const { if (stalled_request_map_.find(handle) != stalled_request_map_.end()) return LOAD_STATE_WAITING_FOR_AVAILABLE_SOCKET; - if (pending_callbacks_.count(handle)) + if (pending_callbacks_.count(reinterpret_cast<ClientSocketHandleID>(handle))) return LOAD_STATE_CONNECTING; return LookupConnectJob(handle)->GetLoadState(); } @@ -345,21 +345,21 @@ ClientSocketHandle* handle, CompletionOnceCallback callback, int rv) { - DCHECK(!pending_callbacks_.count(handle)); - pending_callbacks_.insert(handle); + const auto handle_id = reinterpret_cast<ClientSocketHandleID>(handle); + DCHECK(!pending_callbacks_.count(handle_id)); + pending_callbacks_.insert(handle_id); base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( FROM_HERE, base::BindOnce(&WebSocketTransportClientSocketPool::InvokeUserCallback, - weak_factory_.GetWeakPtr(), - base::UnsafeDanglingUntriaged(handle), std::move(callback), + weak_factory_.GetWeakPtr(), handle_id, std::move(callback), rv)); } void WebSocketTransportClientSocketPool::InvokeUserCallback( - ClientSocketHandle* handle, + ClientSocketHandleID handle_id, CompletionOnceCallback callback, int rv) { - if (pending_callbacks_.erase(handle)) + if (pending_callbacks_.erase(handle_id)) std::move(callback).Run(rv); }
diff --git a/net/socket/websocket_transport_client_socket_pool.h b/net/socket/websocket_transport_client_socket_pool.h index 0427d54..fea8b444 100644 --- a/net/socket/websocket_transport_client_socket_pool.h +++ b/net/socket/websocket_transport_client_socket_pool.h
@@ -29,6 +29,13 @@ struct CommonConnectJobParams; struct NetworkTrafficAnnotationTag; +// Identifier for a ClientSocketHandle to scope the lifetime of references. +// ClientSocketHandleID are derived from ClientSocketHandle*, used in +// comparison only, and are never dereferenced. We use an std::uintptr_t here to +// match the size of a pointer, and to prevent dereferencing. Also, our +// tooling complains about dangling pointers if we pass around a raw ptr. +using ClientSocketHandleID = std::uintptr_t; + class NET_EXPORT_PRIVATE WebSocketTransportClientSocketPool : public ClientSocketPool { public: @@ -183,7 +190,7 @@ void InvokeUserCallbackLater(ClientSocketHandle* handle, CompletionOnceCallback callback, int rv); - void InvokeUserCallback(ClientSocketHandle* handle, + void InvokeUserCallback(ClientSocketHandleID handle_id, CompletionOnceCallback callback, int rv); bool ReachedMaxSocketsLimit() const; @@ -199,7 +206,7 @@ bool DeleteStalledRequest(ClientSocketHandle* handle); const ProxyServer proxy_server_; - std::set<const ClientSocketHandle*> pending_callbacks_; + std::set<ClientSocketHandleID> pending_callbacks_; PendingConnectsMap pending_connects_; StalledRequestQueue stalled_request_queue_; StalledRequestMap stalled_request_map_;
diff --git a/services/device/wake_lock/power_save_blocker/BUILD.gn b/services/device/wake_lock/power_save_blocker/BUILD.gn index f0aaaaa..fe9563e 100644 --- a/services/device/wake_lock/power_save_blocker/BUILD.gn +++ b/services/device/wake_lock/power_save_blocker/BUILD.gn
@@ -51,12 +51,16 @@ } else if ((is_linux || is_chromeos) && use_dbus) { if (is_chromeos_lacros) { sources += [ "power_save_blocker_lacros.cc" ] + deps += [ + "//chromeos/crosapi/mojom", + "//chromeos/lacros", + ] } else { sources += [ "power_save_blocker_linux.cc" ] + deps += [ "//ui/display" ] } deps += [ "//dbus", - "//ui/display", "//ui/gfx", ] } else if (is_mac) {
diff --git a/services/device/wake_lock/power_save_blocker/power_save_blocker_lacros.cc b/services/device/wake_lock/power_save_blocker/power_save_blocker_lacros.cc index aa51acbc..f1cc5b2 100644 --- a/services/device/wake_lock/power_save_blocker/power_save_blocker_lacros.cc +++ b/services/device/wake_lock/power_save_blocker/power_save_blocker_lacros.cc
@@ -7,44 +7,61 @@ #include <string> #include "base/memory/ref_counted.h" -#include "ui/display/screen.h" +#include "chromeos/crosapi/mojom/power.mojom.h" +#include "chromeos/lacros/lacros_service.h" +#include "mojo/public/cpp/bindings/receiver.h" namespace device { /******** PowerSaveBlocker::Delegate ********/ -// Lacros-chrome PowerSaveBlocker uses ash-chrome ProwerSaveBlocker via Wayland. - +// Lacros-chrome PowerSaveBlocker uses ash-chrome ProwerSaveBlocker via crosapi. +// RAII style is maintained by keeping a crosapi::mojom::PowerWakeLock Mojo +// connection, whose disconnection triggers resource release in ash-chrome. class PowerSaveBlocker::Delegate : public base::RefCountedThreadSafe<PowerSaveBlocker::Delegate> { public: - explicit Delegate(scoped_refptr<base::SequencedTaskRunner> ui_task_runner) - : ui_task_runner_(ui_task_runner) {} + Delegate(mojom::WakeLockType type, + mojom::WakeLockReason reason, + const std::string& description, + scoped_refptr<base::SequencedTaskRunner> ui_task_runner) + : type_(type), + reason_(reason), + description_(description), + ui_task_runner_(ui_task_runner) {} Delegate(const Delegate&) = delete; Delegate& operator=(const Delegate&) = delete; void ApplyBlock() { DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); - DCHECK(!screen_saver_suspender_); - if (auto* const screen = display::Screen::GetScreen()) { - screen_saver_suspender_ = screen->SuspendScreenSaver(); + auto* lacros_service = chromeos::LacrosService::Get(); + if (lacros_service->IsAvailable<crosapi::mojom::Power>()) { + lacros_service->GetRemote<crosapi::mojom::Power>()->AddPowerSaveBlocker( + receiver_.BindNewPipeAndPassRemote(), type_, reason_, description_); } } void RemoveBlock() { DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); - screen_saver_suspender_.reset(); + // Disconnect to make ash-chrome release its PowerSaveBlocker. + receiver_.reset(); } private: friend class base::RefCountedThreadSafe<Delegate>; virtual ~Delegate() = default; + // Connection to ash-chrome via crosapi. Disconnection from RemoveBlock() or + // Lacros termination triggers resource release in ash-chrome. + crosapi::mojom::PowerWakeLock lock_; + mojo::Receiver<crosapi::mojom::PowerWakeLock> receiver_{&lock_}; + + mojom::WakeLockType type_; + mojom::WakeLockReason reason_; + std::string description_; scoped_refptr<base::SequencedTaskRunner> ui_task_runner_; - std::unique_ptr<display::Screen::ScreenSaverSuspender> - screen_saver_suspender_; }; /******** PowerSaveBlocker ********/ @@ -55,7 +72,10 @@ const std::string& description, scoped_refptr<base::SequencedTaskRunner> ui_task_runner, scoped_refptr<base::SingleThreadTaskRunner> blocking_task_runner) - : delegate_(base::MakeRefCounted<Delegate>(ui_task_runner)), + : delegate_(base::MakeRefCounted<Delegate>(type, + reason, + description, + ui_task_runner)), ui_task_runner_(ui_task_runner), blocking_task_runner_(blocking_task_runner) { ui_task_runner_->PostTask(FROM_HERE,
diff --git a/services/network/proxy_service_mojo.cc b/services/network/proxy_service_mojo.cc index bc1fb22..4bf6c3b 100644 --- a/services/network/proxy_service_mojo.cc +++ b/services/network/proxy_service_mojo.cc
@@ -10,6 +10,7 @@ #include "base/bind.h" #include "base/check.h" #include "base/task/single_thread_task_runner.h" +#include "net/base/network_delegate.h" #include "net/proxy_resolution/configured_proxy_resolution_service.h" #include "net/proxy_resolution/network_delegate_error_observer.h" #include "net/proxy_resolution/proxy_resolver_factory.h"
diff --git a/services/preferences/public/cpp/dictionary_value_update.cc b/services/preferences/public/cpp/dictionary_value_update.cc index b708f0e..92c8ca01 100644 --- a/services/preferences/public/cpp/dictionary_value_update.cc +++ b/services/preferences/public/cpp/dictionary_value_update.cc
@@ -90,10 +90,10 @@ std::unique_ptr<DictionaryValueUpdate> DictionaryValueUpdate::SetDictionary( base::StringPiece path, - std::unique_ptr<base::DictionaryValue> in_value) { + base::Value::Dict in_value) { RecordPath(path); - auto* dictionary_value = static_cast<base::DictionaryValue*>(value_->SetPath( - path, base::Value::FromUniquePtrValue(std::move(in_value)))); + auto* dictionary_value = static_cast<base::DictionaryValue*>( + value_->SetPath(path, base::Value(std::move(in_value)))); return std::make_unique<DictionaryValueUpdate>( report_update_, dictionary_value, ConcatPath(path_, path)); @@ -123,10 +123,10 @@ std::unique_ptr<DictionaryValueUpdate> DictionaryValueUpdate::SetDictionaryWithoutPathExpansion( base::StringPiece path, - std::unique_ptr<base::DictionaryValue> in_value) { + base::Value::Dict in_value) { RecordKey(path); - auto* dictionary_value = static_cast<base::DictionaryValue*>(value_->SetKey( - path, base::Value::FromUniquePtrValue(std::move(in_value)))); + auto* dictionary_value = static_cast<base::DictionaryValue*>( + value_->SetKey(path, base::Value(std::move(in_value)))); std::vector<std::string> full_path = path_; full_path.push_back(std::string(path));
diff --git a/services/preferences/public/cpp/dictionary_value_update.h b/services/preferences/public/cpp/dictionary_value_update.h index a8443613..1dd6ac2c 100644 --- a/services/preferences/public/cpp/dictionary_value_update.h +++ b/services/preferences/public/cpp/dictionary_value_update.h
@@ -66,7 +66,7 @@ void SetString(base::StringPiece path, const std::u16string& in_value); std::unique_ptr<DictionaryValueUpdate> SetDictionary( base::StringPiece path, - std::unique_ptr<base::DictionaryValue> in_value); + base::Value::Dict in_value); // Like Set(), but without special treatment of '.'. This allows e.g. URLs to // be used as paths. Returns a pointer to the set `value`. @@ -77,7 +77,7 @@ // Convenience forms of SetWithoutPathExpansion(). std::unique_ptr<DictionaryValueUpdate> SetDictionaryWithoutPathExpansion( base::StringPiece path, - std::unique_ptr<base::DictionaryValue> in_value); + base::Value::Dict in_value); // These are convenience forms of Get(). The value will be retrieved // and the return value will be true if the path is valid and the value at
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json index 5c65914b7..ba467a4 100644 --- a/testing/buildbot/chromium.chromiumos.json +++ b/testing/buildbot/chromium.chromiumos.json
@@ -5812,9 +5812,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5436.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5437.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 110.0.5436.0", + "description": "Run with ash-chrome version 110.0.5437.0", "isolate_profile_data": true, "merge": { "args": [], @@ -5826,8 +5826,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v110.0.5436.0", - "revision": "version:110.0.5436.0" + "location": "lacros_version_skew_tests_v110.0.5437.0", + "revision": "version:110.0.5437.0" } ], "dimension_sets": [ @@ -5979,9 +5979,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5436.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5437.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 110.0.5436.0", + "description": "Run with ash-chrome version 110.0.5437.0", "isolate_profile_data": true, "merge": { "args": [], @@ -5993,8 +5993,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v110.0.5436.0", - "revision": "version:110.0.5436.0" + "location": "lacros_version_skew_tests_v110.0.5437.0", + "revision": "version:110.0.5437.0" } ], "dimension_sets": [ @@ -6131,9 +6131,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5436.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5437.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 110.0.5436.0", + "description": "Run with ash-chrome version 110.0.5437.0", "isolate_profile_data": true, "merge": { "args": [], @@ -6145,8 +6145,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v110.0.5436.0", - "revision": "version:110.0.5436.0" + "location": "lacros_version_skew_tests_v110.0.5437.0", + "revision": "version:110.0.5437.0" } ], "dimension_sets": [
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 7fdda85..886d108 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -85399,9 +85399,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5436.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5437.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 110.0.5436.0", + "description": "Run with ash-chrome version 110.0.5437.0", "isolate_profile_data": true, "merge": { "args": [], @@ -85413,8 +85413,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v110.0.5436.0", - "revision": "version:110.0.5436.0" + "location": "lacros_version_skew_tests_v110.0.5437.0", + "revision": "version:110.0.5437.0" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -85536,9 +85536,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5436.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5437.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 110.0.5436.0", + "description": "Run with ash-chrome version 110.0.5437.0", "isolate_profile_data": true, "merge": { "args": [], @@ -85550,8 +85550,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v110.0.5436.0", - "revision": "version:110.0.5436.0" + "location": "lacros_version_skew_tests_v110.0.5437.0", + "revision": "version:110.0.5437.0" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -85663,9 +85663,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5436.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5437.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 110.0.5436.0", + "description": "Run with ash-chrome version 110.0.5437.0", "isolate_profile_data": true, "merge": { "args": [], @@ -85677,8 +85677,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v110.0.5436.0", - "revision": "version:110.0.5436.0" + "location": "lacros_version_skew_tests_v110.0.5437.0", + "revision": "version:110.0.5437.0" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -87019,9 +87019,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5436.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5437.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 110.0.5436.0", + "description": "Run with ash-chrome version 110.0.5437.0", "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -87032,8 +87032,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v110.0.5436.0", - "revision": "version:110.0.5436.0" + "location": "lacros_version_skew_tests_v110.0.5437.0", + "revision": "version:110.0.5437.0" } ], "dimension_sets": [ @@ -87186,9 +87186,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5436.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5437.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 110.0.5436.0", + "description": "Run with ash-chrome version 110.0.5437.0", "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -87199,8 +87199,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v110.0.5436.0", - "revision": "version:110.0.5436.0" + "location": "lacros_version_skew_tests_v110.0.5437.0", + "revision": "version:110.0.5437.0" } ], "dimension_sets": [ @@ -87338,9 +87338,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5436.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5437.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 110.0.5436.0", + "description": "Run with ash-chrome version 110.0.5437.0", "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -87351,8 +87351,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v110.0.5436.0", - "revision": "version:110.0.5436.0" + "location": "lacros_version_skew_tests_v110.0.5437.0", + "revision": "version:110.0.5437.0" } ], "dimension_sets": [ @@ -88874,9 +88874,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5436.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5437.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 110.0.5436.0", + "description": "Run with ash-chrome version 110.0.5437.0", "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -88887,8 +88887,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v110.0.5436.0", - "revision": "version:110.0.5436.0" + "location": "lacros_version_skew_tests_v110.0.5437.0", + "revision": "version:110.0.5437.0" } ], "dimension_sets": [ @@ -89041,9 +89041,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5436.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5437.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 110.0.5436.0", + "description": "Run with ash-chrome version 110.0.5437.0", "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -89054,8 +89054,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v110.0.5436.0", - "revision": "version:110.0.5436.0" + "location": "lacros_version_skew_tests_v110.0.5437.0", + "revision": "version:110.0.5437.0" } ], "dimension_sets": [ @@ -89193,9 +89193,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5436.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5437.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 110.0.5436.0", + "description": "Run with ash-chrome version 110.0.5437.0", "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -89206,8 +89206,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v110.0.5436.0", - "revision": "version:110.0.5436.0" + "location": "lacros_version_skew_tests_v110.0.5437.0", + "revision": "version:110.0.5437.0" } ], "dimension_sets": [ @@ -89975,9 +89975,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5436.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5437.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 110.0.5436.0", + "description": "Run with ash-chrome version 110.0.5437.0", "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -89988,8 +89988,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v110.0.5436.0", - "revision": "version:110.0.5436.0" + "location": "lacros_version_skew_tests_v110.0.5437.0", + "revision": "version:110.0.5437.0" } ], "dimension_sets": [
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json index e40524ad..0bac7356 100644 --- a/testing/buildbot/chromium.memory.json +++ b/testing/buildbot/chromium.memory.json
@@ -8111,7 +8111,7 @@ "dimension_sets": [ { "cpu": "x86-64", - "os": "Ubuntu-18.04" + "os": "Ubuntu-20.04" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -18682,11 +18682,11 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5436.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5437.0/test_ash_chrome", "--test-launcher-print-test-stdio=always", "--combine-ash-logs-on-bots" ], - "description": "Run with ash-chrome version 110.0.5436.0", + "description": "Run with ash-chrome version 110.0.5437.0", "isolate_profile_data": true, "merge": { "args": [], @@ -18698,8 +18698,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v110.0.5436.0", - "revision": "version:110.0.5436.0" + "location": "lacros_version_skew_tests_v110.0.5437.0", + "revision": "version:110.0.5437.0" } ], "dimension_sets": [ @@ -18863,11 +18863,11 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5436.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5437.0/test_ash_chrome", "--test-launcher-print-test-stdio=always", "--combine-ash-logs-on-bots" ], - "description": "Run with ash-chrome version 110.0.5436.0", + "description": "Run with ash-chrome version 110.0.5437.0", "isolate_profile_data": true, "merge": { "args": [], @@ -18879,8 +18879,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v110.0.5436.0", - "revision": "version:110.0.5436.0" + "location": "lacros_version_skew_tests_v110.0.5437.0", + "revision": "version:110.0.5437.0" } ], "dimension_sets": [ @@ -19025,11 +19025,11 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5436.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5437.0/test_ash_chrome", "--test-launcher-print-test-stdio=always", "--combine-ash-logs-on-bots" ], - "description": "Run with ash-chrome version 110.0.5436.0", + "description": "Run with ash-chrome version 110.0.5437.0", "isolate_profile_data": true, "merge": { "args": [], @@ -19041,8 +19041,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v110.0.5436.0", - "revision": "version:110.0.5436.0" + "location": "lacros_version_skew_tests_v110.0.5437.0", + "revision": "version:110.0.5437.0" } ], "dimension_sets": [
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json index f3235615..ad0ef524 100644 --- a/testing/buildbot/chromium.perf.json +++ b/testing/buildbot/chromium.perf.json
@@ -1873,7 +1873,7 @@ { "cpu": "x86-64", "gpu": "1002:6821-4.0.20-3.2.8", - "os": "Mac-11.6.1", + "os": "Mac-12.6.1", "pool": "chrome.tests.perf", "synthetic_product_name": "MacBookPro11,5_x86-64-i7-4870HQ_AMD Radeon R8 M370X 4.0.20 [3.2.8]_Intel Haswell Iris Pro Graphics 5200 4.0.20 [3.2.8]_16384_APPLE SSD SM0512G" } @@ -1922,7 +1922,7 @@ { "cpu": "x86-64", "gpu": "1002:6821-4.0.20-3.2.8", - "os": "Mac-11.6.1", + "os": "Mac-12.6.1", "pool": "chrome.tests.perf", "synthetic_product_name": "MacBookPro11,5_x86-64-i7-4870HQ_AMD Radeon R8 M370X 4.0.20 [3.2.8]_Intel Haswell Iris Pro Graphics 5200 4.0.20 [3.2.8]_16384_APPLE SSD SM0512G" } @@ -1983,7 +1983,7 @@ { "cpu": "x86-64", "gpu": "8086:1626", - "os": "Mac-12.3", + "os": "Mac-12.6.1", "pool": "chrome.tests.perf", "synthetic_product_name": "MacBookAir7,2_x86-64-i5-5350U_Intel Broadwell HD Graphics 6000_8192_APPLE SSD SM0128G" } @@ -2032,7 +2032,7 @@ { "cpu": "x86-64", "gpu": "8086:1626", - "os": "Mac-10.12.6", + "os": "Mac-12.6.1", "pool": "chrome.tests.perf", "synthetic_product_name": "MacBookAir7,2_x86-64-i5-5350U_Intel Broadwell HD Graphics 6000_8192_APPLE SSD SM0128G" }
diff --git a/testing/buildbot/filters/android.emulator_12.gl_unittests.filter b/testing/buildbot/filters/android.emulator_12.gl_unittests.filter index 0ad3644..5ba11951 100644 --- a/testing/buildbot/filters/android.emulator_12.gl_unittests.filter +++ b/testing/buildbot/filters/android.emulator_12.gl_unittests.filter
@@ -1,7 +1,2 @@ # crbug.com/1264644 --GLImageSharedMemory/GLImageCopyTest/0.CopyTexImage --GLImageSharedMemory/GLImageCopyTest/1.CopyTexImage --GLImageSharedMemory/GLImageCopyTest/2.CopyTexImage --GLImageSharedMemory/GLImageCopyTest/3.CopyTexImage --GLImageSharedMemory/GLImageCopyTest/4.CopyTexImage -GLImageSharedMemoryPool/GLImageCopyTest/0.CopyTexImage
diff --git a/testing/buildbot/filters/mac.mac11-arm64-rel.browser_tests.filter b/testing/buildbot/filters/mac.mac11-arm64-rel.browser_tests.filter index 77637e8..c7467d8 100644 --- a/testing/buildbot/filters/mac.mac11-arm64-rel.browser_tests.filter +++ b/testing/buildbot/filters/mac.mac11-arm64-rel.browser_tests.filter
@@ -78,8 +78,6 @@ -PDFExtensionSaveWithPolicyTest.SaveWithPolicyUniqueTimeSuffix -PersistentBackground/DeclarativeNetRequestLazyApiTest.TestMatchOutcome/0 -PreinstalledAppsBrowserTest.TestUninstall --PreinstalledAppsMigrationBrowserTest.TestRollbackCompatibility --PreinstalledAppsMigrationBrowserTest.TestExtensionWasAlreadyUninstalled -PrintBrowserTest.LazyLoadedIframeFetchedCrossOrigin -ProfileBrowserTest.CreateOldProfileAsynchronous -ProfileBrowserTestWithoutDestroyProfile.DISABLE_DestroyRegularProfileBeforeOTRs
diff --git a/testing/buildbot/filters/mac.mac12-arm64-rel.browser_tests.filter b/testing/buildbot/filters/mac.mac12-arm64-rel.browser_tests.filter index 71d5ba46..fce0a18 100644 --- a/testing/buildbot/filters/mac.mac12-arm64-rel.browser_tests.filter +++ b/testing/buildbot/filters/mac.mac12-arm64-rel.browser_tests.filter
@@ -153,8 +153,6 @@ -PredictionManagerModelDownloadingBrowserTest.TestSwitchProfileDoesntCrash -PrefsFunctionalTest.TestHomepageNewTabpagePrefs -PreinstalledAppsBrowserTest.TestUninstall --PreinstalledAppsMigrationBrowserTest.TestRollbackCompatibility --PreinstalledAppsMigrationBrowserTest.TestExtensionWasAlreadyUninstalled -PrintBrowserTest.LazyLoadedIframeFetchedCrossOrigin -PrintPreviewDialogControllerBrowserTest.ReloadInitiatorTab -PrintPreviewDialogControllerBrowserTest.TaskManagementTest
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index 78f8bf2..7cbfd2dc 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -2537,16 +2537,6 @@ ], }, }, - 'Linux MSan Tests': { - 'swarming': { - 'dimension_sets': [ - { - 'cpu': 'x86-64', - 'os': 'Ubuntu-18.04', - }, - ], - }, - }, 'android-asan': { 'swarming': { 'shards': 2,
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl index af3e8270..85712e3 100644 --- a/testing/buildbot/variants.pyl +++ b/testing/buildbot/variants.pyl
@@ -22,16 +22,16 @@ }, 'LACROS_VERSION_SKEW_CANARY': { 'args': [ - '--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5436.0/test_ash_chrome', + '--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5437.0/test_ash_chrome', ], - 'description': 'Run with ash-chrome version 110.0.5436.0', + 'description': 'Run with ash-chrome version 110.0.5437.0', 'identifier': 'Lacros version skew testing ash canary', 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip', - 'location': 'lacros_version_skew_tests_v110.0.5436.0', - 'revision': 'version:110.0.5436.0', + 'location': 'lacros_version_skew_tests_v110.0.5437.0', + 'revision': 'version:110.0.5437.0', }, ], },
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 5d49ee9..006a684 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -2911,29 +2911,6 @@ ] } ], - "CombinedMicroOps": [ - { - "platforms": [ - "android", - "android_weblayer", - "chromeos", - "chromeos_lacros", - "linux", - "mac", - "windows" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "EnableSsePathForCopyLCharsX86", - "LiteralBufferCreateStringWithEncoding", - "UseHtmlAttributeNameLookup" - ] - } - ] - } - ], "CombinedNavigationOptimizations2": [ { "platforms": [ @@ -11170,6 +11147,29 @@ ] } ], + "UIEnableSharedImageCacheForGpu": [ + { + "platforms": [ + "android", + "android_weblayer", + "android_webview", + "chromeos", + "chromeos_lacros", + "fuchsia", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "UIEnableSharedImageCacheForGpu" + ] + } + ] + } + ], "UMA-NonUniformity-Trial-1-Percent": [ { "platforms": [
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index c9d75e6..e03ce6b 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc
@@ -339,6 +339,10 @@ "Prerender2InBackground", base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kPrerender2InNewTab, + "Prerender2InNewTab", + base::FEATURE_DISABLED_BY_DEFAULT); + bool IsPrerender2Enabled() { return base::FeatureList::IsEnabled(blink::features::kPrerender2); }
diff --git a/third_party/blink/common/messaging/string_message_codec.cc b/third_party/blink/common/messaging/string_message_codec.cc index b6f556d3..f18b0c29 100644 --- a/third_party/blink/common/messaging/string_message_codec.cc +++ b/third_party/blink/common/messaging/string_message_codec.cc
@@ -4,24 +4,71 @@ #include "third_party/blink/public/common/messaging/string_message_codec.h" +#include <memory> +#include <string> #include <vector> +#include "base/check_op.h" #include "base/containers/buffer_iterator.h" +#include "base/containers/span.h" +#include "base/functional/overloaded.h" #include "base/logging.h" #include "base/notreached.h" +#include "base/numerics/checked_math.h" #include "mojo/public/cpp/base/big_buffer.h" #include "third_party/blink/public/mojom/array_buffer/array_buffer_contents.mojom.h" namespace blink { namespace { -// Template helpers for visiting std::variant. -template <class... Ts> -struct overloaded : Ts... { - using Ts::operator()...; +// An ArrayBufferPayload impl based on std::vector. +class VectorArrayBuffer : public WebMessageArrayBufferPayload { + public: + VectorArrayBuffer(std::vector<uint8_t> data, size_t position, size_t length) + : data_(std::move(data)), position_(position), length_(length) { + size_t size = base::CheckAdd(position_, length_).ValueOrDie(); + CHECK_GE(data_.size(), size); + } + + size_t GetLength() const override { return length_; } + + absl::optional<base::span<const uint8_t>> GetAsSpanIfPossible() + const override { + return base::make_span(data_).subspan(position_, length_); + } + + void CopyInto(base::span<uint8_t> dest) const override { + CHECK_GE(dest.size(), length_); + memcpy(dest.data(), data_.data() + position_, length_); + } + + private: + std::vector<uint8_t> data_; + size_t position_; + size_t length_; }; -template <class... Ts> -overloaded(Ts...) -> overloaded<Ts...>; + +// An ArrayBufferPayload impl based on mojo::BigBuffer. +class BigBufferArrayBuffer : public WebMessageArrayBufferPayload { + public: + explicit BigBufferArrayBuffer(mojo_base::BigBuffer data) + : data_(std::move(data)) {} + + size_t GetLength() const override { return data_.size(); } + + absl::optional<base::span<const uint8_t>> GetAsSpanIfPossible() + const override { + return base::make_span(data_); + } + + void CopyInto(base::span<uint8_t> dest) const override { + CHECK(dest.size() >= data_.size()); + memcpy(dest.data(), data_.data(), data_.size()); + } + + private: + mojo_base::BigBuffer data_; +}; const uint32_t kVarIntShift = 7; const uint32_t kVarIntMask = (1 << kVarIntShift) - 1; @@ -98,14 +145,20 @@ } // namespace +// static +std::unique_ptr<WebMessageArrayBufferPayload> +WebMessageArrayBufferPayload::CreateForTesting(std::vector<uint8_t> data) { + auto size = data.size(); + return std::make_unique<VectorArrayBuffer>(std::move(data), 0, size); +} + TransferableMessage EncodeWebMessagePayload(const WebMessagePayload& payload) { TransferableMessage message; std::vector<uint8_t> buffer; WriteUint8(kVersionTag, &buffer); WriteUint32(kVersion, &buffer); - absl::visit( - overloaded{ + base::Overloaded{ [&](const std::u16string& str) { if (ContainsOnlyLatin1(str)) { std::string data_latin1(str.cbegin(), str.cend()); @@ -122,12 +175,14 @@ &buffer); } }, - [&](const std::vector<uint8_t>& array_buffer) { + [&](const std::unique_ptr<WebMessageArrayBufferPayload>& + array_buffer) { WriteUint8(kArrayBufferTransferTag, &buffer); // Write at the first slot. WriteUint32(0, &buffer); - mojo_base::BigBuffer big_buffer(array_buffer); + mojo_base::BigBuffer big_buffer(array_buffer->GetLength()); + array_buffer->CopyInto(base::make_span(big_buffer)); message.array_buffer_contents_array.push_back( mojom::SerializedArrayBufferContents::New( std::move(big_buffer))); @@ -141,7 +196,7 @@ } absl::optional<WebMessagePayload> DecodeToWebMessagePayload( - const TransferableMessage& message) { + TransferableMessage message) { base::BufferIterator<const uint8_t> iter(message.encoded_message); uint8_t tag; @@ -201,10 +256,12 @@ uint32_t num_bytes; if (!ReadUint32(iter, &num_bytes)) return absl::nullopt; - auto span = iter.Span<uint8_t>(num_bytes); - return span.size_bytes() == num_bytes + size_t position = iter.position(); + return position + num_bytes == iter.total_size() ? absl::make_optional( - WebMessagePayload(std::vector(span.begin(), span.end()))) + WebMessagePayload(std::make_unique<VectorArrayBuffer>( + std::move(message.owned_encoded_message), position, + num_bytes))) : absl::nullopt; } case kArrayBufferTransferTag: { @@ -216,10 +273,9 @@ return absl::nullopt; if (message.array_buffer_contents_array.size() != 1) return absl::nullopt; - const auto& big_buffer = message.array_buffer_contents_array[0]->contents; - // Data is from renderer process, copy it first before use. - return std::vector(big_buffer.data(), - big_buffer.data() + big_buffer.size()); + return absl::make_optional( + WebMessagePayload(std::make_unique<BigBufferArrayBuffer>( + std::move(message.array_buffer_contents_array[0]->contents)))); } }
diff --git a/third_party/blink/common/messaging/string_message_codec_unittest.cc b/third_party/blink/common/messaging/string_message_codec_unittest.cc index 2bdc67c2..901e7f19 100644 --- a/third_party/blink/common/messaging/string_message_codec_unittest.cc +++ b/third_party/blink/common/messaging/string_message_codec_unittest.cc
@@ -4,6 +4,10 @@ #include "third_party/blink/public/common/messaging/string_message_codec.h" +#include <string> + +#include "base/containers/span.h" +#include "base/functional/overloaded.h" #include "base/strings/utf_string_conversions.h" #include "base/test/task_environment.h" #include "mojo/public/cpp/base/big_buffer.h" @@ -61,7 +65,8 @@ array_buffer_contents.resize(js_array_buffer->ByteLength()); memcpy(array_buffer_contents.data(), js_array_buffer->Data(), js_array_buffer->ByteLength()); - result = array_buffer_contents; + result = WebMessageArrayBufferPayload::CreateForTesting( + std::move(array_buffer_contents)); } } isolate->Dispose(); @@ -89,31 +94,39 @@ v8::ValueSerializer serializer(isolate); serializer.WriteHeader(); - if (const auto* str = absl::get_if<std::u16string>(&message)) { - v8::Local<v8::String> message_as_value = - v8::String::NewFromTwoByte( - isolate, reinterpret_cast<const uint16_t*>(str->data()), - v8::NewStringType::kNormal, str->size()) - .ToLocalChecked(); - EXPECT_TRUE(serializer.WriteValue(context, message_as_value).ToChecked()); - } else if (const auto* array_buffer = - absl::get_if<std::vector<uint8_t>>(&message)) { - v8::Local<v8::ArrayBuffer> message_as_array_buffer = - v8::ArrayBuffer::New(isolate, array_buffer->size()); - memcpy(message_as_array_buffer->GetBackingStore()->Data(), - array_buffer->data(), array_buffer->size()); - if (transferable) { - serializer.TransferArrayBuffer(0, message_as_array_buffer); - } - EXPECT_TRUE( - serializer.WriteValue(context, message_as_array_buffer).ToChecked()); - - mojo_base::BigBuffer big_buffer(*array_buffer); - transferable_message.array_buffer_contents_array.push_back( - mojom::SerializedArrayBufferContents::New(std::move(big_buffer))); - } else { - NOTREACHED(); - } + absl::visit( + base::Overloaded{ + [&](const std::u16string& str) { + v8::Local<v8::String> message_as_value = + v8::String::NewFromTwoByte( + isolate, reinterpret_cast<const uint16_t*>(str.data()), + v8::NewStringType::kNormal, str.size()) + .ToLocalChecked(); + EXPECT_TRUE( + serializer.WriteValue(context, message_as_value).ToChecked()); + }, + [&](const std::unique_ptr<WebMessageArrayBufferPayload>& + array_buffer) { + // Create a new JS ArrayBuffer, then transfer into serializer. + v8::Local<v8::ArrayBuffer> message_as_array_buffer = + v8::ArrayBuffer::New(isolate, array_buffer->GetLength()); + array_buffer->CopyInto(base::make_span( + reinterpret_cast<uint8_t*>(message_as_array_buffer->Data()), + message_as_array_buffer->ByteLength())); + if (transferable) { + serializer.TransferArrayBuffer(0, message_as_array_buffer); + // Copy data into a new array_buffer_contents_array slot. + mojo_base::BigBuffer big_buffer(array_buffer->GetLength()); + array_buffer->CopyInto(big_buffer); + transferable_message.array_buffer_contents_array.push_back( + mojom::SerializedArrayBufferContents::New( + std::move(big_buffer))); + } + EXPECT_TRUE( + serializer.WriteValue(context, message_as_array_buffer) + .ToChecked()); + }}, + message); std::pair<uint8_t*, size_t> buffer = serializer.Release(); result = std::vector<uint8_t>(buffer.first, buffer.first + buffer.second); @@ -140,11 +153,22 @@ const std::vector<uint8_t>& buffer) { EXPECT_TRUE(optional_payload); auto& payload = optional_payload.value(); - EXPECT_TRUE(absl::holds_alternative<std::vector<uint8_t>>(payload)); - const auto& vec = absl::get<std::vector<uint8_t>>(payload); - EXPECT_EQ(buffer.size(), vec.size()); - for (size_t i = 0; i < buffer.size(); ++i) - EXPECT_EQ(buffer[i], vec[i]); + EXPECT_TRUE( + absl::holds_alternative<std::unique_ptr<WebMessageArrayBufferPayload>>( + payload)); + auto& array_buffer = + absl::get<std::unique_ptr<WebMessageArrayBufferPayload>>(payload); + EXPECT_EQ(buffer.size(), array_buffer->GetLength()); + + auto span = array_buffer->GetAsSpanIfPossible(); + if (span) { + // GetAsSpan is supported, check it is the same as the original buffer. + EXPECT_EQ(std::vector<uint8_t>(span->begin(), span->end()), buffer); + } + + std::vector<uint8_t> temp(array_buffer->GetLength()); + array_buffer->CopyInto(base::make_span(temp)); + EXPECT_EQ(temp, buffer); } TEST(StringMessageCodecTest, SelfTest_ASCII) { @@ -177,8 +201,8 @@ TEST(StringMessageCodecTest, SelfTest_ArrayBuffer) { std::vector<uint8_t> message(200, 0xFF); - CheckVectorEQ(DecodeToWebMessagePayload( - EncodeWebMessagePayload(WebMessagePayload(message))), + CheckVectorEQ(DecodeToWebMessagePayload(EncodeWebMessagePayload( + WebMessageArrayBufferPayload::CreateForTesting(message))), message); } @@ -212,9 +236,9 @@ TEST(StringMessageCodecTest, SelfToV8Test_ArrayBuffer) { std::vector<uint8_t> message(200, 0xFF); - CheckVectorEQ( - DecodeWithV8(EncodeWebMessagePayload(WebMessagePayload(message))), - message); + CheckVectorEQ(DecodeWithV8(EncodeWebMessagePayload( + WebMessageArrayBufferPayload::CreateForTesting(message))), + message); } TEST(StringMessageCodecTest, V8ToSelfTest_ASCII) { @@ -239,13 +263,17 @@ TEST(StringMessageCodecTest, V8ToSelfTest_ArrayBuffer) { std::vector<uint8_t> message(200, 0xFF); - CheckVectorEQ(DecodeToWebMessagePayload(EncodeWithV8(message)), message); + CheckVectorEQ(DecodeToWebMessagePayload(EncodeWithV8( + WebMessageArrayBufferPayload::CreateForTesting(message))), + message); } TEST(StringMessageCodecTest, V8ToSelfTest_ArrayBuffer_transferrable) { std::vector<uint8_t> message(200, 0xFF); - CheckVectorEQ(DecodeToWebMessagePayload(EncodeWithV8(message, true)), - message); + CheckVectorEQ( + DecodeToWebMessagePayload(EncodeWithV8( + WebMessageArrayBufferPayload::CreateForTesting(message), true)), + message); } TransferableMessage TransferableMessageFromRawData(std::vector<uint8_t> data) {
diff --git a/third_party/blink/common/messaging/web_message_port.cc b/third_party/blink/common/messaging/web_message_port.cc index cb6b645..36136d2 100644 --- a/third_party/blink/common/messaging/web_message_port.cc +++ b/third_party/blink/common/messaging/web_message_port.cc
@@ -162,7 +162,7 @@ // TODO(chrisha): Finally kill off MessagePortChannel, once // MessagePortDescriptor more thoroughly plays that role. blink::TransferableMessage transferable_message = - blink::EncodeWebMessagePayload(WebMessagePayload(message.data)); + blink::EncodeWebMessagePayload(std::move(message.data)); transferable_message.ports = blink::MessagePortChannel::CreateFromHandles(std::move(ports)); @@ -235,11 +235,11 @@ std::move(*mojo_message), &transferable_message)) { return false; } - + auto ports = std::move(transferable_message.ports); // Decode the string portion of the message. Message message; absl::optional<WebMessagePayload> optional_payload = - blink::DecodeToWebMessagePayload(transferable_message); + blink::DecodeToWebMessagePayload(std::move(transferable_message)); if (!optional_payload) return false; auto& payload = optional_payload.value(); @@ -251,8 +251,7 @@ // Convert raw handles to MessagePorts. // TODO(chrisha): Kill off MessagePortChannel entirely! - auto handles = - blink::MessagePortChannel::ReleaseHandles(transferable_message.ports); + auto handles = blink::MessagePortChannel::ReleaseHandles(ports); for (auto& handle : handles) { message.ports.emplace_back(WebMessagePort(std::move(handle))); }
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h index 4a28dcf2..4408bfd 100644 --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h
@@ -166,6 +166,9 @@ // Enables to keep prerenderings alive in the background when their visibility // state changes to HIDDEN. BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kPrerender2InBackground); +// Enables to run prerendering for new tabs (e.g., target="_blank"). +// See https://crbug.com/1350676. +BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kPrerender2InNewTab); // Returns true when Prerender2 feature is enabled. BLINK_COMMON_EXPORT bool IsPrerender2Enabled(); // Returns true when the same-site cross origin Prerender2 feature is
diff --git a/third_party/blink/public/common/messaging/string_message_codec.h b/third_party/blink/public/common/messaging/string_message_codec.h index 6e2d1c2..ed438f58e 100644 --- a/third_party/blink/public/common/messaging/string_message_codec.h +++ b/third_party/blink/public/common/messaging/string_message_codec.h
@@ -7,16 +7,44 @@ #include <string> #include <vector> + #include "base/containers/span.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/abseil-cpp/absl/types/variant.h" #include "third_party/blink/public/common/common_export.h" #include "third_party/blink/public/common/messaging/transferable_message.h" namespace blink { +// A interface represents ArrayBuffer payload type in WebMessage. +class BLINK_COMMON_EXPORT WebMessageArrayBufferPayload { + public: + virtual ~WebMessageArrayBufferPayload() = default; + + // Returns the length of the payload. + virtual size_t GetLength() const = 0; + + // Convert the underlying buffer to a span if possible. Or return empty if + // can't (like Java ByteArray). JNI API does not provide a way to get a + // pointer to the underlying array memory, so another API |CopyInto| should be + // used instead to avoid an extra copy. + virtual absl::optional<base::span<const uint8_t>> GetAsSpanIfPossible() + const = 0; + + // Copy the underlying buffer into the given destination. The |dest| must be + // larger than or equal to the payload. This method is always available + // regarding various backing stores. + virtual void CopyInto(base::span<uint8_t> dest) const = 0; + + // Create a new WebMessageArrayBufferPayload from vector for testing. + static std::unique_ptr<WebMessageArrayBufferPayload> CreateForTesting( + std::vector<uint8_t> data); +}; + // Represent WebMessage payload type between browser and renderer process. -// std::vector<uint8_t>: the ArrayBuffer. -using WebMessagePayload = absl::variant<std::u16string, std::vector<uint8_t>>; +using WebMessagePayload = + absl::variant<std::u16string, + std::unique_ptr<WebMessageArrayBufferPayload>>; // To support exposing HTML message ports to Java, it is necessary to be able // to encode and decode message data using the same serialization format as V8. @@ -33,7 +61,7 @@ EncodeWebMessagePayload(const WebMessagePayload& payload); BLINK_COMMON_EXPORT absl::optional<WebMessagePayload> DecodeToWebMessagePayload( - const TransferableMessage& message); + TransferableMessage message); } // namespace blink
diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl index f27b9b0..4268030 100644 --- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl +++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
@@ -1031,6 +1031,8 @@ string instanceId # A list of event-specific information. array of EventMetadata eventMetadata + # Storage key this event belongs to. + string storageKey # Called with all existing backgroundServiceEvents when enabled, and all new # events afterwards if enabled and recording.
diff --git a/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h b/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h index 65528a0..2b615d9 100644 --- a/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h +++ b/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h
@@ -54,16 +54,50 @@ int argument_index, ExceptionState& exception_state); +// Class created for IDLAny types. Converts to either ScriptValue or +// v8::Local<v8::Value>. +class CORE_EXPORT NativeValueTraitsAnyAdapter { + STACK_ALLOCATED(); + + public: + NativeValueTraitsAnyAdapter() = default; + NativeValueTraitsAnyAdapter(const NativeValueTraitsAnyAdapter&) = delete; + NativeValueTraitsAnyAdapter(NativeValueTraitsAnyAdapter&&) = default; + explicit NativeValueTraitsAnyAdapter(v8::Isolate* isolate, + v8::Local<v8::Value> value) + : isolate_(isolate), v8_value_(value) {} + + NativeValueTraitsAnyAdapter& operator=(const NativeValueTraitsAnyAdapter&) = + delete; + NativeValueTraitsAnyAdapter& operator=(NativeValueTraitsAnyAdapter&&) = + default; + NativeValueTraitsAnyAdapter& operator=(const ScriptValue& value) { + isolate_ = value.GetIsolate(); + v8_value_ = value.V8Value(); + return *this; + } + + // NOLINTNEXTLINE(google-explicit-constructor) + operator v8::Local<v8::Value>() const { return v8_value_; } + // NOLINTNEXTLINE(google-explicit-constructor) + operator ScriptValue() const { return ScriptValue(isolate_, v8_value_); } + + private: + v8::Isolate* isolate_ = nullptr; + v8::Local<v8::Value> v8_value_; +}; + } // namespace bindings // any template <> struct CORE_EXPORT NativeValueTraits<IDLAny> : public NativeValueTraitsBase<IDLAny> { - static ScriptValue NativeValue(v8::Isolate* isolate, - v8::Local<v8::Value> value, - ExceptionState& exception_state) { - return ScriptValue(isolate, value); + static bindings::NativeValueTraitsAnyAdapter NativeValue( + v8::Isolate* isolate, + v8::Local<v8::Value> value, + ExceptionState& exception_state) { + return bindings::NativeValueTraitsAnyAdapter(isolate, value); } };
diff --git a/third_party/blink/renderer/bindings/core/v8/script_value.h b/third_party/blink/renderer/bindings/core/v8/script_value.h index 389a307..c15f77fc 100644 --- a/third_party/blink/renderer/bindings/core/v8/script_value.h +++ b/third_party/blink/renderer/bindings/core/v8/script_value.h
@@ -44,6 +44,8 @@ class ScriptState; +// ScriptValue is used when an idl specifies the type as 'any'. ScriptValue +// stores the v8 value using WorldSafeV8Reference. class CORE_EXPORT ScriptValue final { DISALLOW_NEW();
diff --git a/third_party/blink/renderer/bindings/core/v8/to_v8_traits.h b/third_party/blink/renderer/bindings/core/v8/to_v8_traits.h index 8e4bc69b..1eaa81fb 100644 --- a/third_party/blink/renderer/bindings/core/v8/to_v8_traits.h +++ b/third_party/blink/renderer/bindings/core/v8/to_v8_traits.h
@@ -60,6 +60,12 @@ return v8::Undefined(script_state->GetIsolate()); return value; } + + [[nodiscard]] static v8::MaybeLocal<v8::Value> ToV8( + ScriptState* script_state, + const v8::MaybeLocal<v8::Value>& value) { + return value; + } }; // Boolean
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc b/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc index aa12b099..24001ea 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc +++ b/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc
@@ -537,7 +537,8 @@ kValidDataURL = 8, kValidFileURL = 9, kValidBlob = 10, - kValidOtherProtocol = 11, + kValidChromeExtension = 11, + kValidOtherProtocol = 12, kMaxValue = kValidOtherProtocol }; @@ -598,19 +599,10 @@ : protocol == "https" ? WasmStreamingInputType::kValidHttps : protocol == "data" ? WasmStreamingInputType::kValidDataURL : protocol == "file" ? WasmStreamingInputType::kValidFileURL - : protocol == "blob" - ? WasmStreamingInputType::kValidBlob + : protocol == "blob" ? WasmStreamingInputType::kValidBlob + : protocol == "chrome-extension" + ? WasmStreamingInputType::kValidChromeExtension : WasmStreamingInputType::kValidOtherProtocol; - // Temporarily sample 0.1% of the other protocols; remove this once we - // identified missing protocols and added them to the - // "WasmStreamingInputType" enum. - if (protocol_type == WasmStreamingInputType::kValidOtherProtocol && - base::RandInt(0, 999) == 0) { - static crash_reporter::CrashKeyString<16> protocol_key( - "wasm-streaming-protocol"); - protocol_key.Set(protocol.Ascii().c_str()); - base::debug::DumpWithoutCrashing(); - } } base::UmaHistogramEnumeration("V8.WasmStreamingInputType", protocol_type);
diff --git a/third_party/blink/renderer/controller/blink_initializer.cc b/third_party/blink/renderer/controller/blink_initializer.cc index f491c4b4..de18af1 100644 --- a/third_party/blink/renderer/controller/blink_initializer.cc +++ b/third_party/blink/renderer/controller/blink_initializer.cc
@@ -108,13 +108,13 @@ // LiteralBuffer as to what this controls. BASE_FEATURE(kLiteralBufferCreateStringWithEncoding, "LiteralBufferCreateStringWithEncoding", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); // See description of `g_use_html_attribute_name_lookup` in AtomicHTMLToken as // to what this controls. BASE_FEATURE(kUseHtmlAttributeNameLookup, "UseHtmlAttributeNameLookup", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); Thread::TaskObserver* g_end_of_task_runner = nullptr;
diff --git a/third_party/blink/renderer/core/css/resolver/matched_properties_cache.cc b/third_party/blink/renderer/core/css/resolver/matched_properties_cache.cc index b591f1549..1eb2e1b 100644 --- a/third_party/blink/renderer/core/css/resolver/matched_properties_cache.cc +++ b/third_party/blink/renderer/core/css/resolver/matched_properties_cache.cc
@@ -116,7 +116,8 @@ const CachedMatchedProperties* MatchedPropertiesCache::Find( const Key& key, - const StyleResolverState& style_resolver_state) { + const StyleResolverState& style_resolver_state, + const MatchResult& match_result) { DCHECK(key.IsValid()); Cache::iterator it = cache_.find(key.hash_); if (it == cache_.end()) @@ -129,6 +130,11 @@ if (cache_item->computed_style->InsideLink() != style_resolver_state.StyleBuilder().InsideLink()) return nullptr; + if (cache_item->computed_style->CanAffectAnimations() != + (style_resolver_state.CanAffectAnimations() || + match_result.ConditionallyAffectsAnimations())) { + return nullptr; + } if (!cache_item->DependenciesEqual(style_resolver_state)) return nullptr; return cache_item; @@ -250,14 +256,6 @@ return false; } - // Pending animation updates rely on CanAffectAnimations() flag to be set - // during Apply for the StyleCascade in order to store the old computed style - // for multi-pass recalcs for container queries. Alternatively, we could set - // this flag on the cached ComputedStyle and set the flag back onto the - // StyleResolverState when applying an entry from the MatchedPropertiesCache. - if (state.CanAffectAnimations()) - return false; - return true; }
diff --git a/third_party/blink/renderer/core/css/resolver/matched_properties_cache.h b/third_party/blink/renderer/core/css/resolver/matched_properties_cache.h index 08995e76..b843bd4 100644 --- a/third_party/blink/renderer/core/css/resolver/matched_properties_cache.h +++ b/third_party/blink/renderer/core/css/resolver/matched_properties_cache.h
@@ -97,7 +97,9 @@ unsigned hash_; }; - const CachedMatchedProperties* Find(const Key&, const StyleResolverState&); + const CachedMatchedProperties* Find(const Key&, + const StyleResolverState&, + const MatchResult&); void Add(const Key&, scoped_refptr<const ComputedStyle>&&, scoped_refptr<const ComputedStyle>&& parent_style);
diff --git a/third_party/blink/renderer/core/css/resolver/matched_properties_cache_test.cc b/third_party/blink/renderer/core/css/resolver/matched_properties_cache_test.cc index 78b5aac..a3db889 100644 --- a/third_party/blink/renderer/core/css/resolver/matched_properties_cache_test.cc +++ b/third_party/blink/renderer/core/css/resolver/matched_properties_cache_test.cc
@@ -67,11 +67,12 @@ const CachedMatchedProperties* Find(const TestKey& key, const ComputedStyle& style, const ComputedStyle& parent_style) { + MatchResult result; StyleResolverState state(document_, *document_.body(), nullptr /* StyleRecalcContext */, StyleRequest(&parent_style)); state.SetStyle(ComputedStyle::Clone(style)); - return cache_.Find(key.InnerKey(), state); + return cache_.Find(key.InnerKey(), state, result); } private:
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.cc b/third_party/blink/renderer/core/css/resolver/style_resolver.cc index 6043173..15dbefde 100644 --- a/third_party/blink/renderer/core/css/resolver/style_resolver.cc +++ b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
@@ -1853,12 +1853,22 @@ bool is_inherited_cache_hit = false; bool is_non_inherited_cache_hit = false; const CachedMatchedProperties* cached_matched_properties = - key.IsValid() ? matched_properties_cache_.Find(key, state) : nullptr; + key.IsValid() ? matched_properties_cache_.Find(key, state, match_result) + : nullptr; AtomicString pseudo_argument = state.StyleBuilder().PseudoArgument(); if (cached_matched_properties && MatchedPropertiesCache::IsCacheable(state)) { INCREMENT_STYLE_STATS_COUNTER(GetDocument().GetStyleEngine(), matched_property_cache_hit, 1); + + if (cached_matched_properties->computed_style->CanAffectAnimations()) { + // Need to set this flag from the cached ComputedStyle to make + // ShouldStoreOldStyle() correctly return true. We do not collect matching + // rules when the cache is hit, and the flag is set as part of that + // process for the full style resolution. + state.SetCanAffectAnimations(); + } + // We can build up the style by copying non-inherited properties from an // earlier style object built using the same exact style declarations. We // then only need to apply the inherited properties, if any, as their values @@ -2130,9 +2140,12 @@ UseCountLegacyOverlapping(GetDocument(), *non_legacy_style, *state.Style()); } - // NOTE: This flag needs to be set before the entry is added to the - // matched properties cache, or it will be wrong on cache hits. + // NOTE: These flags need to be set before the entry is added to the matched + // properties cache, or it will be wrong on cache hits. state.StyleBuilder().SetInlineStyleLostCascade(cascade.InlineStyleLost()); + if (state.CanAffectAnimations() || result.ConditionallyAffectsAnimations()) { + state.StyleBuilder().SetCanAffectAnimations(); + } MaybeAddToMatchedPropertiesCache(state, cache_success, result);
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc b/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc index 56d8c9ea..0484318 100644 --- a/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc +++ b/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc
@@ -3113,4 +3113,32 @@ max_height->ComputedStyleRef().MaxHeight())); } +TEST_F(StyleResolverTestCQ, CanAffectAnimationsMPC) { + GetDocument().documentElement()->setInnerHTML(R"HTML( + <style> + #a { transition: color 1s; } + @container (width > 100000px) { + #b { animation-name: anim; } + } + </style> + <div id=a></div> + <div id=b></div> + <div id=c></div> + )HTML"); + + UpdateAllLifecyclePhasesForTest(); + + auto* a = GetDocument().getElementById("a"); + auto* b = GetDocument().getElementById("b"); + auto* c = GetDocument().getElementById("c"); + + ASSERT_TRUE(a); + ASSERT_TRUE(b); + ASSERT_TRUE(c); + + EXPECT_TRUE(a->ComputedStyleRef().CanAffectAnimations()); + EXPECT_TRUE(b->ComputedStyleRef().CanAffectAnimations()); + EXPECT_FALSE(c->ComputedStyleRef().CanAffectAnimations()); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/dom/events/event_dispatcher.cc b/third_party/blink/renderer/core/dom/events/event_dispatcher.cc index 0d5e7b9..f68d422 100644 --- a/third_party/blink/renderer/core/dom/events/event_dispatcher.cc +++ b/third_party/blink/renderer/core/dom/events/event_dispatcher.cc
@@ -265,6 +265,9 @@ pre_dispatch_event_handler_result); auto result = EventTarget::GetDispatchEventResult(*event_); + if (soft_navigation_scope) { + soft_navigation_scope->SetResult(result); + } return result; }
diff --git a/third_party/blink/renderer/core/editing/compare_positions.cc b/third_party/blink/renderer/core/editing/compare_positions.cc index a060ff4..e9f3677 100644 --- a/third_party/blink/renderer/core/editing/compare_positions.cc +++ b/third_party/blink/renderer/core/editing/compare_positions.cc
@@ -375,11 +375,9 @@ // |------------------+---------------------------------+----------------| // ``` // - // The maximum number of iterations is `number_of_children / 4`. - // - // The minimum number of iterations is: ``` + // The number of iterations is: ``` // std::min(offset_a, offset_b, - // abs(offset_a - offset_b), + // abs(offset_a - offset_b) / 2, // number_of_children - offset_a, // number_of_children - offset_b) // where @@ -387,6 +385,8 @@ // `offset_b` == `Traversal::Index(*child_b)` // // ``` + // Note: this number can't exceed `number_of_children / 4`. + // // Note: We call this function both "node before position" and "node after // position" cases. For "node after position" case, `child_a` and `child_b` // should not be `nullptr`. @@ -407,16 +407,29 @@ const Node* forward_b = child_b; for (;;) { - if (!backward_a || !forward_b) + backward_a = Traversal::PreviousSibling(*backward_a); + if (!backward_a) return kAIsBeforeB; - if (!forward_a || !backward_b || backward_a == forward_b) + if (backward_a == forward_b) + return kAIsAfterB; + + forward_a = Traversal::NextSibling(*forward_a); + if (!forward_a) return kAIsAfterB; if (forward_a == backward_b) return kAIsBeforeB; - backward_a = Traversal::PreviousSibling(*backward_a); - forward_a = Traversal::NextSibling(*forward_a); + backward_b = Traversal::PreviousSibling(*backward_b); + if (!backward_b) + return kAIsAfterB; + if (forward_a == backward_b) + return kAIsBeforeB; + forward_b = Traversal::NextSibling(*forward_b); + if (!forward_b) + return kAIsBeforeB; + if (backward_a == forward_b) + return kAIsAfterB; } NOTREACHED(); @@ -429,9 +442,11 @@ static const Node* FindChildInAncestors(const Node& node, const Node& parent) { DCHECK_NE(node, parent); - for (const Node& child : Traversal::InclusiveAncestorsOf(node)) { - if (Traversal::Parent(child) == parent) - return &child; + const Node* candidate = &node; + for (const Node& child : Traversal::AncestorsOf(node)) { + if (child == parent) + return candidate; + candidate = &child; } return nullptr; }
diff --git a/third_party/blink/renderer/core/editing/position_iterator.cc b/third_party/blink/renderer/core/editing/position_iterator.cc index 2c3fc2ea..ef3fbd47 100644 --- a/third_party/blink/renderer/core/editing/position_iterator.cc +++ b/third_party/blink/renderer/core/editing/position_iterator.cc
@@ -729,11 +729,7 @@ template <typename Strategy> void FastPositionIteratorAlgorithm<Strategy>::MoveToPreviousContainer() { PopOffsetStack(); - child_before_position_ = Strategy::PreviousSibling(*container_node_); - if (!child_before_position_) { - DCHECK(offset_in_container_ == kInvalidOffset || !offset_in_container_); - offset_in_container_ = 0; - } + SetChildBeforePositionToPreviosuSigblingOf(*container_node_); SetContainer(SelectableParentOf<Strategy>(*container_node_)); } @@ -741,15 +737,23 @@ void FastPositionIteratorAlgorithm<Strategy>::MoveToPreviousSkippingChildren() { if (!child_before_position_) { PopOffsetStack(); - child_before_position_ = Strategy::PreviousSibling(*container_node_); + SetChildBeforePositionToPreviosuSigblingOf(*container_node_); return SetContainer(SelectableParentOf<Strategy>(*container_node_)); } MoveOffsetInContainerBy(-1); - child_before_position_ = Strategy::PreviousSibling(*child_before_position_); - if (!child_before_position_) { - DCHECK(offset_in_container_ == kInvalidOffset || !offset_in_container_); - offset_in_container_ = 0; + SetChildBeforePositionToPreviosuSigblingOf(*child_before_position_); +} + +template <typename Strategy> +void FastPositionIteratorAlgorithm< + Strategy>::SetChildBeforePositionToPreviosuSigblingOf(const Node& node) { + child_before_position_ = Strategy::PreviousSibling(node); + if (child_before_position_) { + DCHECK(offset_in_container_); + return; } + DCHECK(offset_in_container_ == kInvalidOffset || !offset_in_container_); + offset_in_container_ = 0; } template <typename Strategy>
diff --git a/third_party/blink/renderer/core/editing/position_iterator.h b/third_party/blink/renderer/core/editing/position_iterator.h index dc9371a1..19aef55 100644 --- a/third_party/blink/renderer/core/editing/position_iterator.h +++ b/third_party/blink/renderer/core/editing/position_iterator.h
@@ -172,6 +172,12 @@ void MoveToPreviousContainer(); void MoveToPreviousSkippingChildren(); + // Set `child_before_position_` to `Strategy::PreviousChildren(node)` + // and set `offset_` to zero if `child_before_position_` becomes + // `nullptr`. + void SetChildBeforePositionToPreviosuSigblingOf(const Node& node); + + // Set `container_node_` to `node` and `container_type` from `node. void SetContainer(Node* node); // Returns `PositionType::AfterNode(*container_node_)` if @@ -188,6 +194,8 @@ Node* container_node_ = nullptr; Node* child_before_position_ = nullptr; uint64_t dom_tree_version_ = 0; + // Note: When `child_before_position_` is `nullptr`, `offset_is_container` + // should be zero. mutable unsigned offset_in_container_ = kInvalidOffset; Vector<unsigned> offset_stack_;
diff --git a/third_party/blink/renderer/core/editing/position_iterator_test.cc b/third_party/blink/renderer/core/editing/position_iterator_test.cc index 79c6191..9efc808 100644 --- a/third_party/blink/renderer/core/editing/position_iterator_test.cc +++ b/third_party/blink/renderer/core/editing/position_iterator_test.cc
@@ -666,6 +666,21 @@ "-S-- HTML HTML@offsetInAnchor[0]")); } +// http://crbug.com/1392758 +TEST_F(PositionIteratorTest, DecrementWithTextAreaFromAfterChildren) { + SetBodyContent("<textarea>abc</textarea>"); + const Element& body = *GetDocument().body(); + const auto expectation = ElementsAre( + "---E BODY BODY@afterChildren", "---E TEXTAREA@1 TEXTAREA@afterAnchor", + "-S-E TEXTAREA@0 TEXTAREA@beforeAnchor TEXTAREA@afterAnchor", + "-S-- BODY BODY@offsetInAnchor[0]", "---- HTML HTML@offsetInAnchor[1]", + "-S-E HEAD HEAD@beforeAnchor HEAD@offsetInAnchor[0]", + "-S-- HTML HTML@offsetInAnchor[0]"); + + EXPECT_THAT(ScanBackward(Position(body, 1)), expectation); + EXPECT_THAT(ScanBackward(Position::LastPositionInNode(body)), expectation); +} + // --- TEST_F(PositionIteratorTest, IncrementFromInputElementAfterChildren) {
diff --git a/third_party/blink/renderer/core/style/computed_style_extra_fields.json5 b/third_party/blink/renderer/core/style/computed_style_extra_fields.json5 index a1b87a66..2650c1c 100644 --- a/third_party/blink/renderer/core/style/computed_style_extra_fields.json5 +++ b/third_party/blink/renderer/core/style/computed_style_extra_fields.json5
@@ -1178,6 +1178,17 @@ type_name: "bool", field_group: "*", default_value: "false", - } + }, + { + // Need to persist this flag from MatchResult and set it back on + // StyleResolverState when we hit the MatchedPropertiesCache. Otherwise + // ShouldStoreOldStyle() in StyleResolver will not return the correct + // result. + name: "CanAffectAnimations", + field_template: "monotonic_flag", + type_name: "bool", + field_group: "*", + default_value: "false", + }, ], }
diff --git a/third_party/blink/renderer/core/timing/soft_navigation_heuristics.h b/third_party/blink/renderer/core/timing/soft_navigation_heuristics.h index b8083df..32db599 100644 --- a/third_party/blink/renderer/core/timing/soft_navigation_heuristics.h +++ b/third_party/blink/renderer/core/timing/soft_navigation_heuristics.h
@@ -87,10 +87,13 @@ heuristics->UserInitiatedClick(script_state); } ~SoftNavigationEventScope() { heuristics_->ClickEventEnded(script_state_); } + // TODO(yoav): Remove this method, as it's not doing anything useful. + void SetResult(DispatchEventResult result) { result_ = result; } private: Persistent<SoftNavigationHeuristics> heuristics_; Persistent<ScriptState> script_state_; + DispatchEventResult result_; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc index 3216b63..6fe3e03 100644 --- a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc +++ b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc
@@ -2048,9 +2048,12 @@ // In Desynchronized canvas disabling the acceleration will break // putImageData: crbug.com/1112060. if (IsAccelerated() && !IsDesynchronized()) { - DisableAcceleration(); - base::UmaHistogramEnumeration("Blink.Canvas.GPUFallbackToCPU", - GPUFallbackToCPUScenario::kGetImageData); + read_count_++; + if (read_count_ >= kFallbackToCPUAfterReadbacks) { + DisableAcceleration(); + base::UmaHistogramEnumeration("Blink.Canvas.GPUFallbackToCPU", + GPUFallbackToCPUScenario::kGetImageData); + } } }
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.h b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.h index 90abd6bf..fc049743 100644 --- a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.h +++ b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.h
@@ -35,6 +35,8 @@ class MODULES_EXPORT BaseRenderingContext2D : public CanvasPath { public: + static constexpr unsigned kFallbackToCPUAfterReadbacks = 2; + BaseRenderingContext2D(const BaseRenderingContext2D&) = delete; BaseRenderingContext2D& operator=(const BaseRenderingContext2D&) = delete; @@ -644,6 +646,7 @@ bool origin_tainted_by_content_; UsePaintCache path2d_use_paint_cache_; int num_readbacks_performed_ = 0; + unsigned read_count_ = 0; }; ALWAYS_INLINE void BaseRenderingContext2D::CheckOverdraw(
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc index 3d109fd7..e808503e 100644 --- a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc +++ b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc
@@ -1285,7 +1285,10 @@ DrawSomething(); NonThrowableExceptionState exception_state; ImageDataSettings* settings = ImageDataSettings::Create(); - Context2D()->getImageData(0, 0, 1, 1, settings, exception_state); + int read_count = BaseRenderingContext2D::kFallbackToCPUAfterReadbacks; + while (read_count--) { + Context2D()->getImageData(0, 0, 1, 1, settings, exception_state); + } EXPECT_FALSE(CanvasElement().GetCanvas2DLayerBridge()->IsAccelerated()); }
diff --git a/third_party/blink/renderer/modules/webaudio/audio_param_handler.cc b/third_party/blink/renderer/modules/webaudio/audio_param_handler.cc index 8464c56..68f96194 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_param_handler.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_param_handler.cc
@@ -26,9 +26,6 @@ namespace { -constexpr double kDefaultSmoothingConstant = 0.05; -constexpr double kSnapThreshold = 0.001; - // Replace NaN values in `values` with `default_value`. void HandleNaNValues(float* values, unsigned number_of_values, @@ -103,8 +100,6 @@ if (context.destination()) { destination_handler_ = &context.destination()->GetAudioDestinationHandler(); } - - timeline_.SetSmoothedValue(default_value); } AudioDestinationHandler& AudioParamHandler::DestinationHandler() const { @@ -220,43 +215,6 @@ SetIntrinsicValue(value); } -float AudioParamHandler::SmoothedValue() { - return timeline_.SmoothedValue(); -} - -bool AudioParamHandler::Smooth() { - // If values have been explicitly scheduled on the timeline, then use the - // exact value. Smoothing effectively is performed by the timeline. - auto [use_timeline_value, value] = timeline_.ValueForContextTime( - DestinationHandler(), IntrinsicValue(), MinValue(), MaxValue(), - GetDeferredTaskHandler().RenderQuantumFrames()); - - float smoothed_value = timeline_.SmoothedValue(); - if (smoothed_value == value) { - // Smoothed value has already approached and snapped to value. - SetIntrinsicValue(value); - return true; - } - - if (use_timeline_value) { - timeline_.SetSmoothedValue(value); - } else { - // Dezipper - exponential approach. - smoothed_value += (value - smoothed_value) * kDefaultSmoothingConstant; - - // If we get close enough then snap to actual value. - // FIXME: the threshold needs to be adjustable depending on range - but - // this is OK general purpose value. - if (fabs(smoothed_value - value) < kSnapThreshold) { - smoothed_value = value; - } - timeline_.SetSmoothedValue(smoothed_value); - } - - SetIntrinsicValue(value); - return false; -} - float AudioParamHandler::FinalValue() { float value = IntrinsicValue(); CalculateFinalValues(&value, 1, false);
diff --git a/third_party/blink/renderer/modules/webaudio/audio_param_handler.h b/third_party/blink/renderer/modules/webaudio/audio_param_handler.h index 9258b65..6343c486 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_param_handler.h +++ b/third_party/blink/renderer/modules/webaudio/audio_param_handler.h
@@ -141,19 +141,6 @@ float MinValue() const { return min_value_; } float MaxValue() const { return max_value_; } - // Value smoothing: - - // When a new value is set with setValue(), in our internal use of the - // parameter we don't immediately jump to it. Instead we smoothly approach - // this value to avoid glitching. - float SmoothedValue(); - - // Smoothly exponentially approaches to (de-zippers) the desired value. - // Returns true if smoothed value has already snapped exactly to value. - bool Smooth(); - - void ResetSmoothedValue() { timeline_.SetSmoothedValue(IntrinsicValue()); } - // An AudioParam needs sample accurate processing if there are // automations scheduled or if there are connections. bool HasSampleAccurateValues() {
diff --git a/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc b/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc index 6d0a9e9..c692ceb 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc
@@ -1347,7 +1347,6 @@ // timeline events too because `default_value` has the expected // value. FillWithDefault(values, default_value, number_of_values, 0); - smoothed_value_ = default_value; RemoveOldEvents(events_.size()); return true;
diff --git a/third_party/blink/renderer/modules/webaudio/audio_param_timeline.h b/third_party/blink/renderer/modules/webaudio/audio_param_timeline.h index 770738010..7031f32 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_param_timeline.h +++ b/third_party/blink/renderer/modules/webaudio/audio_param_timeline.h
@@ -107,9 +107,6 @@ double sample_rate, unsigned render_quantum_frames) const; - float SmoothedValue() { return smoothed_value_; } - void SetSmoothedValue(float v) { smoothed_value_ = v; } - private: class ParamEvent { public: @@ -485,9 +482,6 @@ HashSet<ParamEvent*> new_events_ GUARDED_BY(events_lock_); mutable base::Lock events_lock_; - - // Smoothing (de-zippering) - float smoothed_value_; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/webaudio/biquad_dsp_kernel.h b/third_party/blink/renderer/modules/webaudio/biquad_dsp_kernel.h index 139898c1..f52bf72 100644 --- a/third_party/blink/renderer/modules/webaudio/biquad_dsp_kernel.h +++ b/third_party/blink/renderer/modules/webaudio/biquad_dsp_kernel.h
@@ -76,8 +76,6 @@ return static_cast<BiquadProcessor*>(Processor()); } - // To prevent audio glitches when parameters are changed, - // dezippering is used to slowly change the parameters. void UpdateCoefficientsIfNecessary(int) EXCLUSIVE_LOCKS_REQUIRED(process_lock_);
diff --git a/third_party/blink/renderer/modules/webaudio/biquad_processor.cc b/third_party/blink/renderer/modules/webaudio/biquad_processor.cc index 2fc8252..2afb6a9 100644 --- a/third_party/blink/renderer/modules/webaudio/biquad_processor.cc +++ b/third_party/blink/renderer/modules/webaudio/biquad_processor.cc
@@ -81,38 +81,38 @@ parameter3_->IsAudioRate() || parameter4_->IsAudioRate(); } else { if (has_just_reset_) { - // Snap to exact values first time after reset, then smooth for subsequent - // changes. - parameter1_->ResetSmoothedValue(); - parameter2_->ResetSmoothedValue(); - parameter3_->ResetSmoothedValue(); - parameter4_->ResetSmoothedValue(); + // Snap to exact values first time after reset + previous_parameter1_ = std::numeric_limits<float>::quiet_NaN(); + previous_parameter2_ = std::numeric_limits<float>::quiet_NaN(); + previous_parameter3_ = std::numeric_limits<float>::quiet_NaN(); + previous_parameter4_ = std::numeric_limits<float>::quiet_NaN(); filter_coefficients_dirty_ = true; has_just_reset_ = false; } else { - // TODO(crbug.com/763994): With dezippering removed, we don't want to use - // these methods. We need to implement another way of noticing if one of - // the parameters has changed. We do this as an optimization because - // computing the filter coefficients from these parameters is fairly - // expensive. NOTE: The calls to Smooth() don't actually cause the - // coefficients to be dezippered. This is just a way to notice that the - // coefficient values have changed. `UpdateCoefficientsIfNecessary()` - // checks to see if the filter coefficients are dirty and sets the filter - // to the new value, without smoothing. - // - // Smooth all of the filter parameters. If they haven't yet converged to - // their target value then mark coefficients as dirty. - bool is_stable1 = parameter1_->Smooth(); - bool is_stable2 = parameter2_->Smooth(); - bool is_stable3 = parameter3_->Smooth(); - bool is_stable4 = parameter4_->Smooth(); - if (!(is_stable1 && is_stable2 && is_stable3 && is_stable4)) { + // If filter parameters have changed then mark coefficients as dirty. + const float parameter1_final = parameter1_->FinalValue(); + const float parameter2_final = parameter2_->FinalValue(); + const float parameter3_final = parameter3_->FinalValue(); + const float parameter4_final = parameter4_->FinalValue(); + if ((previous_parameter1_ != parameter1_final) || + (previous_parameter2_ != parameter2_final) || + (previous_parameter3_ != parameter3_final) || + (previous_parameter4_ != parameter4_final)) { filter_coefficients_dirty_ = true; + previous_parameter1_ = parameter1_final; + previous_parameter2_ = parameter2_final; + previous_parameter3_ = parameter3_final; + previous_parameter4_ = parameter4_final; } } } } +void BiquadProcessor::Initialize() { + AudioDSPKernelProcessor::Initialize(); + has_just_reset_ = true; +} + void BiquadProcessor::Process(const AudioBus* source, AudioBus* destination, uint32_t frames_to_process) { @@ -151,6 +151,11 @@ parameter4_->CalculateSampleAccurateValues(values, frames_to_process); } +void BiquadProcessor::Reset() { + AudioDSPKernelProcessor::Reset(); + has_just_reset_ = true; +} + void BiquadProcessor::SetType(FilterType type) { if (type != type_) { type_ = type;
diff --git a/third_party/blink/renderer/modules/webaudio/biquad_processor.h b/third_party/blink/renderer/modules/webaudio/biquad_processor.h index 967c43bd..428ab00 100644 --- a/third_party/blink/renderer/modules/webaudio/biquad_processor.h +++ b/third_party/blink/renderer/modules/webaudio/biquad_processor.h
@@ -67,11 +67,12 @@ std::unique_ptr<AudioDSPKernel> CreateKernel() override; + void Initialize() override; void Process(const AudioBus* source, AudioBus* destination, uint32_t frames_to_process) override; - void ProcessOnlyAudioParams(uint32_t frames_to_process) override; + void Reset() override; // Get the magnitude and phase response of the filter at the given // set of frequencies (in Hz). The phase response is in radians. @@ -110,6 +111,15 @@ // Set to true if any of the filter parameters are a-rate. bool is_audio_rate_; + + bool has_just_reset_ = true; + + // Cache previous parameter values to allow us to skip recomputing filter + // coefficients when parameters are not changing + float previous_parameter1_ = std::numeric_limits<float>::quiet_NaN(); + float previous_parameter2_ = std::numeric_limits<float>::quiet_NaN(); + float previous_parameter3_ = std::numeric_limits<float>::quiet_NaN(); + float previous_parameter4_ = std::numeric_limits<float>::quiet_NaN(); }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/webaudio/oscillator_handler.cc b/third_party/blink/renderer/modules/webaudio/oscillator_handler.cc index 0366bac..c8e12f5 100644 --- a/third_party/blink/renderer/modules/webaudio/oscillator_handler.cc +++ b/third_party/blink/renderer/modules/webaudio/oscillator_handler.cc
@@ -276,8 +276,6 @@ if (first_render_) { first_render_ = false; - frequency_->ResetSmoothedValue(); - detune_->ResetSmoothedValue(); } bool has_sample_accurate_values = false;
diff --git a/third_party/blink/renderer/modules/webcodecs/video_decoder_broker.cc b/third_party/blink/renderer/modules/webcodecs/video_decoder_broker.cc index 1de0475..3e74052 100644 --- a/third_party/blink/renderer/modules/webcodecs/video_decoder_broker.cc +++ b/third_party/blink/renderer/modules/webcodecs/video_decoder_broker.cc
@@ -113,7 +113,7 @@ #if BUILDFLAG(IS_FUCHSIA) execution_context.GetBrowserInterfaceBroker().GetInterface( - fuchsia_media_resource_provider_.InitWithNewPipeAndPassReceiver()); + fuchsia_media_codec_provider_.InitWithNewPipeAndPassReceiver()); #endif // TODO(sandersd): Target color space is used by DXVA VDA to pick an @@ -212,9 +212,9 @@ external_decoder_factory = std::make_unique<media::MojoDecoderFactory>( media_interface_factory_.get()); #elif BUILDFLAG(IS_FUCHSIA) - DCHECK(fuchsia_media_resource_provider_); + DCHECK(fuchsia_media_codec_provider_); external_decoder_factory = std::make_unique<media::FuchsiaDecoderFactory>( - std::move(fuchsia_media_resource_provider_), + std::move(fuchsia_media_codec_provider_), /*allow_overlays=*/false); #endif } @@ -332,8 +332,8 @@ bool decoder_factory_needs_update_ = true; #if BUILDFLAG(IS_FUCHSIA) - mojo::PendingRemote<media::mojom::FuchsiaMediaResourceProvider> - fuchsia_media_resource_provider_; + mojo::PendingRemote<media::mojom::FuchsiaMediaCodecProvider> + fuchsia_media_codec_provider_; #endif std::unique_ptr<media::MediaLog> media_log_;
diff --git a/third_party/blink/renderer/platform/audio/audio_dsp_kernel_processor.cc b/third_party/blink/renderer/platform/audio/audio_dsp_kernel_processor.cc index 65d698ec2..0b3fd5d7 100644 --- a/third_party/blink/renderer/platform/audio/audio_dsp_kernel_processor.cc +++ b/third_party/blink/renderer/platform/audio/audio_dsp_kernel_processor.cc
@@ -39,8 +39,7 @@ AudioDSPKernelProcessor::AudioDSPKernelProcessor(float sample_rate, unsigned number_of_channels, unsigned render_quantum_frames) - : AudioProcessor(sample_rate, number_of_channels, render_quantum_frames), - has_just_reset_(true) {} + : AudioProcessor(sample_rate, number_of_channels, render_quantum_frames) {} void AudioDSPKernelProcessor::Initialize() { if (IsInitialized()) { @@ -56,7 +55,6 @@ } initialized_ = true; - has_just_reset_ = true; } void AudioDSPKernelProcessor::Uninitialize() { @@ -122,11 +120,6 @@ return; } - // Forces snap to parameter values - first time. - // Any processing depending on this value must set it to false at the - // appropriate time. - has_just_reset_ = true; - base::AutoLock locker(process_lock_); for (auto& kernel : kernels_) { kernel->Reset();
diff --git a/third_party/blink/renderer/platform/audio/audio_dsp_kernel_processor.h b/third_party/blink/renderer/platform/audio/audio_dsp_kernel_processor.h index b35f23c3..49602943 100644 --- a/third_party/blink/renderer/platform/audio/audio_dsp_kernel_processor.h +++ b/third_party/blink/renderer/platform/audio/audio_dsp_kernel_processor.h
@@ -81,7 +81,6 @@ protected: Vector<std::unique_ptr<AudioDSPKernel>> kernels_; mutable base::Lock process_lock_; - bool has_just_reset_; }; } // namespace blink
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 996f5cd8..a137662 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -602,6 +602,11 @@ name: "CorsRFC1918", }, { + name: "CrossFramePerformanceTimeline", + status: "test", + base_feature: "CrossFramePerformanceTimeline", + }, + { // Allows positioning a positioned element relative to another one. // https://drafts.csswg.org/css-anchor-1/ name: "CSSAnchorPositioning",
diff --git a/third_party/blink/renderer/platform/wtf/wtf.cc b/third_party/blink/renderer/platform/wtf/wtf.cc index 25b22fbe..dea9f68 100644 --- a/third_party/blink/renderer/platform/wtf/wtf.cc +++ b/third_party/blink/renderer/platform/wtf/wtf.cc
@@ -56,7 +56,7 @@ #if !BUILDFLAG(IS_MAC) && defined(ARCH_CPU_X86_FAMILY) BASE_FEATURE(kEnableSsePathForCopyLCharsX86, "EnableSsePathForCopyLCharsX86", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); #endif #if BUILDFLAG(IS_ANDROID)
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 26a93d1..3409d24 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -3022,6 +3022,17 @@ crbug.com/626703 [ Win ] virtual/partitioned-cookies/http/tests/inspector-protocol/network/disabled-cache-navigation.js [ Failure ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 external/wpt/css/css-writing-modes/forms/range-input-appearance-native-horizontal.optional.html [ Failure ] +crbug.com/626703 external/wpt/css/css-writing-modes/forms/range-input-appearance-native-vertical.optional.html [ Failure ] +crbug.com/626703 external/wpt/css/css-writing-modes/forms/range-input-appearance-none-horizontal.optional.html [ Failure ] +crbug.com/626703 external/wpt/css/css-writing-modes/forms/range-input-appearance-none-vertical.optional.html [ Failure ] +crbug.com/626703 external/wpt/css/css-writing-modes/forms/select-multiple-appearance-native-horizontal.optional.html [ Failure ] +crbug.com/626703 external/wpt/css/css-writing-modes/forms/select-multiple-appearance-native-vlr.optional.html [ Failure ] +crbug.com/626703 external/wpt/css/css-writing-modes/forms/select-multiple-appearance-native-vrl.optional.html [ Failure ] +crbug.com/626703 external/wpt/css/css-writing-modes/forms/select-multiple-appearance-none-horizontal.optional.html [ Failure ] +crbug.com/626703 external/wpt/css/css-writing-modes/forms/select-multiple-appearance-none-vlr.optional.html [ Failure ] +crbug.com/626703 external/wpt/css/css-writing-modes/forms/select-multiple-appearance-none-vrl.optional.html [ Failure ] +crbug.com/626703 [ Mac11-arm64 ] external/wpt/html/semantics/forms/the-selectmenu-element/selectmenu-form-state-restore.tentative.html [ Timeout ] crbug.com/626703 [ Mac11 ] external/wpt/credential-management/fedcm-network-requests.https.html [ Timeout ] crbug.com/626703 external/wpt/css/css-writing-modes/forms/textarea-appearance-native-horizontal.optional.html [ Failure ] crbug.com/626703 external/wpt/css/css-writing-modes/forms/textarea-appearance-native-vlr.optional.html [ Failure ] @@ -3029,7 +3040,7 @@ crbug.com/626703 external/wpt/css/css-writing-modes/forms/textarea-appearance-none-horizontal.optional.html [ Failure ] crbug.com/626703 external/wpt/css/css-writing-modes/forms/textarea-appearance-none-vlr.optional.html [ Failure ] crbug.com/626703 external/wpt/css/css-writing-modes/forms/textarea-appearance-none-vrl.optional.html [ Failure ] -crbug.com/626703 [ Win11 ] external/wpt/screen-orientation/hidden_document.html [ Timeout Failure ] +crbug.com/626703 [ Win11 ] external/wpt/screen-orientation/hidden_document.html [ Failure Timeout ] crbug.com/626703 external/wpt/css/css-writing-modes/forms/color-input-appearance-native-horizontal.optional.html [ Failure ] crbug.com/626703 external/wpt/css/css-writing-modes/forms/color-input-appearance-native-vertical.optional.html [ Failure ] crbug.com/626703 external/wpt/css/css-writing-modes/forms/color-input-appearance-none-horizontal.optional.html [ Failure ] @@ -3447,7 +3458,6 @@ crbug.com/990240 external/wpt/css/css-multicol/multicol-breaking-nobackground-000.html [ Failure ] crbug.com/990240 external/wpt/css/css-multicol/multicol-breaking-nobackground-001.html [ Failure ] crbug.com/481431 external/wpt/css/css-multicol/multicol-breaking-nobackground-004.html [ Failure ] -crbug.com/829028 [ Mac ] external/wpt/css/css-multicol/multicol-list-item-005.html [ Failure ] crbug.com/792435 external/wpt/css/css-multicol/multicol-rule-004.xht [ Failure ] crbug.com/792437 external/wpt/css/css-multicol/multicol-rule-inset-000.xht [ Failure ] crbug.com/990240 external/wpt/css/css-multicol/multicol-rule-nested-balancing-001.html [ Failure ] @@ -5844,17 +5854,6 @@ crbug.com/1298836 external/wpt/fetch/api/basic/response-null-body.any.* [ Failure Pass ] crbug.com/1298836 virtual/plz-dedicated-worker/external/wpt/fetch/api/basic/response-null-body.any.* [ Failure Pass ] -# Iframe credentialless: -#------------------ -# -# Iframe credentialless > CacheStorage: -# From two same-origin-different-partition context, the second `cache.put` -# request hangs indefinitely. -# TODO(arthursonzogni): Remove those, because this has been fixed already. -crbug.com/1285275 external/wpt/html/anonymous-iframe/cache-storage.tentative.https.window.html [ Pass Timeout ] -crbug.com/1285275 virtual/fenced-frame-mparch/external/wpt/html/anonymous-iframe/cache-storage.tentative.https.window.html [ Pass Timeout ] -crbug.com/1285275 virtual/partitioned-cookies/external/wpt/html/anonymous-iframe/cache-storage.tentative.https.window.html [ Pass Timeout ] - # Sheriff 2022-03-10 crbug.com/1304956 storage/indexeddb/dont-wedge.html [ Failure Pass ] @@ -6910,9 +6909,15 @@ crbug.com/1392077 external/wpt/screen-orientation/orientation-reading.html [ Failure Timeout ] # Sheriff 2022-11-23 -crbug.com/1393013 [ Win11 ] http/tests/persistent-origin-trials/critical-origin-trial.https.php [ Pass Failure ] -crbug.com/1393013 [ Win11 ] http/tests/persistent-origin-trials/window-origin-trial.https.php [ Pass Failure ] -crbug.com/1393067 [ Mac ] virtual/gpu-rasterization/images/182.html [ Pass Failure ] -crbug.com/1393067 [ Mac ] virtual/gpu-rasterization/images/23-55.html [ Pass Failure ] -crbug.com/1393067 [ Mac ] virtual/gpu-rasterization/images/55.html [ Pass Failure ] -crbug.com/1393056 [ Mac ] inspector-protocol/debugger/debugger-evaluate-in-worker-while-pause-in-page.js [ Pass Timeout ] +crbug.com/1393013 [ Win11 ] http/tests/persistent-origin-trials/critical-origin-trial.https.php [ Failure Pass ] +crbug.com/1393013 [ Win11 ] http/tests/persistent-origin-trials/window-origin-trial.https.php [ Failure Pass ] +crbug.com/1393067 [ Mac ] virtual/gpu-rasterization/images/182.html [ Failure Pass ] +crbug.com/1393067 [ Mac ] virtual/gpu-rasterization/images/23-55.html [ Failure Pass ] +crbug.com/1393067 [ Mac ] virtual/gpu-rasterization/images/55.html [ Failure Pass ] +crbug.com/1393056 [ Mac ] inspector-protocol/debugger/debugger-evaluate-in-worker-while-pause-in-page.js [ Failure Pass Timeout ] + +# Temporarily disable test to land BackgroundServices frontend CL +crbug.com/1382392 http/tests/devtools/background-services/background-service-grid.js [ Failure Skip ] + +# Temporarily disable test to land CPU-backed canvas switching change +crbug.com/1385633 [ Linux ] virtual/oopr-canvas2d/fast/canvas/check-stale-putImageData.html [ Failure ]
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json index 17bb93d..c1d4173c 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -226043,6 +226043,292 @@ {} ] ], + "range-input-appearance-native-horizontal-rtl.optional.html": [ + "9382f890fb9465f92e527a9b85cda2ff886453cd", + [ + null, + [ + [ + "/css/css-writing-modes/forms/range-input-appearance-native-horizontal.optional.html", + "!=" + ], + [ + "/css/css-writing-modes/forms/range-input-appearance-none-horizontal.optional.html", + "!=" + ] + ], + {} + ] + ], + "range-input-appearance-native-horizontal.optional.html": [ + "1651d83326f809ebe1370fa0e31628681a98e069", + [ + null, + [ + [ + "/css/css-writing-modes/forms/range-input-appearance-native-vertical.optional.html", + "!=" + ], + [ + "/css/css-writing-modes/forms/range-input-appearance-none-vertical.optional.html", + "!=" + ] + ], + {} + ] + ], + "range-input-appearance-native-vertical-rtl.optional.html": [ + "74b24b56af9afc4f8b0ef02e67952783b921bd0c", + [ + null, + [ + [ + "/css/css-writing-modes/forms/range-input-appearance-native-vertical.optional.html", + "!=" + ], + [ + "/css/css-writing-modes/forms/range-input-appearance-none-vertical.optional.html", + "!=" + ] + ], + {} + ] + ], + "range-input-appearance-native-vertical.optional.html": [ + "ca7eb994ae6e2841b35a79cf358aa3ed76090154", + [ + null, + [ + [ + "/css/css-writing-modes/forms/range-input-appearance-native-horizontal.optional.html", + "!=" + ], + [ + "/css/css-writing-modes/forms/range-input-appearance-none-horizontal.optional.html", + "!=" + ] + ], + {} + ] + ], + "range-input-appearance-none-horizontal-rtl.optional.html": [ + "c1485688d36fe66deb39c19a4386018c9b790e41", + [ + null, + [ + [ + "/css/css-writing-modes/forms/range-input-appearance-none-horizontal.optional.html", + "!=" + ], + [ + "/css/css-writing-modes/forms/range-input-appearance-native-horizontal.optional.html", + "!=" + ] + ], + {} + ] + ], + "range-input-appearance-none-horizontal.optional.html": [ + "1f4bfe4c68450ba56bcaa6d238df35201ac24d1e", + [ + null, + [ + [ + "/css/css-writing-modes/forms/range-input-appearance-none-vertical.optional.html", + "!=" + ], + [ + "/css/css-writing-modes/forms/range-input-appearance-native-vertical.optional.html", + "!=" + ] + ], + {} + ] + ], + "range-input-appearance-none-vertical-rtl.optional.html": [ + "a4696e40c97d680fe10cfd7efbae2717df0aaa3a", + [ + null, + [ + [ + "/css/css-writing-modes/forms/range-input-appearance-none-vertical.optional.html", + "!=" + ], + [ + "/css/css-writing-modes/forms/range-input-appearance-native-vertical.optional.html", + "!=" + ] + ], + {} + ] + ], + "range-input-appearance-none-vertical.optional.html": [ + "9c151c659ec0452922f640829f86339b06bdebc4", + [ + null, + [ + [ + "/css/css-writing-modes/forms/range-input-appearance-none-horizontal.optional.html", + "!=" + ], + [ + "/css/css-writing-modes/forms/range-input-appearance-native-horizontal.optional.html", + "!=" + ] + ], + {} + ] + ], + "select-multiple-appearance-native-horizontal.optional.html": [ + "57b84109a823a0e1781f56a5241c5b1394309820", + [ + null, + [ + [ + "/css/css-writing-modes/forms/select-multiple-appearance-native-vlr.optional.html", + "!=" + ], + [ + "/css/css-writing-modes/forms/select-multiple-appearance-none-vlr.optional.html", + "!=" + ], + [ + "/css/css-writing-modes/forms/select-multiple-appearance-native-vrl.optional.html", + "!=" + ], + [ + "/css/css-writing-modes/forms/select-multiple-appearance-none-vrl.optional.html", + "!=" + ] + ], + {} + ] + ], + "select-multiple-appearance-native-vlr.optional.html": [ + "dcec498ff021371f152d77949d937d9439ef0b44", + [ + null, + [ + [ + "/css/css-writing-modes/forms/select-multiple-appearance-native-horizontal.optional.html", + "!=" + ], + [ + "/css/css-writing-modes/forms/select-multiple-appearance-none-horizontal.optional.html", + "!=" + ], + [ + "/css/css-writing-modes/forms/select-multiple-appearance-native-vrl.optional.html", + "!=" + ], + [ + "/css/css-writing-modes/forms/select-multiple-appearance-none-vrl.optional.html", + "!=" + ] + ], + {} + ] + ], + "select-multiple-appearance-native-vrl.optional.html": [ + "bdad9390c0485a69a4f888de008cc970448ccd62", + [ + null, + [ + [ + "/css/css-writing-modes/forms/select-multiple-appearance-native-horizontal.optional.html", + "!=" + ], + [ + "/css/css-writing-modes/forms/select-multiple-appearance-none-horizontal.optional.html", + "!=" + ], + [ + "/css/css-writing-modes/forms/select-multiple-appearance-native-vlr.optional.html", + "!=" + ], + [ + "/css/css-writing-modes/forms/select-multiple-appearance-none-vlr.optional.html", + "!=" + ] + ], + {} + ] + ], + "select-multiple-appearance-none-horizontal.optional.html": [ + "784451c336b063da00cec82830fe3131239f82a0", + [ + null, + [ + [ + "/css/css-writing-modes/forms/select-multiple-appearance-none-vlr.optional.html", + "!=" + ], + [ + "/css/css-writing-modes/forms/select-multiple-appearance-native-vlr.optional.html", + "!=" + ], + [ + "/css/css-writing-modes/forms/select-multiple-appearance-none-vrl.optional.html", + "!=" + ], + [ + "/css/css-writing-modes/forms/select-multiple-appearance-native-vrl.optional.html", + "!=" + ] + ], + {} + ] + ], + "select-multiple-appearance-none-vlr.optional.html": [ + "6099eb271dd9d802df307579730cf168069012f3", + [ + null, + [ + [ + "/css/css-writing-modes/forms/select-multiple-appearance-none-horizontal.optional.html", + "!=" + ], + [ + "/css/css-writing-modes/forms/select-multiple-appearance-native-horizontal.optional.html", + "!=" + ], + [ + "/css/css-writing-modes/forms/select-multiple-appearance-native-vrl.optional.html", + "!=" + ], + [ + "/css/css-writing-modes/forms/select-multiple-appearance-none-vrl.optional.html", + "!=" + ] + ], + {} + ] + ], + "select-multiple-appearance-none-vrl.optional.html": [ + "dfb0269b66f834af24b3644c735fd4e53e5d55e8", + [ + null, + [ + [ + "/css/css-writing-modes/forms/select-multiple-appearance-none-horizontal.optional.html", + "!=" + ], + [ + "/css/css-writing-modes/forms/select-multiple-appearance-native-horizontal.optional.html", + "!=" + ], + [ + "/css/css-writing-modes/forms/select-multiple-appearance-none-vlr.optional.html", + "!=" + ], + [ + "/css/css-writing-modes/forms/select-multiple-appearance-native-vlr.optional.html", + "!=" + ] + ], + {} + ] + ], "textarea-appearance-native-horizontal.optional.html": [ "79c54d5063dbe9aec30795b9d2a102c83eec902a", [ @@ -316949,7 +317235,15 @@ [] ] } - } + }, + "select-multiple-scrolling.optional-expected.txt": [ + "464cdd671865d23e588523f9b2e8e4195b965eb6", + [] + ], + "select-size-scrolling-and-sizing.optional-expected.txt": [ + "c6bc659541735c299008f967b80fb99cad41dae8", + [] + ] }, "horizontal-rule-vlr-003-ref.xht": [ "24130d157837083bf97eeff3420f58693f1daf27", @@ -328131,18 +328425,6 @@ "81943845447e6c6b7962b3961996e45c12e04cd4", [] ], - "feature-policy-idle-detection-worker.html": [ - "1ef5298abf1b2062f98c8aba5675decd36c5313d", - [] - ], - "feature-policy-idle-detection-worker.js": [ - "2e4e3cdc727613bbecf51465a0f3802781cf847b", - [] - ], - "feature-policy-idle-detection.html": [ - "65a578181b9ac433961416759195402343c57c6a", - [] - ], "feature-policy-nested-subframe-policy.https.sub.html": [ "30525d8a3cda45b5ca63777c582a74e677f27031", [] @@ -328159,30 +328441,6 @@ "08a0ecaded8c5af917be1ae1287d455483205e45", [] ], - "feature-policy-serial-worker.html": [ - "9e6a7d02ba2b8eef1fcc12d8049af830688e6946", - [] - ], - "feature-policy-serial-worker.js": [ - "2e8e6f5433a5e8fe9180b5660a9f301c936637dc", - [] - ], - "feature-policy-serial.html": [ - "caf716d37ac53c492f2eeb5815af533fc840eec7", - [] - ], - "feature-policy-usb-worker.html": [ - "fa8a2d70eb8d12933479e094e90375fedd062f5e", - [] - ], - "feature-policy-usb-worker.js": [ - "c294f14f3c628d81845a81cbef08bbf5c01f9d29", - [] - ], - "feature-policy-usb.html": [ - "99d47c6f3929bd61f7dfdefb1c5488c396abc172", - [] - ], "featurepolicy.js": [ "864c434c6633ca7a91de229a7511dd0bd3109add", [] @@ -351954,28 +352212,28 @@ "96ca8ed76f39d3f3a2e63c292b4a882917ffa3b4", [] ], - "idle-detection-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html.ini": [ - "45c77e5a730f2ce403fa64965be29c8d5a8268e8", + "idle-detection-allowed-by-permissions-policy-attribute-redirect-on-load.https.sub.html.ini": [ + "e00e2705e8158d40604279f2e14c92b70be1290d", [] ], - "idle-detection-allowed-by-feature-policy-attribute.https.sub.html.ini": [ - "a4d0e1d511cc0ba654896e9aecf11743967b5c23", + "idle-detection-allowed-by-permissions-policy-attribute.https.sub.html.ini": [ + "d0037302a23a03b38dc54eec0a1306c7e4c8f63c", [] ], - "idle-detection-allowed-by-feature-policy.https.sub.html.headers": [ - "729e9429e6a4ad7375474297d4fd7e7599eb04e0", + "idle-detection-allowed-by-permissions-policy.https.sub.html.headers": [ + "2bf18afe5fe4d034619b3e0a62455649d4203e18", [] ], - "idle-detection-allowed-by-feature-policy.https.sub.html.ini": [ - "cda09c8701f517b413ef221cad8df0206eb75df5", + "idle-detection-allowed-by-permissions-policy.https.sub.html.ini": [ + "6f363c189c39ce8e2921eb7be18b2a9a306423f7", [] ], - "idle-detection-default-feature-policy.https.sub.html.ini": [ - "08fd1d3caaafd6761c75d692858f7b524376328d", + "idle-detection-default-permissions-policy.https.sub.html.ini": [ + "cb296f98a8730d86ba71d19f3b77a777635c200a", [] ], - "idle-detection-disabled-by-feature-policy.https.sub.html.headers": [ - "f27e1a262717ea1ed666f59035a88a1d481a7460", + "idle-detection-disabled-by-permissions-policy.https.sub.html.headers": [ + "289463c30d8de9f6ce41ab635b7876cc5d06160f", [] ], "idle-permission.tentative.https.window.js.ini": [ @@ -351991,12 +352249,12 @@ [] ], "resources": { - "idle-detection-allowed-by-feature-policy-worker.js": [ - "e643414f750897516db0576cd02262c3d571d4c1", + "idle-detection-allowed-by-permissions-policy-worker.js": [ + "1fe410ed114ac09df4873ea661a038a7b3faec87", [] ], - "idle-detection-disabled-by-feature-policy-worker.js": [ - "138b29173f73eaed62dc57f4c912d15c174f9a5f", + "idle-detection-disabled-by-permissions-policy-worker.js": [ + "c30f7c188e747eaf4b43dacaba21fd17d2d5af81", [] ], "idle-detection-helper.js": [ @@ -354782,7 +355040,7 @@ [] ], "util.js": [ - "1b3c82d7d68da9b2f94159db850d1951dadd33f6", + "597e2d7d849bf55113f594d647913a73b44f24ef", [] ] } @@ -360290,11 +360548,11 @@ [] ], "permissions-policy-idle-detection-worker.js": [ - "2e4e3cdc727613bbecf51465a0f3802781cf847b", + "0d348c72ae7136268da5414a963dee6e83315911", [] ], "permissions-policy-idle-detection.html": [ - "65a578181b9ac433961416759195402343c57c6a", + "f21a3851d16dc33df4e37a09cb373ee737971076", [] ], "permissions-policy-local-fonts.html": [ @@ -360330,11 +360588,11 @@ [] ], "permissions-policy-serial-worker.js": [ - "2e8e6f5433a5e8fe9180b5660a9f301c936637dc", + "59bb6787ddf7166217f9f60cc58752d4f2853971", [] ], "permissions-policy-serial.html": [ - "caf716d37ac53c492f2eeb5815af533fc840eec7", + "fe25f034826249e99da51f3590092f8479b8f6ff", [] ], "permissions-policy-usb-worker.html": [ @@ -360342,11 +360600,11 @@ [] ], "permissions-policy-usb-worker.js": [ - "c294f14f3c628d81845a81cbef08bbf5c01f9d29", + "97d96e7fb71a9d41271923ec831940b91ab94ccf", [] ], "permissions-policy-usb.html": [ - "99d47c6f3929bd61f7dfdefb1c5488c396abc172", + "8812ca7db9a8288e4a820bc282a9febb74903971", [] ], "permissions-policy.js": [ @@ -364949,21 +365207,21 @@ "ac19136b35acc43e7290131fd082657c58f1387b", [] ], - "serial-allowed-by-feature-policy-worker.js": [ - "46c338e9a33a9ee0148ca48d09fc9c3bec37736b", + "serial-allowed-by-permissions-policy-worker.js": [ + "cef0aacdfc3d2f755b185439679706318935df17", [] ], - "serial-disabled-by-feature-policy-worker.js": [ - "b64b1a861ecfa431fab2ec383dcf420326a47bde", + "serial-disabled-by-permissions-policy-worker.js": [ + "afac44297484c816f455d86f5cc61b757b8cb084", [] ] }, - "serial-allowed-by-feature-policy.https.sub.html.headers": [ - "113ce29ae9f5aeafbf68388c03be1c776c889c60", + "serial-allowed-by-permissions-policy.https.sub.html.headers": [ + "27deb827582114a45e29a7ebbb463badee1b6d7b", [] ], - "serial-disabled-by-feature-policy.https.sub.html.headers": [ - "be3e6afd423f767369725724eb3509447c852a59", + "serial-disabled-by-permissions-policy.https.sub.html.headers": [ + "690b6967513cd25ec11d048c448f63af463fdb03", [] ], "serialPort_events.https.any-expected.txt": [ @@ -378635,12 +378893,12 @@ "e16621057a0240186803bb1de1c012406c89505d", [] ], - "usb-allowed-by-feature-policy-worker.js": [ - "99ac97e28b0ba8dff1af22096589ba18201129c0", + "usb-allowed-by-permissions-policy-worker.js": [ + "d06a58647438f034a2535f4d821bb5bb47000580", [] ], - "usb-disabled-by-feature-policy-worker.js": [ - "59349560ad197538e569c4dca7c46504ff2567bf", + "usb-disabled-by-permissions-policy-worker.js": [ + "caf2727cd13cbb4570b1c7d1afa984ad02a96266", [] ], "usb-helpers.js": [ @@ -378648,11 +378906,11 @@ [] ] }, - "usb-allowed-by-feature-policy.https.sub.html.headers": [ + "usb-allowed-by-permissions-policy.https.sub.html.headers": [ "022b027812ab3ea7e7b730d99f11f4229aa8fb2f", [] ], - "usb-disabled-by-feature-policy.https.sub.html.headers": [ + "usb-disabled-by-permissions-policy.https.sub.html.headers": [ "ff22d62f104a3cf8cf4a659498f682dc1e83d34d", [] ], @@ -445131,6 +445389,20 @@ {} ] ], + "select-multiple-scrolling.optional.html": [ + "ffaba9fe552dc999576342e368fed5e54941a546", + [ + null, + {} + ] + ], + "select-size-scrolling-and-sizing.optional.html": [ + "d70e018da72a3c5636c2b5c4907d22c839378cc4", + [ + null, + {} + ] + ], "textarea-rows-cols-sizing.html": [ "8cd9c27d36cba2f6c7a1863c3d1c95d1c3b97320", [ @@ -538851,8 +539123,8 @@ } ] ], - "idle-detection-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html": [ - "6c6ff6f14c8d5f47d6c838863e32e1fa05d17729", + "idle-detection-allowed-by-permissions-policy-attribute-redirect-on-load.https.sub.html": [ + "fc92a09f6c89bc6204bc7b88d1dc6c2e4ac709ca", [ null, { @@ -538860,8 +539132,8 @@ } ] ], - "idle-detection-allowed-by-feature-policy-attribute.https.sub.html": [ - "f3cfa0e1383f9687e513d51b47da3bc3c33e1abc", + "idle-detection-allowed-by-permissions-policy-attribute.https.sub.html": [ + "be2de1d76c62359f5ceddfa62801570f4182db4a", [ null, { @@ -538869,8 +539141,8 @@ } ] ], - "idle-detection-allowed-by-feature-policy.https.sub.html": [ - "75d15409de36a05258e0ec339ad00595a131b01f", + "idle-detection-allowed-by-permissions-policy.https.sub.html": [ + "47a7d69ee0c8772220311f3814c5efce960bb61a", [ null, { @@ -538878,8 +539150,8 @@ } ] ], - "idle-detection-default-feature-policy.https.sub.html": [ - "f0766ae960e133cdfa73f9eb46767ddb5b6f5ae5", + "idle-detection-default-permissions-policy.https.sub.html": [ + "762e29968ecc8b17d1a36fc7509b9c34544fa4bf", [ null, { @@ -538887,8 +539159,8 @@ } ] ], - "idle-detection-disabled-by-feature-policy.https.sub.html": [ - "2814a2263db71658ac9104974147b543929c25e4", + "idle-detection-disabled-by-permissions-policy.https.sub.html": [ + "90317dece7aff71c84a2d288790104d61cf4e1da", [ null, {} @@ -576603,22 +576875,22 @@ } ] ], - "serial-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html": [ - "7c3a88dd51f93d74dc86882c12aab6bd2c25afb0", + "serial-allowed-by-permissions-policy-attribute-redirect-on-load.https.sub.html": [ + "ac278ff0cf0f92dd2547851771e5cda7cc15ea4b", [ null, {} ] ], - "serial-allowed-by-feature-policy-attribute.https.sub.html": [ - "1420c5c01434a852661e40287ae24585bcce5aa4", + "serial-allowed-by-permissions-policy-attribute.https.sub.html": [ + "02560b180f6ae61761913324fed9f973a76b79f2", [ null, {} ] ], - "serial-allowed-by-feature-policy.https.sub.html": [ - "36990694d19db365eddd2ebee9cd85867318d4c8", + "serial-allowed-by-permissions-policy.https.sub.html": [ + "1be8eb979f8217db5683e8d2c780c183c2a466e5", [ null, { @@ -576626,15 +576898,15 @@ } ] ], - "serial-default-feature-policy.https.sub.html": [ - "61a872f9b5c400bd9d0cb97c2ecadc69ce6ccc30", + "serial-default-permissions-policy.https.sub.html": [ + "e3908d921521cf2419f66db8dc78bea6e044789e", [ null, {} ] ], - "serial-disabled-by-feature-policy.https.sub.html": [ - "cddf157e8ae5a9dc53ce2b5ad9bf499c61b0db04", + "serial-disabled-by-permissions-policy.https.sub.html": [ + "53646c526c8e613647909ca4518339b427043c32", [ null, {} @@ -624718,36 +624990,36 @@ } ] ], - "usb-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html": [ - "e0757feeb2da84da7e391053dd03a9b3458a2900", + "usb-allowed-by-permissions-policy-attribute-redirect-on-load.https.sub.html": [ + "013efd9b4db00019bc5484c17f5c1b2e7ad93575", [ null, {} ] ], - "usb-allowed-by-feature-policy-attribute.https.sub.html": [ - "078db141ad319d83079a7c8f7a6b7b9ebd813286", + "usb-allowed-by-permissions-policy-attribute.https.sub.html": [ + "54af693da0d4f6b7b6d205c7b2ffdd464b6e2232", [ null, {} ] ], - "usb-allowed-by-feature-policy.https.sub.html": [ - "831cb42cab614b62e261e227c5423f6d7a70746a", + "usb-allowed-by-permissions-policy.https.sub.html": [ + "e1461fe8e698b78dcad86dc92b919947c4e81336", [ null, {} ] ], - "usb-default-feature-policy.https.sub.html": [ - "34dda5280126f0a84526380ba9b5ce4df9613b24", + "usb-default-permissions-policy.https.sub.html": [ + "5a9ddcb4fe74b662f85ba4394c2016eb8e2f37f2", [ null, {} ] ], - "usb-disabled-by-feature-policy.https.sub.html": [ - "97e66b2a373f73de5fd705cdaabb60d5625127f5", + "usb-disabled-by-permissions-policy.https.sub.html": [ + "3217d326f7c5fc678607eaa674fe8d965fa680d0", [ null, {} @@ -624779,8 +625051,8 @@ } ] ], - "usb-supported-by-feature-policy.html": [ - "d5b585a094f516839dd897935839953d15043dce", + "usb-supported-by-permissions-policy.html": [ + "8e6352116d33d2aac1dc80809d6357ff78c370d9", [ null, {}
diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/container-for-shadow-dom.html b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/container-for-shadow-dom.html index 3e7572b..22fa9dd 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/container-for-shadow-dom.html +++ b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/container-for-shadow-dom.html
@@ -4,6 +4,7 @@ <link rel="help" href="https://drafts.csswg.org/css-contain-3/#query-container"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/resources/declarative-shadow-dom-polyfill.js"></script> <script src="support/cq-testcommon.js"></script> <style> #inclusive-ancestor-across-root,
diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/container-name-tree-scoped.html b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/container-name-tree-scoped.html index 7c41c54..c4f4bb9 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/container-name-tree-scoped.html +++ b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/container-name-tree-scoped.html
@@ -5,6 +5,7 @@ <link rel="help" href="https://drafts.csswg.org/css-scoping-1/#shadow-names"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/resources/declarative-shadow-dom-polyfill.js"></script> <script src="support/cq-testcommon.js"></script> <div id="container-name-host">
diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/container-size-shadow-invalidation.html b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/container-size-shadow-invalidation.html index 0ee6770..7350d297 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/container-size-shadow-invalidation.html +++ b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/container-size-shadow-invalidation.html
@@ -4,6 +4,7 @@ <link rel="help" href="https://drafts.csswg.org/css-contain-3/#query-container"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/resources/declarative-shadow-dom-polyfill.js"></script> <script src="support/cq-testcommon.js"></script> <style> .container {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/container-units-shadow.html b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/container-units-shadow.html index e605a53..1a711da 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/container-units-shadow.html +++ b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/container-units-shadow.html
@@ -4,6 +4,7 @@ <link rel="help" href="https://drafts.csswg.org/css-contain-3/#container-queries"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/resources/declarative-shadow-dom-polyfill.js"></script> <script src="support/cq-testcommon.js"></script> <style> #outer {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/support/cq-testcommon.js b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/support/cq-testcommon.js index 673c317..2eaca1d 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/support/cq-testcommon.js +++ b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/support/cq-testcommon.js
@@ -1,13 +1,3 @@ function assert_implements_container_queries() { assert_implements(CSS.supports("container-type:size"), "Basic support for container queries required"); } - -function polyfill_declarative_shadow_dom(root) { - root.querySelectorAll("template[shadowroot]").forEach(template => { - const mode = template.getAttribute("shadowroot"); - const shadowRoot = template.parentNode.attachShadow({ mode }); - shadowRoot.appendChild(template.content); - template.remove(); - polyfill_declarative_shadow_dom(shadowRoot); - }); -}
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-drop-over-ruby-ref.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-drop-over-ruby-ref.html new file mode 100644 index 0000000..c7492e4 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-drop-over-ruby-ref.html
@@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter with over ruby</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#initial-letter-block-position"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + .fake-initial-letter { + background: lime; + float: left; + height: 80px; + margin-top: 22px; + width: 80px; + } +</style> +</head> +<body> +<div class="sample"> +<div class="fake-initial-letter"></div> +bc <ruby>xyz<rt>XYZ</rt></ruby><br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-drop-over-ruby-tall-ref.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-drop-over-ruby-tall-ref.html new file mode 100644 index 0000000..3ce5ba9 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-drop-over-ruby-tall-ref.html
@@ -0,0 +1,38 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter with over ruby overflow</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#initial-letter-block-position"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + rt { font-size: 80px; } + + .fake-initial-letter { + background: lime; + float: left; + height: 80px; + margin-top: 92px; + width: 80px; + } + + .surrounding { display:inline-block; } +</style> +</head> +<body> +<div class="sample"> +<div class="fake-initial-letter"></div> +<div class="surrounding">bc <ruby>xyz<rt>X</rt></ruby></div> +def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-drop-over-ruby-tall.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-drop-over-ruby-tall.html new file mode 100644 index 0000000..fd92e1b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-drop-over-ruby-tall.html
@@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter with over ruby overflow</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#initial-letter-block-position"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<link rel="match" href="initial-letter-block-position-drop-over-ruby-tall-ref.html"> +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + rt { font-size: 80px; } + + .initial-letter::first-letter { + initial-letter: 3 drop; + color: lime; + font-size: 100px; /* should be ignored in rendering */ + line-height: 50px; /* should be ignored in rendering */ + } +</style> +</head> +<body> +<div class="sample initial-letter"> +Abc <ruby>xyz<rt>X</rt></ruby><br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-drop-over-ruby.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-drop-over-ruby.html new file mode 100644 index 0000000..5d8b0b9 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-drop-over-ruby.html
@@ -0,0 +1,32 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter with over ruby</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#initial-letter-block-position"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<link rel="match" href="initial-letter-block-position-drop-over-ruby-ref.html"> +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + .initial-letter::first-letter { + initial-letter: 3 drop; + color: lime; + font-size: 100px; /* should be ignored in rendering */ + line-height: 50px; /* should be ignored in rendering */ + } +</style> +</head> +<body> +<div class="sample initial-letter"> +Abc <ruby>xyz<rt>XYZ</rt></ruby><br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-drop-under-ruby-ref.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-drop-under-ruby-ref.html new file mode 100644 index 0000000..f490dc5 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-drop-under-ruby-ref.html
@@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter with under ruby</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#initial-letter-block-position"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + ruby { ruby-position: under; } + .fake-initial-letter { + background: lime; + float: left; + height: 80px; + margin-top: 14px; + width: 80px; + } +</style> +</head> +<body> +<div class="sample"> +<div class="fake-initial-letter"></div> +bc <ruby>xyz<rt>XYZ</rt></ruby><br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-drop-under-ruby-tall-ref.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-drop-under-ruby-tall-ref.html new file mode 100644 index 0000000..07b6c983 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-drop-under-ruby-tall-ref.html
@@ -0,0 +1,38 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter with under ruby</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#initial-letter-block-position"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + rt { font-size: 80px; } + ruby { ruby-position: under; } + .fake-initial-letter { + background: lime; + float: left; + height: 80px; + margin-top: 14px; + width: 80px; + } + + .surrounding { display:inline-block; margin-bottom: -2px; } +</style> +</head> +<body> +<div class="sample"> +<div class="fake-initial-letter"></div> +<div class="surrounding">bc <ruby>xyz<rt>X</rt></ruby></div> +def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-drop-under-ruby-tall.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-drop-under-ruby-tall.html new file mode 100644 index 0000000..6892160 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-drop-under-ruby-tall.html
@@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter with under ruby</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#initial-letter-block-position"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<link rel="match" href="initial-letter-block-position-drop-under-ruby-tall-ref.html"> +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + rt { font-size: 80px; } + ruby { ruby-position: under; } + .initial-letter::first-letter { + initial-letter: 3 drop; + color: lime; + font-size: 100px; /* should be ignored in rendering */ + line-height: 50px; /* should be ignored in rendering */ + } +</style> +</head> +<body> +<div class="sample initial-letter"> +Abc <ruby>xyz<rt>X</rt></ruby><br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-drop-under-ruby.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-drop-under-ruby.html new file mode 100644 index 0000000..c9f4623 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-drop-under-ruby.html
@@ -0,0 +1,32 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter with under ruby</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#initial-letter-block-position"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<link rel="match" href="initial-letter-block-position-drop-under-ruby-ref.html"> +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + ruby { ruby-position: under; } + .initial-letter::first-letter { + initial-letter: 3 drop; + color: lime; + font-size: 100px; /* should be ignored in rendering */ + line-height: 50px; /* should be ignored in rendering */ + } +</style> +</head> +<body> +<div class="sample initial-letter"> +Abc <ruby>xyz<rt>XYZ</rt></ruby><br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-margins-ref.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-margins-ref.html new file mode 100644 index 0000000..ffcc8bf2 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-margins-ref.html
@@ -0,0 +1,36 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter with margin in LTR</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#block-position"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + .fake-initial-letter { + background: lime; + float: left; + height: 80px; + margin-bottom: 30px; + margin-left: 15px; + margin-right: 45px; + margin-top: 24px; + width: 80px; + } +</style> +</head> +<body> +<div class="sample"> +<div class="fake-initial-letter"></div> +bc<br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-margins-rtl-ref.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-margins-rtl-ref.html new file mode 100644 index 0000000..6feb72d --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-margins-rtl-ref.html
@@ -0,0 +1,37 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter with margin in RTL</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#block-position"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<style> + .sample { + border: solid 1px green; + direction: rtl; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + .fake-initial-letter { + background: lime; + float: right; + height: 80px; + margin-bottom: 30px; + margin-left: 15px; + margin-right: 45px; + margin-top: 24px; + width: 80px; + } +</style> +</head> +<body> +<div class="sample"> +<div class="fake-initial-letter"></div> +bc<br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-margins-rtl.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-margins-rtl.html new file mode 100644 index 0000000..7bfd201 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-margins-rtl.html
@@ -0,0 +1,40 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter with margin in RTL</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#block-position"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<link rel="match" href="initial-letter-block-position-margins-rtl-ref.html"> +<style> + .sample { + border: solid 1px green; + direction: rtl; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + .initial-letter::first-letter { + initial-letter: 3 drop; + color: lime; + font-size: 100px; /* should be ignored in rendering */ + line-height: 50px; /* should be ignored in rendering */ + } + + .initial-letter::first-letter { + margin-top: 10px; + margin-bottom: 30px; + margin-left: 15px; + margin-right: 45px; + } +</style> +</head> +<body> +<div class="sample initial-letter"> +Abc<br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-margins-vlr-ref.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-margins-vlr-ref.html new file mode 100644 index 0000000..6bbc5c3 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-margins-vlr-ref.html
@@ -0,0 +1,37 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter with margin in vertical-lr</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#block-position"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + height: 230px; + line-height: 24px; + writing-mode: vertical-lr; + } + + .fake-initial-letter { + background: lime; + float: left; + height: 80px; + margin-bottom: 30px; + margin-left: 23px; + margin-right: 45px; + margin-top: 10px; + width: 80px; + } +</style> +</head> +<body> +<div class="sample"> +<div class="fake-initial-letter"></div> +bc<br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-margins-vlr.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-margins-vlr.html new file mode 100644 index 0000000..09c6948 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-margins-vlr.html
@@ -0,0 +1,40 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter with margin in vertical-lr</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#block-position"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<link rel="match" href="initial-letter-block-position-margins-vlr-ref.html"> +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + height: 230px; + line-height: 24px; + writing-mode: vertical-lr; + } + + .initial-letter::first-letter { + initial-letter: 3 drop; + color: lime; + font-size: 100px; /* should be ignored in rendering */ + line-height: 50px; /* should be ignored in rendering */ + } + + .initial-letter::first-letter { + margin-top: 10px; + margin-bottom: 30px; + margin-left: 15px; + margin-right: 45px; + } +</style> +</head> +<body> +<div class="sample initial-letter"> +Abc<br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-margins-vrl-ref.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-margins-vrl-ref.html new file mode 100644 index 0000000..d608d256c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-margins-vrl-ref.html
@@ -0,0 +1,37 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter with margin in vertical-rl</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#block-position"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + height: 230px; + line-height: 24px; + writing-mode: vertical-rl; + } + + .fake-initial-letter { + background: lime; + float: left; + height: 80px; + margin-bottom: 30px; + margin-left: 15px; + margin-right: 53px; + margin-top: 10px; + width: 80px; + } +</style> +</head> +<body> +<div class="sample"> +<div class="fake-initial-letter"></div> +bc<br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-margins-vrl.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-margins-vrl.html new file mode 100644 index 0000000..2e2696f --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-margins-vrl.html
@@ -0,0 +1,40 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter with margin in vertical-rl</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#block-position"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<link rel="match" href="initial-letter-block-position-margins-vrl-ref.html"> +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + height: 230px; + line-height: 24px; + writing-mode: vertical-rl; + } + + .initial-letter::first-letter { + initial-letter: 3 drop; + color: lime; + font-size: 100px; /* should be ignored in rendering */ + line-height: 50px; /* should be ignored in rendering */ + } + + .initial-letter::first-letter { + margin-top: 10px; + margin-bottom: 30px; + margin-left: 15px; + margin-right: 45px; + } +</style> +</head> +<body> +<div class="sample initial-letter"> +Abc<br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-margins.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-margins.html new file mode 100644 index 0000000..3ce4c7d --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-margins.html
@@ -0,0 +1,39 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter with margin in LTR</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#block-position"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<link rel="match" href="initial-letter-block-position-margins-ref.html"> +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + .initial-letter::first-letter { + initial-letter: 3 drop; + color: lime; + font-size: 100px; /* should be ignored in rendering */ + line-height: 50px; /* should be ignored in rendering */ + } + + .initial-letter::first-letter { + margin-top: 10px; + margin-bottom: 30px; + margin-left: 15px; + margin-right: 45px; + } +</style> +</head> +<body> +<div class="sample initial-letter"> +Abc<br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-raise-over-ruby-ref.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-raise-over-ruby-ref.html new file mode 100644 index 0000000..c5222c99 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-raise-over-ruby-ref.html
@@ -0,0 +1,39 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter with over ruby</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#initial-letter-block-position"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + .fake-initial-letter { + background: lime; + float: left; + height: 80px; + margin-top: 14px; + width: 80px; + } + + .surrounding { + display:inline-block; + margin-top: -16px; + } +</style> +</head> +<body> +<div class="sample"> +<div class="fake-initial-letter"></div><br><br><br> +<div class="surrounding">bc <ruby>xyz<rt>XYZ</rt></ruby></div> +def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-raise-over-ruby-tall-ref.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-raise-over-ruby-tall-ref.html new file mode 100644 index 0000000..74f2944 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-raise-over-ruby-tall-ref.html
@@ -0,0 +1,38 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter with over ruby overflow</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#initial-letter-block-position"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + rt { font-size: 80px; } + + .fake-initial-letter { + background: lime; + float: left; + height: 80px; + margin-top: 20px; + width: 80px; + } + + .surrounding { display:inline-block; } +</style> +</head> +<body> +<div class="sample"> +<div class="fake-initial-letter"></div> +<div class="surrounding">bc <ruby>xyz<rt>X</rt></ruby></div> +def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-raise-over-ruby-tall.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-raise-over-ruby-tall.html new file mode 100644 index 0000000..eddba2f --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-raise-over-ruby-tall.html
@@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter with over ruby overflow</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#initial-letter-block-position"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<link rel="match" href="initial-letter-block-position-raise-over-ruby-tall-ref.html"> +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + rt { font-size: 80px; } + + .initial-letter::first-letter { + initial-letter: 3 raise; + color: lime; + font-size: 100px; /* should be ignored in rendering */ + line-height: 50px; /* should be ignored in rendering */ + } +</style> +</head> +<body> +<div class="sample initial-letter"> +Abc <ruby>xyz<rt>X</rt></ruby><br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-raise-over-ruby.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-raise-over-ruby.html new file mode 100644 index 0000000..29b285ba3 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-raise-over-ruby.html
@@ -0,0 +1,32 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter with over ruby</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#initial-letter-block-position"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<link rel="match" href="initial-letter-block-position-raise-over-ruby-ref.html"> +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + .initial-letter::first-letter { + initial-letter: 3 raise; + color: lime; + font-size: 100px; /* should be ignored in rendering */ + line-height: 50px; /* should be ignored in rendering */ + } +</style> +</head> +<body> +<div class="sample initial-letter"> +Abc <ruby>xyz<rt>XYZ</rt></ruby><br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-raise-under-ruby-ref.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-raise-under-ruby-ref.html new file mode 100644 index 0000000..da28721a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-raise-under-ruby-ref.html
@@ -0,0 +1,40 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter with under ruby</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#initial-letter-block-position"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + ruby { ruby-position: under; } + .fake-initial-letter { + background: lime; + float: left; + height: 80px; + margin-top: 14px; + width: 80px; + } + + .surrounding { + display:inline-block; + margin-top: -16px; + margin-bottom: -2px; + } +</style> +</head> +<body> +<div class="sample"> +<div class="fake-initial-letter"></div><br><br><br> +<div class="surrounding">bc <ruby>xyz<rt>XYZ</rt></ruby></div> +def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-raise-under-ruby-tall-ref.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-raise-under-ruby-tall-ref.html new file mode 100644 index 0000000..c88f02bb --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-raise-under-ruby-tall-ref.html
@@ -0,0 +1,38 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter with under ruby</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#initial-letter-block-position"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + rt { font-size: 80px; } + ruby { ruby-position: under; } + .fake-initial-letter { + background: lime; + float: left; + height: 80px; + margin-top: 14px; + width: 80px; + } + + .surrounding { display:inline-block; margin-top: 72px; margin-bottom: -2px; } +</style> +</head> +<body> +<div class="sample"> +<div class="fake-initial-letter"></div> +<div class="surrounding">bc <ruby>xyz<rt>X</rt></ruby></div> +def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-raise-under-ruby-tall.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-raise-under-ruby-tall.html new file mode 100644 index 0000000..40130d47 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-raise-under-ruby-tall.html
@@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter with under ruby</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#initial-letter-block-position"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<link rel="match" href="initial-letter-block-position-raise-under-ruby-tall-ref.html"> +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + rt { font-size: 80px; } + ruby { ruby-position: under; } + .initial-letter::first-letter { + initial-letter: 3 raise; + color: lime; + font-size: 100px; /* should be ignored in rendering */ + line-height: 50px; /* should be ignored in rendering */ + } +</style> +</head> +<body> +<div class="sample initial-letter"> +Abc <ruby>xyz<rt>X</rt></ruby><br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-raise-under-ruby.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-raise-under-ruby.html new file mode 100644 index 0000000..367479d --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-raise-under-ruby.html
@@ -0,0 +1,32 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter with under ruby</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#initial-letter-block-position"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<link rel="match" href="initial-letter-block-position-raise-under-ruby-ref.html"> +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + ruby { ruby-position: under; } + .initial-letter::first-letter { + initial-letter: 3 raise; + color: lime; + font-size: 100px; /* should be ignored in rendering */ + line-height: 50px; /* should be ignored in rendering */ + } +</style> +</head> +<body> +<div class="sample initial-letter"> +Abc <ruby>xyz<rt>XYZ</rt></ruby><br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-drop-initial-ref.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-drop-initial-ref.html new file mode 100644 index 0000000..4020855 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-drop-initial-ref.html
@@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter drop initial</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#drop-initial"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + .fake-initial-letter { + background: lime; + float: left; + height: 80px; + margin-top: 14px; + width: 80px; + } +</style> +</head> +<body> +<div class="sample"> +<div class="fake-initial-letter"></div> +bc<br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-drop-initial-rtl-ref.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-drop-initial-rtl-ref.html new file mode 100644 index 0000000..0b99ceff --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-drop-initial-rtl-ref.html
@@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter drop initial in RTL</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#drop-initial"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<style> + .sample { + border: solid 1px green; + direction: rtl; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + .fake-initial-letter { + background: lime; + float: right; + height: 80px; + margin-top: 14px; + width: 80px; + } +</style> +</head> +<body> +<div class="sample"> +<div class="fake-initial-letter"></div> +bc<br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-drop-initial-rtl.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-drop-initial-rtl.html new file mode 100644 index 0000000..542cf00 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-drop-initial-rtl.html
@@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter drop initial in RTL</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#drop-initial"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<link rel="match" href="initial-letter-drop-initial-rtl-ref.html"> +<style> + .sample { + border: solid 1px green; + direction: rtl; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + .initial-letter::first-letter { + initial-letter: 3 drop; + color: lime; + font-size: 100px; /* should be ignored in rendering */ + line-height: 50px; /* should be ignored in rendering */ + } +</style> +</head> +<body> +<div class="sample initial-letter"> +Abc<br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-drop-initial-vlr-ref.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-drop-initial-vlr-ref.html new file mode 100644 index 0000000..f28d1eed --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-drop-initial-vlr-ref.html
@@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter drop initial in vertical-lr</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#drop-initial"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + height: 230px; + line-height: 24px; + writing-mode: vertical-lr; + } + + .fake-initial-letter { + background: lime; + float: left; + height: 80px; + margin-left: 8px; + width: 80px; + } +</style> +</head> +<body> +<div class="sample"> +<div class="fake-initial-letter"></div> +bc<br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-drop-initial-vlr.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-drop-initial-vlr.html new file mode 100644 index 0000000..98bb7a6 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-drop-initial-vlr.html
@@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter drop initial in vertical-lr</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#drop-initial"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<link rel="match" href="initial-letter-drop-initial-vlr-ref.html"> +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + height: 230px; + line-height: 24px; + writing-mode: vertical-lr; + } + + .initial-letter::first-letter { + initial-letter: 3 drop; + color: lime; + font-size: 100px; /* should be ignored in rendering */ + line-height: 50px; /* should be ignored in rendering */ + } +</style> +</head> +<body> +<div class="sample initial-letter"> +Abc<br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-drop-initial-vrl-ref.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-drop-initial-vrl-ref.html new file mode 100644 index 0000000..4ec34f4c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-drop-initial-vrl-ref.html
@@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter drop initial in vertical-lr</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#drop-initial"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + height: 230px; + line-height: 24px; + writing-mode: vertical-rl; + } + + .fake-initial-letter { + background: lime; + float: left; + height: 80px; + margin-right: 8px; + width: 80px; + } +</style> +</head> +<body> +<div class="sample"> +<div class="fake-initial-letter"></div> +bc<br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-drop-initial-vrl.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-drop-initial-vrl.html new file mode 100644 index 0000000..4d6aece --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-drop-initial-vrl.html
@@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter drop initial in vertical-lr</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#drop-initial"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<link rel="match" href="initial-letter-drop-initial-vrl-ref.html"> +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + height: 230px; + line-height: 24px; + writing-mode: vertical-rl; + } + + .initial-letter::first-letter { + initial-letter: 3 drop; + color: lime; + font-size: 100px; /* should be ignored in rendering */ + line-height: 50px; /* should be ignored in rendering */ + } +</style> +</head> +<body> +<div class="sample initial-letter"> +Abc<br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-drop-initial.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-drop-initial.html new file mode 100644 index 0000000..edd3ac96 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-drop-initial.html
@@ -0,0 +1,32 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter drop initial</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#drop-initial"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<link rel="match" href="initial-letter-drop-initial-ref.html"> +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + .initial-letter::first-letter { + initial-letter: 3 drop; + color: lime; + font-size: 100px; /* should be ignored in rendering */ + line-height: 50px; /* should be ignored in rendering */ + } +</style> +</head> +<body> +<div class="sample initial-letter"> +Abc<br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-indentation-ref.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-indentation-ref.html new file mode 100644 index 0000000..627dc43a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-indentation-ref.html
@@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter indentation</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#indentation"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + .fake-initial-letter { + background: lime; + float: left; + height: 80px; + margin-left: 20px; + margin-top: 14px; + width: 80px; + } +</style> +</head> +<body> +<div class="sample"> +<div class="fake-initial-letter"></div> +bc<br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-indentation-rtl-ref.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-indentation-rtl-ref.html new file mode 100644 index 0000000..8c72718 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-indentation-rtl-ref.html
@@ -0,0 +1,35 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter indentation in RTL</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#indentation"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<style> + .sample { + border: solid 1px green; + direction: rtl; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + .fake-initial-letter { + background: lime; + float: right; + height: 80px; + margin-right: 20px; + margin-top: 14px; + width: 80px; + } +</style> +</head> +<body> +<div class="sample"> +<div class="fake-initial-letter"></div> +bc<br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-indentation-rtl.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-indentation-rtl.html new file mode 100644 index 0000000..cd3e6f8 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-indentation-rtl.html
@@ -0,0 +1,36 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter indentation in RTL</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#indentation"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<link rel="match" href="initial-letter-indentation-rtl-ref.html"> +<style> + .sample { + border: solid 1px green; + direction: rtl; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + .initial-letter::first-letter { + initial-letter: 3 drop; + color: lime; + font-size: 100px; /* should be ignored in rendering */ + line-height: 50px; /* should be ignored in rendering */ + } + .sample { + text-indent: 10px; + } +</style> +</head> +<body> +<div class="sample initial-letter"> +Abc<br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-indentation.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-indentation.html new file mode 100644 index 0000000..20431f4 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-indentation.html
@@ -0,0 +1,35 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter indentation</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#indentation"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<link rel="match" href="initial-letter-indentation-ref.html"> +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + .initial-letter::first-letter { + initial-letter: 3 drop; + color: lime; + font-size: 100px; /* should be ignored in rendering */ + line-height: 50px; /* should be ignored in rendering */ + } + .sample { + text-indent: 10px; + } +</style> +</head> +<body> +<div class="sample initial-letter"> +Abc<br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial-ref.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial-ref.html new file mode 100644 index 0000000..983e5802 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial-ref.html
@@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter raise initial</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#raise-initial"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + .fake-initial-letter { + background: lime; + float: left; + height: 80px; + margin-top: 14px; + width: 80px; + } +</style> +</head> +<body> +<div class="sample"> +<div class="fake-initial-letter"></div><br><br><br> +bc<br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial-rtl-ref.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial-rtl-ref.html new file mode 100644 index 0000000..fbf155d --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial-rtl-ref.html
@@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter raise initial in RTL</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#raise-initial"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<style> + .sample { + border: solid 1px green; + direction: rtl; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + .fake-initial-letter { + background: lime; + float: right; + height: 80px; + margin-top: 14px; + width: 80px; + } +</style> +</head> +<body> +<div class="sample"> +<div class="fake-initial-letter"></div><br><br><br> +bc<br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial-rtl.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial-rtl.html new file mode 100644 index 0000000..10b90ac --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial-rtl.html
@@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter raise initial in RTL</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#raise-initial"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<link rel="match" href="initial-letter-raise-initial-rtl-ref.html"> +<style> + .sample { + border: solid 1px green; + direction: rtl; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + .initial-letter::first-letter { + initial-letter: 3 raise; + color: lime; + font-size: 100px; /* should be ignored in rendering */ + line-height: 50px; /* should be ignored in rendering */ + } +</style> +</head> +<body> +<div class="sample initial-letter"> +Abc<br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial-vlr-ref.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial-vlr-ref.html new file mode 100644 index 0000000..58e5c33 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial-vlr-ref.html
@@ -0,0 +1,42 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter raise initial in vertical-lr</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#raise-initial"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + height: 230px; + line-height: 24px; + writing-mode: vertical-lr; + } + + .fake-initial-letter { + background: lime; + display: inline-block; + height: 80px; + margin-left: 8px; + margin-right: 8px; + width: 80px; + } + + .remainder { + display: inline-block; + vertical-align: top; + margin-top: -20px; + } +</style> +</head> +<body> +<div class="sample"> +<div class="fake-initial-letter"></div> +<div class="remainder">bc</div><br> +def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial-vlr.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial-vlr.html new file mode 100644 index 0000000..6b1ebd5 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial-vlr.html
@@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter raise initial in vertical-lr</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#raise-initial"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<link rel="match" href="initial-letter-raise-initial-vlr-ref.html"> +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + height: 230px; + line-height: 24px; + writing-mode: vertical-lr; + } + + .initial-letter::first-letter { + initial-letter: 3 raise; + color: lime; + font-size: 100px; /* should be ignored in rendering */ + line-height: 50px; /* should be ignored in rendering */ + } +</style> +</head> +<body> +<div class="sample initial-letter"> +Abc<br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial-vrl-ref.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial-vrl-ref.html new file mode 100644 index 0000000..5fa6845 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial-vrl-ref.html
@@ -0,0 +1,42 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter raise initial in vertical-lr</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#raise-initial"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + height: 230px; + line-height: 24px; + writing-mode: vertical-rl; + } + + .fake-initial-letter { + background: lime; + display: inline-block; + height: 80px; + margin-left: 8px; + margin-right: 8px; + width: 80px; + } + + .remainder { + display: inline-block; + vertical-align: bottom; + margin-top: -20px; + } +</style> +</head> +<body> +<div class="sample"> +<div class="fake-initial-letter"></div> +<div class="remainder">bc</div><br> +def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial-vrl.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial-vrl.html new file mode 100644 index 0000000..62a699f5 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial-vrl.html
@@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter raise initial in vertical-lr</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#raise-initial"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<link rel="match" href="initial-letter-raise-initial-vrl-ref.html"> +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + height: 230px; + line-height: 24px; + writing-mode: vertical-rl; + } + + .initial-letter::first-letter { + initial-letter: 3 raise; + color: lime; + font-size: 100px; /* should be ignored in rendering */ + line-height: 50px; /* should be ignored in rendering */ + } +</style> +</head> +<body> +<div class="sample initial-letter"> +Abc<br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial.html new file mode 100644 index 0000000..4b8e8145 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial.html
@@ -0,0 +1,32 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter raise initial</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#raise-initial"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<link rel="match" href="initial-letter-raise-initial-ref.html"> +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + .initial-letter::first-letter { + initial-letter: 3 raise; + color: lime; + font-size: 100px; /* should be ignored in rendering */ + line-height: 50px; /* should be ignored in rendering */ + } +</style> +</head> +<body> +<div class="sample initial-letter"> +Abc<br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raised-sunken-caps-raise-ref.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raised-sunken-caps-raise-ref.html new file mode 100644 index 0000000..3585854 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raised-sunken-caps-raise-ref.html
@@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter raise initial should not overlap with previous line.</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#raised-sunken-caps"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + .fake-initial-letter { + background: lime; + float: left; + height: 80px; + margin-top: 14px; + width: 80px; + } +</style> +</head> +<body> +<div>This line before initial letter.</div> +<div class="sample"> +<div class="fake-initial-letter"></div><br><br><br> +bc<br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raised-sunken-caps-raise.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raised-sunken-caps-raise.html new file mode 100644 index 0000000..4e90667 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raised-sunken-caps-raise.html
@@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter raise initial should not overlap with previous line.</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#raised-sunken-caps"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<link rel="match" href="initial-letter-raised-sunken-caps-raise-ref.html"> +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + .initial-letter::first-letter { + initial-letter: 3 raise; + color: lime; + font-size: 100px; /* should be ignored in rendering */ + line-height: 50px; /* should be ignored in rendering */ + } +</style> +</head> +<body> +<div>This line before initial letter.</div> +<div class="sample initial-letter"> +Abc<br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raised-sunken-caps-sunken-ref.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raised-sunken-caps-sunken-ref.html new file mode 100644 index 0000000..a70288d --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raised-sunken-caps-sunken-ref.html
@@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter sunken initial should not overlap with previous line.</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#raised-sunken-caps"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + .fake-initial-letter { + background: lime; + float: left; + height: 80px; + margin-top: 14px; + width: 80px; + } +</style> +</head> +<body> +<div>This line before initial letter.</div> +<div class="sample"> +<div class="fake-initial-letter"></div><br><br> +bc<br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raised-sunken-caps-sunken.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raised-sunken-caps-sunken.html new file mode 100644 index 0000000..add9030 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raised-sunken-caps-sunken.html
@@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter sunken initial should not overlap with previous line.</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#raised-sunken-caps"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<link rel="match" href="initial-letter-raised-sunken-caps-sunken-ref.html"> +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + .initial-letter::first-letter { + initial-letter: 3 2; + color: lime; + font-size: 100px; /* should be ignored in rendering */ + line-height: 50px; /* should be ignored in rendering */ + } +</style> +</head> +<body> +<div>This line before initial letter.</div> +<div class="sample initial-letter"> +Abc<br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-short-para-initial-letter-clears-ref.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-short-para-initial-letter-clears-ref.html new file mode 100644 index 0000000..8f96d66 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-short-para-initial-letter-clears-ref.html
@@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter subsequent paragraph clears initial letter.</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#short-para-initial-letter"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + .fake-initial-letter { + background: lime; + float: left; + height: 80px; + margin-top: 14px; + width: 80px; + } +</style> +</head> +<body> +<div class="sample"><div class="fake-initial-letter"></div>bc<br>Def<br></div> +<div class="sample" style="padding-top:44px"><div class="fake-initial-letter"></div>XY<br>ABC<br></div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-short-para-initial-letter-clears.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-short-para-initial-letter-clears.html new file mode 100644 index 0000000..92d0756a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-short-para-initial-letter-clears.html
@@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter subsequent paragraph clears initial letter.</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#short-para-initial-letter"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<link rel="match" href="initial-letter-short-para-initial-letter-clears-ref.html"> +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + .initial-letter::first-letter { + initial-letter: 3 drop; + color: lime; + font-size: 100px; /* should be ignored in rendering */ + line-height: 50px; /* should be ignored in rendering */ + } +</style> +</head> +<body> +<div class="sample initial-letter">Abc<br>Def<br></div> +<div class="sample initial-letter">WXY<br>ABC</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-short-para-initial-letter-wraps-ref.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-short-para-initial-letter-wraps-ref.html new file mode 100644 index 0000000..2808ba5f --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-short-para-initial-letter-wraps-ref.html
@@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter subsequent paragraph wraps initial letter.</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#short-para-initial-letter"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + .fake-initial-letter { + background: lime; + float: left; + height: 80px; + margin-top: 14px; + width: 80px; + } +</style> +</head> +<body> +<div class="sample"><div class="fake-initial-letter"></div>bc</div> +<div>subsequent paragraph</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-short-para-initial-letter-wraps.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-short-para-initial-letter-wraps.html new file mode 100644 index 0000000..d09be388 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-short-para-initial-letter-wraps.html
@@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter subsequent paragraph wraps initial letter.</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#short-para-initial-letter"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<link rel="match" href="initial-letter-short-para-initial-letter-wraps-ref.html"> +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + .initial-letter::first-letter { + initial-letter: 3 drop; + color: lime; + font-size: 100px; /* should be ignored in rendering */ + line-height: 50px; /* should be ignored in rendering */ + } +</style> +</head> +<body> +<div class="sample initial-letter">Abc</div> +<div>subsequent paragraph</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-sunk-initial-ref.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-sunk-initial-ref.html new file mode 100644 index 0000000..06b9ad9b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-sunk-initial-ref.html
@@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter sunken initial</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#sunk-initial"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + .fake-initial-letter { + background: lime; + float: left; + height: 80px; + margin-top: 14px; + width: 80px; + } +</style> +</head> +<body> +<div class="sample"> +<div class="fake-initial-letter"></div><br><br> +bc<br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-sunk-initial-rtl-ref.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-sunk-initial-rtl-ref.html new file mode 100644 index 0000000..e686e982 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-sunk-initial-rtl-ref.html
@@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter sunk initial in RTL</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#sunk-initial"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<style> + .sample { + border: solid 1px green; + direction: rtl; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + .fake-initial-letter { + background: lime; + float: right; + height: 80px; + margin-top: 14px; + width: 80px; + } +</style> +</head> +<body> +<div class="sample"> +<div class="fake-initial-letter"></div><br><br> +bc<br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-sunk-initial-rtl.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-sunk-initial-rtl.html new file mode 100644 index 0000000..214ee94 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-sunk-initial-rtl.html
@@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter sunk initial in RTL</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#sunk-initial"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<link rel="match" href="initial-letter-sunk-initial-rtl-ref.html"> +<style> + .sample { + border: solid 1px green; + direction: rtl; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + .initial-letter::first-letter { + initial-letter: 3 2; + color: lime; + font-size: 100px; /* should be ignored in rendering */ + line-height: 50px; /* should be ignored in rendering */ + } +</style> +</head> +<body> +<div class="sample initial-letter"> +Abc<br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-sunk-initial-vlr-ref.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-sunk-initial-vlr-ref.html new file mode 100644 index 0000000..c3ccef2 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-sunk-initial-vlr-ref.html
@@ -0,0 +1,47 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter sunk initial in vertical-lr</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#sunk-initial"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + height: 230px; + line-height: 24px; + writing-mode: vertical-lr; + } + + .fake-initial-letter { + background: lime; + display: inline-block; + height: 80px; + margin-left: 8px; + margin-right: 8px; + width: 80px; + } + + .remainder { + display: inline-block; + margin-left: 48px; + margin-top: -20px; + vertical-align: bottom; + } + + .remainder2 { + display: inline-block; + } +</style> +</head> +<body> +<div class="sample"> +<div class="fake-initial-letter"></div> +<div class="remainder">bc<br>def<br></div><br> +<div class="remainder2">ghi<br>jkl<br>mno<br></div> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-sunk-initial-vlr.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-sunk-initial-vlr.html new file mode 100644 index 0000000..a490129 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-sunk-initial-vlr.html
@@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter sunk initial in vertical-lr</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#sunk-initial"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<link rel="match" href="initial-letter-sunk-initial-vlr-ref.html"> +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + height: 230px; + line-height: 24px; + writing-mode: vertical-lr; + } + + .initial-letter::first-letter { + initial-letter: 3 2; + color: lime; + font-size: 100px; /* should be ignored in rendering */ + line-height: 50px; /* should be ignored in rendering */ + } +</style> +</head> +<body> +<div class="sample initial-letter"> +Abc<br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-sunk-initial-vrl-ref.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-sunk-initial-vrl-ref.html new file mode 100644 index 0000000..a7db8b9 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-sunk-initial-vrl-ref.html
@@ -0,0 +1,47 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter sunk initial in vertical-lr</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#sunk-initial"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + height: 230px; + line-height: 24px; + writing-mode: vertical-rl; + } + + .fake-initial-letter { + background: lime; + display: inline-block; + height: 80px; + margin-left: 8px; + margin-right: 8px; + width: 80px; + } + + .remainder { + display: inline-block; + margin-right: 48px; + margin-top: -20px; + vertical-align: top; + } + + .remainder2 { + display: inline-block; + } +</style> +</head> +<body> +<div class="sample"> +<div class="fake-initial-letter"></div> +<div class="remainder">bc<br>def</div><br> +<div class="remainder2">ghi<br>jkl<br>mno<br></div> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-sunk-initial-vrl.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-sunk-initial-vrl.html new file mode 100644 index 0000000..52584a98 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-sunk-initial-vrl.html
@@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter sunk initial in vertical-lr</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#sunk-initial"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<link rel="match" href="initial-letter-sunk-initial-vrl-ref.html"> +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + height: 230px; + line-height: 24px; + writing-mode: vertical-rl; + } + + .initial-letter::first-letter { + initial-letter: 3 2; + color: lime; + font-size: 100px; /* should be ignored in rendering */ + line-height: 50px; /* should be ignored in rendering */ + } +</style> +</head> +<body> +<div class="sample initial-letter"> +Abc<br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-sunk-initial.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-sunk-initial.html new file mode 100644 index 0000000..701469c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-sunk-initial.html
@@ -0,0 +1,32 @@ +<!DOCTYPE html> +<html> +<head> +<title>Tests initial letter sunken initial</title> +<link rel="author" title="Google LLC" href="https://www.google.com/"> +<link rel="help" href="https://drafts.csswg.org/css-inline/#sunk-initial"> +<meta name="flags" content="ahem"> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" > +<link rel="match" href="initial-letter-sunk-initial-ref.html"> +<style> + .sample { + border: solid 1px green; + font-family: Ahem; + font-size: 20px; + line-height: 24px; + width: 230px; + } + + .initial-letter::first-letter { + initial-letter: 3 2; + color: lime; + font-size: 100px; /* should be ignored in rendering */ + line-height: 50px; /* should be ignored in rendering */ + } +</style> +</head> +<body> +<div class="sample initial-letter"> +Abc<br>def<br>ghi<br>jkl<br>mno<br> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/range-input-appearance-native-horizontal-rtl.optional.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/range-input-appearance-native-horizontal-rtl.optional.html new file mode 100644 index 0000000..9382f89 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/range-input-appearance-native-horizontal-rtl.optional.html
@@ -0,0 +1,12 @@ +<!DOCTYPE html> +<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m"> +<link rel="help" href="https://html.spec.whatwg.org/#range-state-(type=range)"> +<link rel="help" href="https://drafts.csswg.org/css-writing-modes-4/#block-flow"> +<title>native input[type=range] in horizontal writing mode & RTL direction</title> +<meta charset="utf-8"> +<link rel="mismatch" href="range-input-appearance-native-horizontal.optional.html"> +<link rel="mismatch" href="range-input-appearance-none-horizontal.optional.html"> + +<!-- Note test description should be the same across all files to mismatch on. --> +<p>The range input below should match the correct writing mode & direction.</p> +<input type="range" min="0" max="100" value="10" style="direction: rtl">
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/range-input-appearance-native-horizontal.optional.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/range-input-appearance-native-horizontal.optional.html new file mode 100644 index 0000000..1651d83 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/range-input-appearance-native-horizontal.optional.html
@@ -0,0 +1,12 @@ +<!DOCTYPE html> +<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m"> +<link rel="help" href="https://html.spec.whatwg.org/#range-state-(type=range)"> +<link rel="help" href="https://drafts.csswg.org/css-writing-modes-4/#block-flow"> +<title>native input[type=range] in horizontal writing mode</title> +<meta charset="utf-8"> +<link rel="mismatch" href="range-input-appearance-native-vertical.optional.html"> +<link rel="mismatch" href="range-input-appearance-none-vertical.optional.html"> + +<!-- Note test description should be the same across all files to mismatch on. --> +<p>The range input below should match the correct writing mode & direction.</p> +<input type="range" min="0" max="100" value="10">
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/range-input-appearance-native-vertical-rtl.optional.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/range-input-appearance-native-vertical-rtl.optional.html new file mode 100644 index 0000000..74b24b5 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/range-input-appearance-native-vertical-rtl.optional.html
@@ -0,0 +1,12 @@ +<!DOCTYPE html> +<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m"> +<link rel="help" href="https://html.spec.whatwg.org/#range-state-(type=range)"> +<link rel="help" href="https://drafts.csswg.org/css-writing-modes-4/#block-flow"> +<title>native input[type=range] in vertical writing mode & RTL direction</title> +<meta charset="utf-8"> +<link rel="mismatch" href="range-input-appearance-native-vertical.optional.html"> +<link rel="mismatch" href="range-input-appearance-none-vertical.optional.html"> + +<!-- Note test description should be the same across all files to mismatch on. --> +<p>The range input below should match the correct writing mode & direction.</p> +<input type="range" min="0" max="100" value="10" style="writing-mode: vertical-rl; direction: rtl;">
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/range-input-appearance-native-vertical.optional.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/range-input-appearance-native-vertical.optional.html new file mode 100644 index 0000000..ca7eb99 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/range-input-appearance-native-vertical.optional.html
@@ -0,0 +1,12 @@ +<!DOCTYPE html> +<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m"> +<link rel="help" href="https://html.spec.whatwg.org/#range-state-(type=range)"> +<link rel="help" href="https://drafts.csswg.org/css-writing-modes-4/#block-flow"> +<title>native input[type=range] in vertical writing mode</title> +<meta charset="utf-8"> +<link rel="mismatch" href="range-input-appearance-native-horizontal.optional.html"> +<link rel="mismatch" href="range-input-appearance-none-horizontal.optional.html"> + +<!-- Note test description should be the same across all files to mismatch on. --> +<p>The range input below should match the correct writing mode & direction.</p> +<input type="range" min="0" max="100" value="10" style="writing-mode: vertical-rl">
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/range-input-appearance-none-horizontal-rtl.optional.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/range-input-appearance-none-horizontal-rtl.optional.html new file mode 100644 index 0000000..c148568 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/range-input-appearance-none-horizontal-rtl.optional.html
@@ -0,0 +1,12 @@ +<!DOCTYPE html> +<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m"> +<link rel="help" href="https://html.spec.whatwg.org/#range-state-(type=range)"> +<link rel="help" href="https://drafts.csswg.org/css-writing-modes-4/#block-flow"> +<title>unstyled input[type=range] in horizontal writing mode & RTL direction</title> +<meta charset="utf-8"> +<link rel="mismatch" href="range-input-appearance-none-horizontal.optional.html"> +<link rel="mismatch" href="range-input-appearance-native-horizontal.optional.html"> + +<!-- Note test description should be the same across all files to mismatch on. --> +<p>The range input below should match the correct writing mode & direction.</p> +<input type="range" min="0" max="100" value="10" style="direction: rtl; appearance: none;">
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/range-input-appearance-none-horizontal.optional.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/range-input-appearance-none-horizontal.optional.html new file mode 100644 index 0000000..1f4bfe4 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/range-input-appearance-none-horizontal.optional.html
@@ -0,0 +1,12 @@ +<!DOCTYPE html> +<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m"> +<link rel="help" href="https://html.spec.whatwg.org/#range-state-(type=range)"> +<link rel="help" href="https://drafts.csswg.org/css-writing-modes-4/#block-flow"> +<title>unstyled input[type=range] in horizontal writing mode</title> +<meta charset="utf-8"> +<link rel="mismatch" href="range-input-appearance-none-vertical.optional.html"> +<link rel="mismatch" href="range-input-appearance-native-vertical.optional.html"> + +<!-- Note test description should be the same across all files to mismatch on. --> +<p>The range input below should match the correct writing mode & direction.</p> +<input type="range" min="0" max="100" value="10" style="appearance: none;">
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/range-input-appearance-none-vertical-rtl.optional.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/range-input-appearance-none-vertical-rtl.optional.html new file mode 100644 index 0000000..a4696e4 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/range-input-appearance-none-vertical-rtl.optional.html
@@ -0,0 +1,12 @@ +<!DOCTYPE html> +<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m"> +<link rel="help" href="https://html.spec.whatwg.org/#range-state-(type=range)"> +<link rel="help" href="https://drafts.csswg.org/css-writing-modes-4/#block-flow"> +<title>unstyled input[type=range] in vertical writing mode & RTL direction</title> +<meta charset="utf-8"> +<link rel="mismatch" href="range-input-appearance-none-vertical.optional.html"> +<link rel="mismatch" href="range-input-appearance-native-vertical.optional.html"> + +<!-- Note test description should be the same across all files to mismatch on. --> +<p>The range input below should match the correct writing mode & direction.</p> +<input type="range" min="0" max="100" value="10" style="writing-mode: vertical-lr; direction: rtl; appearance: none;">
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/range-input-appearance-none-vertical.optional.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/range-input-appearance-none-vertical.optional.html new file mode 100644 index 0000000..9c151c6 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/range-input-appearance-none-vertical.optional.html
@@ -0,0 +1,12 @@ +<!DOCTYPE html> +<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m"> +<link rel="help" href="https://html.spec.whatwg.org/#range-state-(type=range)"> +<link rel="help" href="https://drafts.csswg.org/css-writing-modes-4/#block-flow"> +<title>unstyled input[type=range] in vertical writing mode</title> +<meta charset="utf-8"> +<link rel="mismatch" href="range-input-appearance-none-horizontal.optional.html"> +<link rel="mismatch" href="range-input-appearance-native-horizontal.optional.html"> + +<!-- Note test description should be the same across all files to mismatch on. --> +<p>The range input below should match the correct writing mode & direction.</p> +<input type="range" min="0" max="100" value="10" style="writing-mode: vertical-lr; appearance: none;">
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/select-multiple-appearance-native-horizontal.optional.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/select-multiple-appearance-native-horizontal.optional.html new file mode 100644 index 0000000..57b84109 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/select-multiple-appearance-native-horizontal.optional.html
@@ -0,0 +1,115 @@ +<!DOCTYPE html> +<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m"> +<link rel="help" href="https://html.spec.whatwg.org/#the-select-element"> +<link rel="help" href="https://drafts.csswg.org/css-writing-modes-4/#block-flow"> +<title>native select[multiple] in horizontal writing mode</title> +<meta charset="utf-8"> +<link rel="mismatch" href="select-multiple-appearance-native-vlr.optional.html"> +<link rel="mismatch" href="select-multiple-appearance-none-vlr.optional.html"> +<link rel="mismatch" href="select-multiple-appearance-native-vrl.optional.html"> +<link rel="mismatch" href="select-multiple-appearance-none-vrl.optional.html"> + +<!-- Note test description should be the same across all files to mismatch on. --> +<p>The select below should match the correct writing mode.</p> +<select multiple> + <option>Option 1</option> + <option>Option 2</option> + <option>Option 3</option> + <option>Option 4</option> + <option>Option 5</option> + <option>Option 6</option> + <option>Option 7</option> + <option>Option 8</option> + <option>Option 9</option> + <option>Option 10</option> + <option>Option 11</option> + <option>Option 12</option> + <option>Option 13</option> + <option>Option 14</option> + <option>Option 15</option> + <option>Option 16</option> + <option>Option 17</option> + <option>Option 18</option> + <option>Option 19</option> + <option>Option 20</option> + <option>Option 21</option> + <option>Option 22</option> + <option>Option 23</option> + <option>Option 24</option> + <option>Option 25</option> + <option>Option 26</option> + <option>Option 27</option> + <option>Option 28</option> + <option>Option 29</option> + <option>Option 30</option> + <option>Option 31</option> + <option>Option 32</option> + <option>Option 33</option> + <option>Option 34</option> + <option>Option 35</option> + <option>Option 36</option> + <option>Option 37</option> + <option>Option 38</option> + <option>Option 39</option> + <option>Option 40</option> + <option>Option 41</option> + <option>Option 42</option> + <option>Option 43</option> + <option>Option 44</option> + <option>Option 45</option> + <option>Option 46</option> + <option>Option 47</option> + <option>Option 48</option> + <option>Option 49</option> + <option>Option 50</option> + <option>Option 51</option> + <option>Option 52</option> + <option>Option 53</option> + <option>Option 54</option> + <option>Option 55</option> + <option>Option 56</option> + <option>Option 57</option> + <option>Option 58</option> + <option>Option 59</option> + <option>Option 60</option> + <option>Option 61</option> + <option>Option 62</option> + <option>Option 63</option> + <option>Option 64</option> + <option>Option 65</option> + <option>Option 66</option> + <option>Option 67</option> + <option>Option 68</option> + <option>Option 69</option> + <option>Option 70</option> + <option>Option 71</option> + <option>Option 72</option> + <option>Option 73</option> + <option>Option 74</option> + <option>Option 75</option> + <option>Option 76</option> + <option>Option 77</option> + <option>Option 78</option> + <option>Option 79</option> + <option>Option 80</option> + <option>Option 81</option> + <option>Option 82</option> + <option>Option 83</option> + <option>Option 84</option> + <option>Option 85</option> + <option>Option 86</option> + <option>Option 87</option> + <option>Option 88</option> + <option>Option 89</option> + <option>Option 90</option> + <option>Option 91</option> + <option>Option 92</option> + <option>Option 93</option> + <option>Option 94</option> + <option>Option 95</option> + <option>Option 96</option> + <option>Option 97</option> + <option>Option 98</option> + <option>Option 99</option> + <option>Option 100</option> +</select>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/select-multiple-appearance-native-vlr.optional.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/select-multiple-appearance-native-vlr.optional.html new file mode 100644 index 0000000..dcec498 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/select-multiple-appearance-native-vlr.optional.html
@@ -0,0 +1,115 @@ +<!DOCTYPE html> +<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m"> +<link rel="help" href="https://html.spec.whatwg.org/#the-select-element"> +<link rel="help" href="https://drafts.csswg.org/css-writing-modes-4/#block-flow"> +<title>native select[multiple] in vertical writing mode</title> +<meta charset="utf-8"> +<link rel="mismatch" href="select-multiple-appearance-native-horizontal.optional.html"> +<link rel="mismatch" href="select-multiple-appearance-none-horizontal.optional.html"> +<link rel="mismatch" href="select-multiple-appearance-native-vrl.optional.html"> +<link rel="mismatch" href="select-multiple-appearance-none-vrl.optional.html"> + +<!-- Note test description should be the same across all files to mismatch on. --> +<p>The select below should match the correct writing mode.</p> +<select multiple style="writing-mode: vertical-lr"> + <option>Option 1</option> + <option>Option 2</option> + <option>Option 3</option> + <option>Option 4</option> + <option>Option 5</option> + <option>Option 6</option> + <option>Option 7</option> + <option>Option 8</option> + <option>Option 9</option> + <option>Option 10</option> + <option>Option 11</option> + <option>Option 12</option> + <option>Option 13</option> + <option>Option 14</option> + <option>Option 15</option> + <option>Option 16</option> + <option>Option 17</option> + <option>Option 18</option> + <option>Option 19</option> + <option>Option 20</option> + <option>Option 21</option> + <option>Option 22</option> + <option>Option 23</option> + <option>Option 24</option> + <option>Option 25</option> + <option>Option 26</option> + <option>Option 27</option> + <option>Option 28</option> + <option>Option 29</option> + <option>Option 30</option> + <option>Option 31</option> + <option>Option 32</option> + <option>Option 33</option> + <option>Option 34</option> + <option>Option 35</option> + <option>Option 36</option> + <option>Option 37</option> + <option>Option 38</option> + <option>Option 39</option> + <option>Option 40</option> + <option>Option 41</option> + <option>Option 42</option> + <option>Option 43</option> + <option>Option 44</option> + <option>Option 45</option> + <option>Option 46</option> + <option>Option 47</option> + <option>Option 48</option> + <option>Option 49</option> + <option>Option 50</option> + <option>Option 51</option> + <option>Option 52</option> + <option>Option 53</option> + <option>Option 54</option> + <option>Option 55</option> + <option>Option 56</option> + <option>Option 57</option> + <option>Option 58</option> + <option>Option 59</option> + <option>Option 60</option> + <option>Option 61</option> + <option>Option 62</option> + <option>Option 63</option> + <option>Option 64</option> + <option>Option 65</option> + <option>Option 66</option> + <option>Option 67</option> + <option>Option 68</option> + <option>Option 69</option> + <option>Option 70</option> + <option>Option 71</option> + <option>Option 72</option> + <option>Option 73</option> + <option>Option 74</option> + <option>Option 75</option> + <option>Option 76</option> + <option>Option 77</option> + <option>Option 78</option> + <option>Option 79</option> + <option>Option 80</option> + <option>Option 81</option> + <option>Option 82</option> + <option>Option 83</option> + <option>Option 84</option> + <option>Option 85</option> + <option>Option 86</option> + <option>Option 87</option> + <option>Option 88</option> + <option>Option 89</option> + <option>Option 90</option> + <option>Option 91</option> + <option>Option 92</option> + <option>Option 93</option> + <option>Option 94</option> + <option>Option 95</option> + <option>Option 96</option> + <option>Option 97</option> + <option>Option 98</option> + <option>Option 99</option> + <option>Option 100</option> +</select>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/select-multiple-appearance-native-vrl.optional.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/select-multiple-appearance-native-vrl.optional.html new file mode 100644 index 0000000..bdad9390 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/select-multiple-appearance-native-vrl.optional.html
@@ -0,0 +1,115 @@ +<!DOCTYPE html> +<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m"> +<link rel="help" href="https://html.spec.whatwg.org/#the-select-element"> +<link rel="help" href="https://drafts.csswg.org/css-writing-modes-4/#block-flow"> +<title>native select[multiple] in vertical writing mode</title> +<meta charset="utf-8"> +<link rel="mismatch" href="select-multiple-appearance-native-horizontal.optional.html"> +<link rel="mismatch" href="select-multiple-appearance-none-horizontal.optional.html"> +<link rel="mismatch" href="select-multiple-appearance-native-vlr.optional.html"> +<link rel="mismatch" href="select-multiple-appearance-none-vlr.optional.html"> + +<!-- Note test description should be the same across all files to mismatch on. --> +<p>The select below should match the correct writing mode.</p> +<select multiple style="writing-mode: vertical-rl"> + <option>Option 1</option> + <option>Option 2</option> + <option>Option 3</option> + <option>Option 4</option> + <option>Option 5</option> + <option>Option 6</option> + <option>Option 7</option> + <option>Option 8</option> + <option>Option 9</option> + <option>Option 10</option> + <option>Option 11</option> + <option>Option 12</option> + <option>Option 13</option> + <option>Option 14</option> + <option>Option 15</option> + <option>Option 16</option> + <option>Option 17</option> + <option>Option 18</option> + <option>Option 19</option> + <option>Option 20</option> + <option>Option 21</option> + <option>Option 22</option> + <option>Option 23</option> + <option>Option 24</option> + <option>Option 25</option> + <option>Option 26</option> + <option>Option 27</option> + <option>Option 28</option> + <option>Option 29</option> + <option>Option 30</option> + <option>Option 31</option> + <option>Option 32</option> + <option>Option 33</option> + <option>Option 34</option> + <option>Option 35</option> + <option>Option 36</option> + <option>Option 37</option> + <option>Option 38</option> + <option>Option 39</option> + <option>Option 40</option> + <option>Option 41</option> + <option>Option 42</option> + <option>Option 43</option> + <option>Option 44</option> + <option>Option 45</option> + <option>Option 46</option> + <option>Option 47</option> + <option>Option 48</option> + <option>Option 49</option> + <option>Option 50</option> + <option>Option 51</option> + <option>Option 52</option> + <option>Option 53</option> + <option>Option 54</option> + <option>Option 55</option> + <option>Option 56</option> + <option>Option 57</option> + <option>Option 58</option> + <option>Option 59</option> + <option>Option 60</option> + <option>Option 61</option> + <option>Option 62</option> + <option>Option 63</option> + <option>Option 64</option> + <option>Option 65</option> + <option>Option 66</option> + <option>Option 67</option> + <option>Option 68</option> + <option>Option 69</option> + <option>Option 70</option> + <option>Option 71</option> + <option>Option 72</option> + <option>Option 73</option> + <option>Option 74</option> + <option>Option 75</option> + <option>Option 76</option> + <option>Option 77</option> + <option>Option 78</option> + <option>Option 79</option> + <option>Option 80</option> + <option>Option 81</option> + <option>Option 82</option> + <option>Option 83</option> + <option>Option 84</option> + <option>Option 85</option> + <option>Option 86</option> + <option>Option 87</option> + <option>Option 88</option> + <option>Option 89</option> + <option>Option 90</option> + <option>Option 91</option> + <option>Option 92</option> + <option>Option 93</option> + <option>Option 94</option> + <option>Option 95</option> + <option>Option 96</option> + <option>Option 97</option> + <option>Option 98</option> + <option>Option 99</option> + <option>Option 100</option> +</select>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/select-multiple-appearance-none-horizontal.optional.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/select-multiple-appearance-none-horizontal.optional.html new file mode 100644 index 0000000..784451c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/select-multiple-appearance-none-horizontal.optional.html
@@ -0,0 +1,115 @@ +<!DOCTYPE html> +<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m"> +<link rel="help" href="https://html.spec.whatwg.org/#the-select-element"> +<link rel="help" href="https://drafts.csswg.org/css-writing-modes-4/#block-flow"> +<title>unstyled select[multiple] in horizontal writing mode</title> +<meta charset="utf-8"> +<link rel="mismatch" href="select-multiple-appearance-none-vlr.optional.html"> +<link rel="mismatch" href="select-multiple-appearance-native-vlr.optional.html"> +<link rel="mismatch" href="select-multiple-appearance-none-vrl.optional.html"> +<link rel="mismatch" href="select-multiple-appearance-native-vrl.optional.html"> + +<!-- Note test description should be the same across all files to mismatch on. --> +<p>The select below should match the correct writing mode.</p> +<select multiple style="appearance: none"> + <option>Option 1</option> + <option>Option 2</option> + <option>Option 3</option> + <option>Option 4</option> + <option>Option 5</option> + <option>Option 6</option> + <option>Option 7</option> + <option>Option 8</option> + <option>Option 9</option> + <option>Option 10</option> + <option>Option 11</option> + <option>Option 12</option> + <option>Option 13</option> + <option>Option 14</option> + <option>Option 15</option> + <option>Option 16</option> + <option>Option 17</option> + <option>Option 18</option> + <option>Option 19</option> + <option>Option 20</option> + <option>Option 21</option> + <option>Option 22</option> + <option>Option 23</option> + <option>Option 24</option> + <option>Option 25</option> + <option>Option 26</option> + <option>Option 27</option> + <option>Option 28</option> + <option>Option 29</option> + <option>Option 30</option> + <option>Option 31</option> + <option>Option 32</option> + <option>Option 33</option> + <option>Option 34</option> + <option>Option 35</option> + <option>Option 36</option> + <option>Option 37</option> + <option>Option 38</option> + <option>Option 39</option> + <option>Option 40</option> + <option>Option 41</option> + <option>Option 42</option> + <option>Option 43</option> + <option>Option 44</option> + <option>Option 45</option> + <option>Option 46</option> + <option>Option 47</option> + <option>Option 48</option> + <option>Option 49</option> + <option>Option 50</option> + <option>Option 51</option> + <option>Option 52</option> + <option>Option 53</option> + <option>Option 54</option> + <option>Option 55</option> + <option>Option 56</option> + <option>Option 57</option> + <option>Option 58</option> + <option>Option 59</option> + <option>Option 60</option> + <option>Option 61</option> + <option>Option 62</option> + <option>Option 63</option> + <option>Option 64</option> + <option>Option 65</option> + <option>Option 66</option> + <option>Option 67</option> + <option>Option 68</option> + <option>Option 69</option> + <option>Option 70</option> + <option>Option 71</option> + <option>Option 72</option> + <option>Option 73</option> + <option>Option 74</option> + <option>Option 75</option> + <option>Option 76</option> + <option>Option 77</option> + <option>Option 78</option> + <option>Option 79</option> + <option>Option 80</option> + <option>Option 81</option> + <option>Option 82</option> + <option>Option 83</option> + <option>Option 84</option> + <option>Option 85</option> + <option>Option 86</option> + <option>Option 87</option> + <option>Option 88</option> + <option>Option 89</option> + <option>Option 90</option> + <option>Option 91</option> + <option>Option 92</option> + <option>Option 93</option> + <option>Option 94</option> + <option>Option 95</option> + <option>Option 96</option> + <option>Option 97</option> + <option>Option 98</option> + <option>Option 99</option> + <option>Option 100</option> +</select>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/select-multiple-appearance-none-vlr.optional.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/select-multiple-appearance-none-vlr.optional.html new file mode 100644 index 0000000..6099eb2 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/select-multiple-appearance-none-vlr.optional.html
@@ -0,0 +1,115 @@ +<!DOCTYPE html> +<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m"> +<link rel="help" href="https://html.spec.whatwg.org/#the-select-element"> +<link rel="help" href="https://drafts.csswg.org/css-writing-modes-4/#block-flow"> +<title>unstyled select[multiple] in vertical writing mode</title> +<meta charset="utf-8"> +<link rel="mismatch" href="select-multiple-appearance-none-horizontal.optional.html"> +<link rel="mismatch" href="select-multiple-appearance-native-horizontal.optional.html"> +<link rel="mismatch" href="select-multiple-appearance-native-vrl.optional.html"> +<link rel="mismatch" href="select-multiple-appearance-none-vrl.optional.html"> + +<!-- Note test description should be the same across all files to mismatch on. --> +<p>The select below should match the correct writing mode.</p> +<select multiple style="writing-mode: vertical-lr; appearance: none"> + <option>Option 1</option> + <option>Option 2</option> + <option>Option 3</option> + <option>Option 4</option> + <option>Option 5</option> + <option>Option 6</option> + <option>Option 7</option> + <option>Option 8</option> + <option>Option 9</option> + <option>Option 10</option> + <option>Option 11</option> + <option>Option 12</option> + <option>Option 13</option> + <option>Option 14</option> + <option>Option 15</option> + <option>Option 16</option> + <option>Option 17</option> + <option>Option 18</option> + <option>Option 19</option> + <option>Option 20</option> + <option>Option 21</option> + <option>Option 22</option> + <option>Option 23</option> + <option>Option 24</option> + <option>Option 25</option> + <option>Option 26</option> + <option>Option 27</option> + <option>Option 28</option> + <option>Option 29</option> + <option>Option 30</option> + <option>Option 31</option> + <option>Option 32</option> + <option>Option 33</option> + <option>Option 34</option> + <option>Option 35</option> + <option>Option 36</option> + <option>Option 37</option> + <option>Option 38</option> + <option>Option 39</option> + <option>Option 40</option> + <option>Option 41</option> + <option>Option 42</option> + <option>Option 43</option> + <option>Option 44</option> + <option>Option 45</option> + <option>Option 46</option> + <option>Option 47</option> + <option>Option 48</option> + <option>Option 49</option> + <option>Option 50</option> + <option>Option 51</option> + <option>Option 52</option> + <option>Option 53</option> + <option>Option 54</option> + <option>Option 55</option> + <option>Option 56</option> + <option>Option 57</option> + <option>Option 58</option> + <option>Option 59</option> + <option>Option 60</option> + <option>Option 61</option> + <option>Option 62</option> + <option>Option 63</option> + <option>Option 64</option> + <option>Option 65</option> + <option>Option 66</option> + <option>Option 67</option> + <option>Option 68</option> + <option>Option 69</option> + <option>Option 70</option> + <option>Option 71</option> + <option>Option 72</option> + <option>Option 73</option> + <option>Option 74</option> + <option>Option 75</option> + <option>Option 76</option> + <option>Option 77</option> + <option>Option 78</option> + <option>Option 79</option> + <option>Option 80</option> + <option>Option 81</option> + <option>Option 82</option> + <option>Option 83</option> + <option>Option 84</option> + <option>Option 85</option> + <option>Option 86</option> + <option>Option 87</option> + <option>Option 88</option> + <option>Option 89</option> + <option>Option 90</option> + <option>Option 91</option> + <option>Option 92</option> + <option>Option 93</option> + <option>Option 94</option> + <option>Option 95</option> + <option>Option 96</option> + <option>Option 97</option> + <option>Option 98</option> + <option>Option 99</option> + <option>Option 100</option> +</select>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/select-multiple-appearance-none-vrl.optional.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/select-multiple-appearance-none-vrl.optional.html new file mode 100644 index 0000000..dfb0269b6 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/select-multiple-appearance-none-vrl.optional.html
@@ -0,0 +1,115 @@ +<!DOCTYPE html> +<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m"> +<link rel="help" href="https://html.spec.whatwg.org/#the-textarea-element"> +<link rel="help" href="https://drafts.csswg.org/css-writing-modes-4/#block-flow"> +<title>unstyled select[multiple] in vertical writing mode</title> +<meta charset="utf-8"> +<link rel="mismatch" href="select-multiple-appearance-none-horizontal.optional.html"> +<link rel="mismatch" href="select-multiple-appearance-native-horizontal.optional.html"> +<link rel="mismatch" href="select-multiple-appearance-none-vlr.optional.html"> +<link rel="mismatch" href="select-multiple-appearance-native-vlr.optional.html"> + +<!-- Note test description should be the same across all files to mismatch on. --> +<p>The select below should match the correct writing mode.</p> +<select multiple style="writing-mode: vertical-rl; appearance: none"> + <option>Option 1</option> + <option>Option 2</option> + <option>Option 3</option> + <option>Option 4</option> + <option>Option 5</option> + <option>Option 6</option> + <option>Option 7</option> + <option>Option 8</option> + <option>Option 9</option> + <option>Option 10</option> + <option>Option 11</option> + <option>Option 12</option> + <option>Option 13</option> + <option>Option 14</option> + <option>Option 15</option> + <option>Option 16</option> + <option>Option 17</option> + <option>Option 18</option> + <option>Option 19</option> + <option>Option 20</option> + <option>Option 21</option> + <option>Option 22</option> + <option>Option 23</option> + <option>Option 24</option> + <option>Option 25</option> + <option>Option 26</option> + <option>Option 27</option> + <option>Option 28</option> + <option>Option 29</option> + <option>Option 30</option> + <option>Option 31</option> + <option>Option 32</option> + <option>Option 33</option> + <option>Option 34</option> + <option>Option 35</option> + <option>Option 36</option> + <option>Option 37</option> + <option>Option 38</option> + <option>Option 39</option> + <option>Option 40</option> + <option>Option 41</option> + <option>Option 42</option> + <option>Option 43</option> + <option>Option 44</option> + <option>Option 45</option> + <option>Option 46</option> + <option>Option 47</option> + <option>Option 48</option> + <option>Option 49</option> + <option>Option 50</option> + <option>Option 51</option> + <option>Option 52</option> + <option>Option 53</option> + <option>Option 54</option> + <option>Option 55</option> + <option>Option 56</option> + <option>Option 57</option> + <option>Option 58</option> + <option>Option 59</option> + <option>Option 60</option> + <option>Option 61</option> + <option>Option 62</option> + <option>Option 63</option> + <option>Option 64</option> + <option>Option 65</option> + <option>Option 66</option> + <option>Option 67</option> + <option>Option 68</option> + <option>Option 69</option> + <option>Option 70</option> + <option>Option 71</option> + <option>Option 72</option> + <option>Option 73</option> + <option>Option 74</option> + <option>Option 75</option> + <option>Option 76</option> + <option>Option 77</option> + <option>Option 78</option> + <option>Option 79</option> + <option>Option 80</option> + <option>Option 81</option> + <option>Option 82</option> + <option>Option 83</option> + <option>Option 84</option> + <option>Option 85</option> + <option>Option 86</option> + <option>Option 87</option> + <option>Option 88</option> + <option>Option 89</option> + <option>Option 90</option> + <option>Option 91</option> + <option>Option 92</option> + <option>Option 93</option> + <option>Option 94</option> + <option>Option 95</option> + <option>Option 96</option> + <option>Option 97</option> + <option>Option 98</option> + <option>Option 99</option> + <option>Option 100</option> +</select>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/select-multiple-scrolling.optional-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/select-multiple-scrolling.optional-expected.txt new file mode 100644 index 0000000..464cdd6 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/select-multiple-scrolling.optional-expected.txt
@@ -0,0 +1,6 @@ +This is a testharness.js-based test. +PASS select[multiple][style="writing-mode: horizontal-tb"] scrolls correctly +FAIL select[multiple][style="writing-mode: vertical-lr"] scrolls correctly assert_true: select should be scrollable in block axis expected true got false +FAIL select[multiple][style="writing-mode: vertical-rl"] scrolls correctly assert_true: select should be scrollable in block axis expected true got false +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/select-multiple-scrolling.optional.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/select-multiple-scrolling.optional.html new file mode 100644 index 0000000..ffaba9f --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/select-multiple-scrolling.optional.html
@@ -0,0 +1,103 @@ +<!doctype html> +<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m"> +<link rel="help" href="https://html.spec.whatwg.org/#the-select-element"> +<link rel="help" href="https://drafts.csswg.org/css-writing-modes-4/#block-flow"> +<link rel="help" href="https://drafts.csswg.org/cssom-view/#scrolling-area"> +<title>Test <select> multiple attribute scroll progression</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<select multiple size="5"></select> +<script> +const select = document.querySelector("select"); +for (let i = 0; i < 100; i++) { + const option = document.createElement("option"); + option.textContent = `Option ${i + 1}`; + select.appendChild(option); +} + +for (const writingMode of ["horizontal-tb", "vertical-lr", "vertical-rl", "sideways-lr", "sideways-rl"]) { + if (!CSS.supports(`writing-mode: ${writingMode}`)) + continue; + + const scrollBlockAxis = (() => { + switch (writingMode) { + case "horizontal-tb": + return "scrollTop"; + case "vertical-lr": + case "sideways-lr": + case "vertical-rl": + case "sideways-rl": + return "scrollLeft"; + } + })(); + const scrollInlineAxis = scrollBlockAxis === "scrollTop" ? "scrollLeft" : "scrollTop"; + + const isHorizontal = writingMode === "horizontal-tb"; + const clientBlock = isHorizontal ? "clientHeight" : "clientWidth"; + const clientInline = isHorizontal ? "clientWidth" : "clientHeight"; + const scrollBlock = isHorizontal ? "scrollHeight" : "scrollWidth"; + const scrollInline = isHorizontal ? "scrollWidth" : "scrollHeight"; + + test(t => { + select.scrollTop = select.scrollLeft = 0; + select.style.writingMode = writingMode; + t.add_cleanup(() => { + select.removeAttribute("style"); + select.scrollTop = select.scrollLeft = 0; + }); + + assert_true( + select[scrollBlock] > select[clientBlock], + "select should be scrollable in block axis" + ); + assert_equals( + select[scrollInline], select[clientInline], + "select should not be scrollable in inline axis" + ); + + assert_equals( + select[scrollBlockAxis], 0, + `scrolling is initially at block start for writing-mode: ${writingMode}` + ); + + const isReversedBlockFlowDirection = writingMode.endsWith("-rl"); + select[scrollBlockAxis] = 100; + if (!isReversedBlockFlowDirection) { + assert_true( + select[scrollBlockAxis] > 0, + `Setting ${scrollBlockAxis} to a positive value of the list works for writing-mode: ${writingMode}` + ); + } else { + assert_equals( + select[scrollBlockAxis], 0, + `Setting ${scrollBlockAxis} to a positive value of the list does not work for writing-mode: ${writingMode}` + ); + } + + select[scrollBlockAxis] = -100; + if (isReversedBlockFlowDirection) { + assert_true( + select[scrollBlockAxis] < 0, + `Setting ${scrollBlockAxis} to a negative value of the list works for writing-mode: ${writingMode}` + ); + } else { + assert_equals( + select[scrollBlockAxis], 0, + `Setting ${scrollBlockAxis} to a negative value of the list does not work for writing-mode: ${writingMode}` + ); + } + + select[scrollInlineAxis] = 100; + assert_equals( + select[scrollInlineAxis], 0, + `setting ${scrollInlineAxis} to a positive value should not scroll for writing-mode: ${writingMode}` + ); + select[scrollInlineAxis] = -100; + assert_equals( + select[scrollInlineAxis], 0, + `setting ${scrollInlineAxis} to a negative value should not scroll for writing-mode: ${writingMode}` + ); + }, `select[multiple][style="writing-mode: ${writingMode}"] scrolls correctly`); +}; +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/select-size-scrolling-and-sizing.optional-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/select-size-scrolling-and-sizing.optional-expected.txt new file mode 100644 index 0000000..c6bc659 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/select-size-scrolling-and-sizing.optional-expected.txt
@@ -0,0 +1,9 @@ +This is a testharness.js-based test. +PASS select[size][style="writing-mode: horizontal-tb"] scrolls correctly +PASS select[size][style="writing-mode: horizontal-tb"] sizing works correctly +FAIL select[size][style="writing-mode: vertical-lr"] scrolls correctly assert_true: select should be scrollable in block axis expected true got false +FAIL select[size][style="writing-mode: vertical-lr"] sizing works correctly assert_true: clientWidth increased when increasing size expected true got false +FAIL select[size][style="writing-mode: vertical-rl"] scrolls correctly assert_true: select should be scrollable in block axis expected true got false +FAIL select[size][style="writing-mode: vertical-rl"] sizing works correctly assert_true: clientWidth increased when increasing size expected true got false +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/select-size-scrolling-and-sizing.optional.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/select-size-scrolling-and-sizing.optional.html new file mode 100644 index 0000000..d70e018d --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/forms/select-size-scrolling-and-sizing.optional.html
@@ -0,0 +1,137 @@ +<!doctype html> +<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m"> +<link rel="help" href="https://html.spec.whatwg.org/#the-select-element"> +<link rel="help" href="https://drafts.csswg.org/css-writing-modes-4/#block-flow"> +<link rel="help" href="https://drafts.csswg.org/cssom-view/#scrolling-area"> +<title>Test <select> size attribute scroll progression and sizing</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<select size="5"></select> +<script> +const select = document.querySelector("select"); +for (let i = 0; i < 100; i++) { + const option = document.createElement("option"); + option.textContent = `Option ${i + 1}`; + select.appendChild(option); +} + +for (const writingMode of ["horizontal-tb", "vertical-lr", "vertical-rl", "sideways-lr", "sideways-rl"]) { + if (!CSS.supports(`writing-mode: ${writingMode}`)) + continue; + + const scrollBlockAxis = (() => { + switch (writingMode) { + case "horizontal-tb": + return "scrollTop"; + case "vertical-lr": + case "sideways-lr": + case "vertical-rl": + case "sideways-rl": + return "scrollLeft"; + } + })(); + const scrollInlineAxis = scrollBlockAxis === "scrollTop" ? "scrollLeft" : "scrollTop"; + + const isHorizontal = writingMode === "horizontal-tb"; + const clientBlock = isHorizontal ? "clientHeight" : "clientWidth"; + const clientInline = isHorizontal ? "clientWidth" : "clientHeight"; + const scrollBlock = isHorizontal ? "scrollHeight" : "scrollWidth"; + const scrollInline = isHorizontal ? "scrollWidth" : "scrollHeight"; + + const select = document.querySelector("select"); + + test(t => { + select.scrollTop = select.scrollLeft = 0; + select.style.writingMode = writingMode; + t.add_cleanup(() => { + select.removeAttribute("style"); + select.scrollTop = select.scrollLeft = 0; + }); + + assert_true( + select[scrollBlock] > select[clientBlock], + "select should be scrollable in block axis" + ); + assert_equals( + select[scrollInline], select[clientInline], + "select should not be scrollable in inline axis" + ); + + assert_equals( + select[scrollBlockAxis], 0, + `scrolling is initially at block start for writing-mode: ${writingMode}` + ); + + const isReversedBlockFlowDirection = writingMode.endsWith("-rl"); + select[scrollBlockAxis] = 100; + if (!isReversedBlockFlowDirection) { + assert_true( + select[scrollBlockAxis] > 0, + `Setting ${scrollBlockAxis} to a positive value of the list works for writing-mode: ${writingMode}` + ); + } else { + assert_equals( + select[scrollBlockAxis], 0, + `Setting ${scrollBlockAxis} to a positive value of the list does not work for writing-mode: ${writingMode}` + ); + } + + select[scrollBlockAxis] = -100; + if (isReversedBlockFlowDirection) { + assert_true( + select[scrollBlockAxis] < 0, + `Setting ${scrollBlockAxis} to a negative value of the list works for writing-mode: ${writingMode}` + ); + } else { + assert_equals( + select[scrollBlockAxis], 0, + `Setting ${scrollBlockAxis} to a negative value of the list does not work for writing-mode: ${writingMode}` + ); + } + + select[scrollInlineAxis] = 100; + assert_equals( + select[scrollInlineAxis], 0, + `setting ${scrollInlineAxis} to a positive value should not scroll for writing-mode: ${writingMode}` + ); + select[scrollInlineAxis] = -100; + assert_equals( + select[scrollInlineAxis], 0, + `setting ${scrollInlineAxis} to a negative value should not scroll for writing-mode: ${writingMode}` + ); + }, `select[size][style="writing-mode: ${writingMode}"] scrolls correctly`); + + test(t => { + select.style.writingMode = writingMode; + t.add_cleanup(() => { + select.removeAttribute("style"); + select.size = 5; + }); + + let prevBlockSize = select[clientBlock]; + let prevInlineSize = select[clientInline]; + select.size = 10; + assert_true( + select[clientBlock] > prevBlockSize, + `${clientBlock} increased when increasing size` + ); + assert_equals( + select[clientInline], prevInlineSize, + `${clientInline} did not change when increasing size` + ); + + prevBlockSize = select[clientBlock]; + prevInlineSize = select[clientInline]; + select.size = 8; + assert_true( + select[clientBlock] < prevBlockSize, + `${clientBlock} decreased when decreasing size` + ); + assert_equals( + select[clientInline], prevInlineSize, + `${clientInline} did not change when decreasing size` + ); + }, `select[size][style="writing-mode: ${writingMode}"] sizing works correctly`); +}; +</script>
diff --git a/third_party/blink/web_tests/external/wpt/resources/declarative-shadow-dom-polyfill.js b/third_party/blink/web_tests/external/wpt/resources/declarative-shadow-dom-polyfill.js new file mode 100644 index 0000000..dfb0a1e --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resources/declarative-shadow-dom-polyfill.js
@@ -0,0 +1,16 @@ +/* + * Polyfill for attaching shadow trees for declarative Shadow DOM for implementations that do not support + * declarative Shadow DOM. + * + * root: The root of the subtree to perform the attachments in + */ + +function polyfill_declarative_shadow_dom(root) { + root.querySelectorAll("template[shadowroot]").forEach(template => { + const mode = template.getAttribute("shadowroot"); + const shadowRoot = template.parentNode.attachShadow({ mode }); + shadowRoot.appendChild(template.content); + template.remove(); + polyfill_declarative_shadow_dom(shadowRoot); + }); +}
diff --git a/third_party/blink/web_tests/external/wpt/shadow-dom/focus-navigation/resources/shadow-dom.js b/third_party/blink/web_tests/external/wpt/shadow-dom/focus-navigation/resources/shadow-dom.js index 442fde2..83dfc0d6 100644 --- a/third_party/blink/web_tests/external/wpt/shadow-dom/focus-navigation/resources/shadow-dom.js +++ b/third_party/blink/web_tests/external/wpt/shadow-dom/focus-navigation/resources/shadow-dom.js
@@ -25,7 +25,7 @@ var parent = template.parentNode; parent.removeChild(template); var shadowRoot; - if (!mode || mode == 'v0') { + if (!mode) { shadowRoot = parent.attachShadow({ mode: 'open' }); } else { shadowRoot = @@ -83,10 +83,7 @@ let parent = template.parentNode; parent.removeChild(template); let shadowRoot; - if (template.getAttribute('data-mode') === 'v0') { - // For legacy Shadow DOM - shadowRoot = parent.attachShadow({ mode: 'open' }); - } else if (template.getAttribute('data-slot-assignment') === 'manual') { + if (template.getAttribute('data-slot-assignment') === 'manual') { shadowRoot = parent.attachShadow({ mode: template.getAttribute('data-mode'),
diff --git a/third_party/blink/web_tests/external/wpt/soft-navigation-heuristics/navigation-api-hash.tentative.html b/third_party/blink/web_tests/external/wpt/soft-navigation-heuristics/navigation-api-hash.tentative.html index 3f2464cc..a63b177a 100644 --- a/third_party/blink/web_tests/external/wpt/soft-navigation-heuristics/navigation-api-hash.tentative.html +++ b/third_party/blink/web_tests/external/wpt/soft-navigation-heuristics/navigation-api-hash.tentative.html
@@ -16,6 +16,7 @@ <script> const link = document.getElementById("link"); testNavigationApi("Test soft navigation with the Navigation API", e => { + timestamps[counter]["eventStart"] = performance.now(); e.intercept({handler: async () => { await addImageToMain(); main.appendChild(img);
diff --git a/third_party/blink/web_tests/external/wpt/soft-navigation-heuristics/navigation-api-rejected.tentative.html b/third_party/blink/web_tests/external/wpt/soft-navigation-heuristics/navigation-api-rejected.tentative.html index c5bdbcc9..bcc0451d 100644 --- a/third_party/blink/web_tests/external/wpt/soft-navigation-heuristics/navigation-api-rejected.tentative.html +++ b/third_party/blink/web_tests/external/wpt/soft-navigation-heuristics/navigation-api-rejected.tentative.html
@@ -16,6 +16,7 @@ <script> const link = document.getElementById("link"); testNavigationApi("Test intercepted and rejected navigate event", e => { + timestamps[counter]["eventStart"] = performance.now(); e.intercept({handler: async () => { await addImageToMain(); throw new Error("This navigation handler rejected");
diff --git a/third_party/blink/web_tests/external/wpt/soft-navigation-heuristics/navigation-api.tentative.html b/third_party/blink/web_tests/external/wpt/soft-navigation-heuristics/navigation-api.tentative.html index e434340a..c4f2786c 100644 --- a/third_party/blink/web_tests/external/wpt/soft-navigation-heuristics/navigation-api.tentative.html +++ b/third_party/blink/web_tests/external/wpt/soft-navigation-heuristics/navigation-api.tentative.html
@@ -16,6 +16,7 @@ <script> const link = document.getElementById("link"); testNavigationApi("Test soft navigation with the Navigation API", e => { + timestamps[counter]["eventStart"] = performance.now(); e.intercept({handler: async () => { await addImageToMain(); main.appendChild(img);
diff --git a/third_party/blink/web_tests/external/wpt/soft-navigation-heuristics/resources/soft-navigation-helper.js b/third_party/blink/web_tests/external/wpt/soft-navigation-heuristics/resources/soft-navigation-helper.js index ccfec71..a24fe22 100644 --- a/third_party/blink/web_tests/external/wpt/soft-navigation-heuristics/resources/soft-navigation-helper.js +++ b/third_party/blink/web_tests/external/wpt/soft-navigation-heuristics/resources/soft-navigation-helper.js
@@ -44,15 +44,7 @@ const testNavigationApi = (testName, navigateEventHandler, link) => { promise_test(async t => { const preClickLcp = await getLcpEntries(); - const eventHandlerWrapper = async e => { - const localCounter = counter; - timestamps[localCounter]["eventStart"] = performance.now(); - navigateEventHandler(e); - await new Promise(r => t.step_timeout(r, 10)); - timestamps[localCounter]["eventEnd"] = performance.now(); - }; - - navigation.addEventListener('navigate', eventHandlerWrapper); + navigation.addEventListener('navigate', navigateEventHandler); click(link); await new Promise(resolve => { (new PerformanceObserver(() => resolve())).observe({ @@ -115,8 +107,7 @@ const setEvent = (t, button, pushState, addContent, pushUrl, eventType) => { const eventObject = (eventType == "click") ? button : window; eventObject.addEventListener(eventType, async e => { - const localCounter = counter; - timestamps[localCounter]["eventStart"] = performance.now(); + timestamps[counter]["eventStart"] = performance.now(); // Jump through a task, to ensure task tracking is working properly. await new Promise(r => t.step_timeout(r, 0)); @@ -134,7 +125,6 @@ await new Promise(r => t.step_timeout(r, 10)); await addContent(url); - timestamps[localCounter]["eventEnd"] = performance.now(); ++counter; clicked = true; @@ -157,13 +147,10 @@ assert_true(entry.name.includes(pushUrl ? URL : document.location.href), "The soft navigation name is properly set"); const entryTimestamp = entry.startTime; - - assert_greater_than_equal(entryTimestamp, timestamps[i]["syncPostClick"], - "Entry timestamp is greater than (or equals) the click timestamp"); - assert_less_than_equal(entryTimestamp, timestamps[i]["eventStart"], - "Entry timestamp is lower than (or equals) the event handler start"); - assert_less_than(entryTimestamp, timestamps[i]["eventEnd"], "eventEnd", - "Entry timestamp is strictly lower than the event handler end"); + assert_less_than_equal(timestamps[i]["syncPostClick"], entryTimestamp); + assert_greater_than_equal( + timestamps[i]['eventStart'], entryTimestamp, + 'Event start timestamp matches'); assert_not_equals(entry.navigationId, performance.getEntriesByType("navigation")[0].navigationId, "The navigation ID was incremented");
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/background-services/background-services-event-includes-storage-key-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/background-services/background-services-event-includes-storage-key-expected.txt new file mode 100644 index 0000000..0b20787 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/background-services/background-services-event-includes-storage-key-expected.txt
@@ -0,0 +1,5 @@ +Tests that background service events are reported with storage key. + +Perform background fetch: +background service event received with storage key: true +
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/background-services/background-services-event-includes-storage-key.js b/third_party/blink/web_tests/http/tests/inspector-protocol/background-services/background-services-event-includes-storage-key.js new file mode 100644 index 0000000..2f2a49fd62 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/background-services/background-services-event-includes-storage-key.js
@@ -0,0 +1,38 @@ +async function setUp(dp) { + // Grant permission to register Background Fetch event. + await dp.Browser.grantPermissions({ + origin: location.origin, + permissions: ['backgroundFetch'], + }); + + await dp.BackgroundService.startObserving({service: 'backgroundFetch'}); + dp.BackgroundService.setRecording( + {shouldRecord: true, service: 'backgroundFetch'}); + await dp.BackgroundService.onceRecordingStateChanged(); +} + +async function tearDown(dp) { + dp.BackgroundService.setRecording( + {shouldRecord: false, service: 'backgroundFetch'}); + await dp.BackgroundService.onceRecordingStateChanged(); +} + +(async function(testRunner) { + var {session, dp} = await testRunner.startURL( + 'resources/background-services.html', + `Tests that background service events are reported with storage key.\n`); + + await session.evaluateAsync('installSW()'); + await setUp(dp); + + testRunner.log('Perform background fetch:'); + session.evaluate( + `sw.backgroundFetch.fetch('my-fetch-success', 'background-fetch.txt')`); + const eventReceived = + await dp.BackgroundService.onceBackgroundServiceEventReceived(); + testRunner.log(`background service event received with storage key: ${ + eventReceived.params.backgroundServiceEvent.storageKey ? true : false}`); + + await tearDown(dp); + testRunner.completeTest(); +});
diff --git a/third_party/blink/web_tests/platform/linux/virtual/oopr-canvas2d/fast/canvas/canvas-ellipse-zero-lineto-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/oopr-canvas2d/fast/canvas/canvas-ellipse-zero-lineto-expected.txt new file mode 100644 index 0000000..faf194d --- /dev/null +++ b/third_party/blink/web_tests/platform/linux/virtual/oopr-canvas2d/fast/canvas/canvas-ellipse-zero-lineto-expected.txt
@@ -0,0 +1,5 @@ +CONSOLE WARNING: Canvas2D: Multiple readback operations using getImageData are faster with the willReadFrequently attribute set to true. See: https://html.spec.whatwg.org/multipage/canvas.html#concept-canvas-will-read-frequently +This is a testharness.js-based test. +FAIL This tests checks that ellipse can draw lines correctly in edge cases. assert_equals: expected 255 but got 0 +Harness: the test ran to completion. +
diff --git a/third_party/closure_compiler/externs/input_method_private.js b/third_party/closure_compiler/externs/input_method_private.js index 1f9eb261..7a758a68 100644 --- a/third_party/closure_compiler/externs/input_method_private.js +++ b/third_party/closure_compiler/externs/input_method_private.js
@@ -238,13 +238,6 @@ chrome.inputMethodPrivate.finishComposingText = function(parameters, callback) {}; /** - * Fires the input.ime.onMenuItemActivated event. - * @param {string} engineID ID of the engine to use. - * @param {string} name Name of the MenuItem which was activated - */ -chrome.inputMethodPrivate.notifyImeMenuItemActivated = function(engineID, name) {}; - -/** * Shows the input view window. If the input view window is already shown, this * function will do nothing. * @param {function(): void=} callback Called when the operation completes.
diff --git a/third_party/closure_compiler/interfaces/input_method_private_interface.js b/third_party/closure_compiler/interfaces/input_method_private_interface.js index 6f52199..e5bd69c 100644 --- a/third_party/closure_compiler/interfaces/input_method_private_interface.js +++ b/third_party/closure_compiler/interfaces/input_method_private_interface.js
@@ -100,13 +100,6 @@ setSelectionRange: function(parameters, callback) {}, /** - * Fires the input.ime.onMenuItemActivated event. - * @param {string} engineID ID of the engine to use. - * @param {string} name Name of the MenuItem which was activated - */ - notifyImeMenuItemActivated: function(engineID, name) {}, - - /** * Shows the input view window. If the input view window is already shown, * this function will do nothing. * @param {function(): void=} callback Called when the operation completes.
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium index 4f889cb..42d8918e 100644 --- a/third_party/freetype/README.chromium +++ b/third_party/freetype/README.chromium
@@ -1,7 +1,7 @@ Name: FreeType URL: http://www.freetype.org/ -Version: VER-2-12-1-138-g1c44de209 -Revision: 1c44de209cb465d175279dc30cd95f9857f703dd +Version: VER-2-12-1-139-gaca4ec590 +Revision: aca4ec5907e0bfb5bbeb01370257a121f3f47a0f CPEPrefix: cpe:/a:freetype:freetype:2.12.1 License: Custom license "inspired by the BSD, Artistic, and IJG (Independent JPEG Group) licenses"
diff --git a/third_party/ipcz/src/ipcz/driver_memory.cc b/third_party/ipcz/src/ipcz/driver_memory.cc index 6dcf5c4..612eca8 100644 --- a/third_party/ipcz/src/ipcz/driver_memory.cc +++ b/third_party/ipcz/src/ipcz/driver_memory.cc
@@ -54,12 +54,17 @@ } DriverMemoryMapping DriverMemory::Map() { - ABSL_ASSERT(is_valid()); + if (!is_valid()) { + return DriverMemoryMapping(); + } + void* address; IpczDriverHandle mapping_handle; IpczResult result = memory_.driver()->MapSharedMemory( memory_.handle(), 0, nullptr, &address, &mapping_handle); - ABSL_ASSERT(result == IPCZ_RESULT_OK); + if (result != IPCZ_RESULT_OK) { + return DriverMemoryMapping(); + } return DriverMemoryMapping(*memory_.driver(), mapping_handle, address, size_); }
diff --git a/third_party/ipcz/src/ipcz/driver_memory.h b/third_party/ipcz/src/ipcz/driver_memory.h index 2a55699..271117f 100644 --- a/third_party/ipcz/src/ipcz/driver_memory.h +++ b/third_party/ipcz/src/ipcz/driver_memory.h
@@ -44,7 +44,8 @@ DriverMemory Clone(); // Asks the driver to map this memory object into the process's address space - // and returns a scoper to control the mapping's lifetime. + // and returns a scoper to control the mapping's lifetime. Returns an invalid + // mapping if mapping fails or if called on an invalid DriverMemory. DriverMemoryMapping Map(); private:
diff --git a/third_party/ipcz/src/ipcz/driver_memory_mapping.h b/third_party/ipcz/src/ipcz/driver_memory_mapping.h index 94651878..7a4a8f7 100644 --- a/third_party/ipcz/src/ipcz/driver_memory_mapping.h +++ b/third_party/ipcz/src/ipcz/driver_memory_mapping.h
@@ -50,9 +50,9 @@ void Unmap(); IpczDriver driver_; - IpczDriverHandle mapping_; - void* address_; - size_t size_; + IpczDriverHandle mapping_ = IPCZ_INVALID_DRIVER_HANDLE; + void* address_ = nullptr; + size_t size_ = 0; }; } // namespace ipcz
diff --git a/third_party/ipcz/src/ipcz/node_connector.cc b/third_party/ipcz/src/ipcz/node_connector.cc index 41a64de55..88386343 100644 --- a/third_party/ipcz/src/ipcz/node_connector.cc +++ b/third_party/ipcz/src/ipcz/node_connector.cc
@@ -119,9 +119,9 @@ << "name " << connect.params().receiver_name.ToString() << " from broker " << connect.params().broker_name.ToString(); - DriverMemory buffer_memory( - connect.TakeDriverObject(connect.params().buffer)); - if (!buffer_memory.is_valid()) { + DriverMemoryMapping mapping = + DriverMemory(connect.TakeDriverObject(connect.params().buffer)).Map(); + if (!mapping.is_valid()) { return false; } @@ -129,7 +129,7 @@ node_, LinkSide::kB, connect.params().receiver_name, connect.params().broker_name, Node::Type::kBroker, connect.params().protocol_version, transport_, - NodeLinkMemory::Create(node_, buffer_memory.Map())); + NodeLinkMemory::Create(node_, std::move(mapping))); node_->SetAssignedName(connect.params().receiver_name); if ((flags_ & IPCZ_CONNECT_NODE_TO_ALLOCATION_DELEGATE) != 0) { node_->SetAllocationDelegate(new_link); @@ -231,13 +231,17 @@ << connect.params().broker_name.ToString() << " as referred by " << connect.params().referrer_name.ToString(); - DriverMemory broker_buffer( - connect.TakeDriverObject(connect.params().broker_link_buffer)); + DriverMemoryMapping broker_mapping = + DriverMemory( + connect.TakeDriverObject(connect.params().broker_link_buffer)) + .Map(); + DriverMemoryMapping referrer_mapping = + DriverMemory( + connect.TakeDriverObject(connect.params().referrer_link_buffer)) + .Map(); Ref<DriverTransport> referrer_transport = MakeRefCounted<DriverTransport>( connect.TakeDriverObject(connect.params().referrer_link_transport)); - DriverMemory referrer_buffer( - connect.TakeDriverObject(connect.params().referrer_link_buffer)); - if (!broker_buffer.is_valid() || !referrer_buffer.is_valid() || + if (!broker_mapping.is_valid() || !referrer_mapping.is_valid() || !referrer_transport->driver_object().is_valid()) { return false; } @@ -252,7 +256,7 @@ node_, LinkSide::kB, connect.params().name, connect.params().broker_name, Node::Type::kBroker, broker_protocol_version, transport_, - NodeLinkMemory::Create(node_, broker_buffer.Map())); + NodeLinkMemory::Create(node_, std::move(broker_mapping))); node_->SetAssignedName(connect.params().name); if ((flags_ & IPCZ_CONNECT_NODE_TO_ALLOCATION_DELEGATE) != 0) { node_->SetAllocationDelegate(broker_link); @@ -269,7 +273,7 @@ node_, LinkSide::kB, connect.params().name, connect.params().referrer_name, Node::Type::kNormal, referrer_protocol_version, std::move(referrer_transport), - NodeLinkMemory::Create(node_, referrer_buffer.Map())); + NodeLinkMemory::Create(node_, std::move(referrer_mapping))); AcceptConnection({.link = referrer_link, .broker = broker_link}, connect.params().num_initial_portals); @@ -441,13 +445,13 @@ remote_name < local_name_ ? LinkSide::kA : LinkSide::kB; DriverMemory their_memory( connect.TakeDriverObject(connect.params().buffer)); - if (!their_memory.is_valid()) { - return false; - } - DriverMemoryMapping primary_buffer_mapping = this_side.is_side_a() ? std::move(link_memory_allocation_.mapping) : their_memory.Map(); + if (!primary_buffer_mapping.is_valid()) { + return false; + } + Ref<NodeLink> link = NodeLink::CreateActive( node_, this_side, local_name_, remote_name, Node::Type::kBroker, connect.params().protocol_version, transport_,
diff --git a/third_party/ipcz/src/ipcz/node_link.cc b/third_party/ipcz/src/ipcz/node_link.cc index 121bdd1..b122131b 100644 --- a/third_party/ipcz/src/ipcz/node_link.cc +++ b/third_party/ipcz/src/ipcz/node_link.cc
@@ -397,8 +397,9 @@ std::min(msg::kProtocolVersion, accepted.params().protocol_version); auto transport = MakeRefCounted<DriverTransport>( accepted.TakeDriverObject(accepted.params().transport)); - DriverMemory buffer(accepted.TakeDriverObject(accepted.params().buffer)); - if (!transport->driver_object().is_valid() || !buffer.is_valid()) { + DriverMemoryMapping mapping = + DriverMemory(accepted.TakeDriverObject(accepted.params().buffer)).Map(); + if (!transport->driver_object().is_valid() || !mapping.is_valid()) { // Not quite a validation failure if the broker simply failed to allocate // resources for this link. Treat it like a connection failure. callback(/*link=*/nullptr, /*num_initial_portals=*/0); @@ -408,7 +409,7 @@ Ref<NodeLink> link_to_referree = NodeLink::CreateInactive( node_, LinkSide::kA, local_node_name_, accepted.params().name, Node::Type::kNormal, protocol_version, std::move(transport), - NodeLinkMemory::Create(node_, buffer.Map())); + NodeLinkMemory::Create(node_, std::move(mapping))); callback(link_to_referree, accepted.params().num_initial_portals); link_to_referree->Activate(); return true; @@ -449,12 +450,8 @@ return false; } - auto memory = DriverMemory(accept.TakeDriverObject(accept.params().memory)); - if (!memory.is_valid()) { - return false; - } - - auto mapping = memory.Map(); + DriverMemoryMapping mapping = + DriverMemory(accept.TakeDriverObject(accept.params().memory)).Map(); if (!mapping.is_valid()) { return false; } @@ -491,12 +488,13 @@ } bool NodeLink::OnAddBlockBuffer(msg::AddBlockBuffer& add) { - DriverMemory buffer(add.TakeDriverObject(add.params().buffer)); - if (!buffer.is_valid()) { + DriverMemoryMapping mapping = + DriverMemory(add.TakeDriverObject(add.params().buffer)).Map(); + if (!mapping.is_valid()) { return false; } return memory().AddBlockBuffer(add.params().id, add.params().block_size, - buffer.Map()); + std::move(mapping)); } bool NodeLink::OnAcceptParcel(msg::AcceptParcel& accept) {
diff --git a/third_party/ipcz/src/ipcz/node_link_memory.cc b/third_party/ipcz/src/ipcz/node_link_memory.cc index ddbc062..b4715bc 100644 --- a/third_party/ipcz/src/ipcz/node_link_memory.cc +++ b/third_party/ipcz/src/ipcz/node_link_memory.cc
@@ -205,6 +205,10 @@ } DriverMemoryMapping mapping = memory.Map(); + if (!mapping.is_valid()) { + return {}; + } + PrimaryBuffer& primary_buffer = *reinterpret_cast<PrimaryBuffer*>(mapping.bytes().data()); @@ -400,12 +404,12 @@ node_->AllocateSharedMemory( buffer_size, [self = WrapRefCounted(this), block_size, link = std::move(link)](DriverMemory memory) { - if (!memory.is_valid()) { + DriverMemoryMapping mapping = memory.Map(); + if (!mapping.is_valid()) { self->OnCapacityRequestComplete(block_size, false); return; } - DriverMemoryMapping mapping = memory.Map(); BlockAllocator allocator(mapping.bytes(), block_size); allocator.InitializeRegion();
diff --git a/third_party/nearby/README.chromium b/third_party/nearby/README.chromium index 300e8045..5a441b3d 100644 --- a/third_party/nearby/README.chromium +++ b/third_party/nearby/README.chromium
@@ -1,7 +1,7 @@ Name: Nearby Connections Library Short Name: Nearby URL: https://github.com/google/nearby -Version: 8bd3d3458056c59801ecf2d86145844c4137070c +Version: 00b1a1570ef5290394b7e865a67392ae4199f4c4 License: Apache 2.0 License File: LICENSE Security Critical: yes
diff --git a/tools/bisect_test.py b/tools/bisect_test.py index 26ce31c..e004747 100644 --- a/tools/bisect_test.py +++ b/tools/bisect_test.py
@@ -4,6 +4,7 @@ import unittest import subprocess +import sys bisect_builds = __import__('bisect-builds') @@ -76,6 +77,8 @@ self.assertEqual(self.bisect(1, 3, lambda *args: 'b', num_runs=10), (1, 2)) self.assertEqual(FakeProcess.called_num_times, 1) + @unittest.skipIf(sys.platform == 'win32', 'Test fails on Windows due to ' + 'https://crbug.com/1393138') def testBisectAllRunsWhenAllSucceed(self): self.assertEqual(self.bisect(1, 3, lambda *args: 'b', num_runs=10), (1, 2)) self.assertEqual(FakeProcess.called_num_times, 10)
diff --git a/tools/browserbench-webdriver/browserbench.py b/tools/browserbench-webdriver/browserbench.py index b8b0bf8c..5234ae2 100644 --- a/tools/browserbench-webdriver/browserbench.py +++ b/tools/browserbench-webdriver/browserbench.py
@@ -16,6 +16,8 @@ DEFAULT_STP_DRIVER_PATH = '/Applications/Safari Technology Preview.app/Contents/MacOS/safaridriver' +WS_DISPLAY_LIST_PATH = '/Library/Preferences/com.apple.windowserver.displays.plist' + # Maximum number of times the benchmark will be run before giving up. MAX_ATTEMPTS = 6 @@ -30,6 +32,19 @@ self._githash = None self._browser = None self._driver = None + self._is_120 = BrowserBench._IsDisplayRefreshRate120() + + @staticmethod + def _IsDisplayRefreshRate120(): + # The current refresh rate is stored in + # /Library/Preferences/com.apple.windowserver.displays.plist . If it has the + # string Hz = 120 then display is at 120. This likely isn't right if there + # are multiple displays, but it's good enough for the lab where we only + # have devices with a single display. + windowserver_output = subprocess.run(["defaults", "read", + WS_DISPLAY_LIST_PATH], + capture_output=True) + return windowserver_output.stdout.decode('utf-8').find('Hz = 120') != -1 @staticmethod def _CreateChromeDriver(optargs): @@ -184,6 +199,7 @@ 'test': self._name, 'version': self._version, 'browser': self._browser, + 'Refresh Rate': '120' if self._is_120 else '60', }, 'results': self._ConvertMeasurementsToSkiaFormat(measurements), 'links': {
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index d711da4..d3feca0 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -18583,6 +18583,14 @@ </description> </action> +<action name="MobileKeyCommandSearchTabs"> + <owner>lpromero@google.com</owner> + <owner>alionadangla@google.com</owner> + <description> + The user has performed the key command to search a tab in the tab grid. + </description> +</action> + <action name="MobileKeyCommandShowBookmarks"> <owner>lpromero@google.com</owner> <owner>alionadangla@google.com</owner>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index eca78917..41d2ddf 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -35007,7 +35007,8 @@ <int value="1107" label="INPUT_IME_DEACTIVATE"/> <int value="1108" label="ENTERPRISE_PLATFORMKEYS_CHALLENGEMACHINEKEY"/> <int value="1109" label="ENTERPRISE_PLATFORMKEYS_CHALLENGEUSERKEY"/> - <int value="1110" label="INPUTMETHODPRIVATE_NOTIFYIMEMENUITEMACTIVATED"/> + <int value="1110" + label="DELETED_INPUTMETHODPRIVATE_NOTIFYIMEMENUITEMACTIVATED"/> <int value="1111" label="INPUT_IME_SHOWWINDOW"/> <int value="1112" label="INPUT_IME_HIDEWINDOW"/> <int value="1113" label="INPUTMETHODPRIVATE_SHOWINPUTVIEW"/> @@ -89783,8 +89784,10 @@ <enum name="ScreenAILoadLibraryResult"> <int value="0" label="Succeeded to load ScreenAI libraries"/> - <int value="1" label="Failed to load VisualAnnotation library"/> + <int value="1" label="Failed to load VisualAnnotation library (deprecated)"/> <int value="2" label="Failed to load MainContentExtraction library"/> + <int value="3" label="Failed to load Layout Extraction library"/> + <int value="4" label="Failed to load OCR library"/> </enum> <enum name="ScreenRotationAcceleratorAction"> @@ -102590,6 +102593,12 @@ </int> </enum> +<enum name="V8DetailedMemoryMeasurementMode"> + <int value="0" label="Bounded"/> + <int value="1" label="Lazy"/> + <int value="2" label="Eager (for testing only)"/> +</enum> + <enum name="V8ExternalPointerTableCompactionOutcome"> <int value="0" label="kSuccess">Table compaction was successful.</int> <int value="1" label="kPartialSuccess"> @@ -104881,7 +104890,8 @@ <int value="8" label="kValidDataURL"/> <int value="9" label="kValidFileURL"/> <int value="10" label="kValidBlob"/> - <int value="11" label="kValidOtherProtocol"/> + <int value="11" label="kValidChromeExtension"/> + <int value="12" label="kValidOtherProtocol"/> </enum> <enum name="WaylandTimingEvent">
diff --git a/tools/metrics/histograms/metadata/ios/histograms.xml b/tools/metrics/histograms/metadata/ios/histograms.xml index 8538769..e7c98d5 100644 --- a/tools/metrics/histograms/metadata/ios/histograms.xml +++ b/tools/metrics/histograms/metadata/ios/histograms.xml
@@ -956,6 +956,16 @@ </summary> </histogram> +<histogram name="IOS.MainFrameNavigationIsInLockdownMode" enum="Boolean" + expires_after="2023-11-23"> + <owner>ajuma@chromium.org</owner> + <owner>bling-fundamentals@google.com</owner> + <summary> + Records whether Lockdown Mode is enabled for a main-frame navigation action. + This is recorded once for every allowed main-frame navigation action. + </summary> +</histogram> + <histogram name="IOS.MainThreadFreezeDetection.HangWithCleanExit" enum="Boolean" expires_after="2023-09-12"> <owner>justincohen@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/media/histograms.xml b/tools/metrics/histograms/metadata/media/histograms.xml index 82086ec..9cdfec9 100644 --- a/tools/metrics/histograms/metadata/media/histograms.xml +++ b/tools/metrics/histograms/metadata/media/histograms.xml
@@ -3411,10 +3411,10 @@ </histogram> <histogram name="Media.Midi.SendReceiveUsage" enum="MidiSendReceiveUsage" - expires_after="2022-11-30"> + expires_after="2023-06-30"> <owner>hongchan@chromium.org</owner> - <owner>toyoshim@chromium.org</owner> - <owner>midi-dev@chromium.org</owner> + <owner>mjwilson@chromium.org</owner> + <owner>src/third_party/blink/renderer/modules/webaudio/OWNERS</owner> <summary> Reports whether any data was sent or received by a MidiManager. Recorded once per MidiManager instantiation, upon destruction. MidiManager is @@ -3426,10 +3426,10 @@ </histogram> <histogram name="Media.Midi.SysExMessageSizeUpTo1MB" units="bytes" - expires_after="2022-11-30"> + expires_after="2023-06-30"> <owner>hongchan@chromium.org</owner> - <owner>toyoshim@chromium.org</owner> - <owner>midi-dev@chromium.org</owner> + <owner>mjwilson@chromium.org</owner> + <owner>src/third_party/blink/renderer/modules/webaudio/OWNERS</owner> <summary> Reports sysex message size. @@ -3437,10 +3437,10 @@ </summary> </histogram> -<histogram name="Media.Midi.Usage" enum="MidiUsage" expires_after="2022-11-30"> +<histogram name="Media.Midi.Usage" enum="MidiUsage" expires_after="2023-06-30"> <owner>hongchan@chromium.org</owner> - <owner>toyoshim@chromium.org</owner> - <owner>midi-dev@chromium.org</owner> + <owner>mjwilson@chromium.org</owner> + <owner>src/third_party/blink/renderer/modules/webaudio/OWNERS</owner> <summary> The MidiManager instance use count, but this is not intended to understand the real API usage because this can be counted by feature scanning scripts
diff --git a/tools/metrics/histograms/metadata/performance_manager/histograms.xml b/tools/metrics/histograms/metadata/performance_manager/histograms.xml index 431fec5..59aec45 100644 --- a/tools/metrics/histograms/metadata/performance_manager/histograms.xml +++ b/tools/metrics/histograms/metadata/performance_manager/histograms.xml
@@ -28,6 +28,32 @@ </summary> </histogram> +<histogram + name="PerformanceManager.V8DetailedMemory.{Destination}.MeasurementMode" + enum="V8DetailedMemoryMeasurementMode" expires_after="2023-05-23"> + <owner>joenotcharles@chromium.org</owner> + <owner>chrome-catan@google.com</owner> + <summary> + Logged every time V8DetailedMemoryReporter.GetV8MemoryUsage is sent to a + renderer, with the measurement mode. This can be used to find the volume of + measurement requests to track their performance overhead. + + {Destination} + </summary> + <token key="Destination"> + <variant name="AllRenderers" + summary="This metric records measurement requests stemming from + V8DetailedMemoryRequest::StartMeasurement, which are sent to + all renderer processes. Scale all counts by the number of + renderer processes when comparing between subpopulations."/> + <variant name="SingleRenderer" + summary="This metric records measurement requests stemming from + V8DetailedMemoryRequest::StartMeasurementForProcess, which + are sent to a single renderer process. Counts don't need to + be scaled."/> + </token> +</histogram> + </histograms> </histogram-configuration>
diff --git a/tools/metrics/histograms/metadata/platform/histograms.xml b/tools/metrics/histograms/metadata/platform/histograms.xml index 0a7be9b..08c6ee15 100644 --- a/tools/metrics/histograms/metadata/platform/histograms.xml +++ b/tools/metrics/histograms/metadata/platform/histograms.xml
@@ -1640,6 +1640,7 @@ <variant name="TpmManager"/> <variant name="TrunksSend"/> <variant name="U2f"/> + <variant name="Unknown"/> <variant name="Vtpm"/> </token> </histogram> @@ -1659,6 +1660,7 @@ <variant name="TpmManager"/> <variant name="TrunksSend"/> <variant name="U2f"/> + <variant name="Unknown"/> <variant name="Vtpm"/> </token> </histogram>
diff --git a/tools/metrics/histograms/metadata/web_audio/histograms.xml b/tools/metrics/histograms/metadata/web_audio/histograms.xml index 7dc5ba907..69ac1ed 100644 --- a/tools/metrics/histograms/metadata/web_audio/histograms.xml +++ b/tools/metrics/histograms/metadata/web_audio/histograms.xml
@@ -33,7 +33,7 @@ </histogram> <histogram name="WebAudio.AudioBuffer.NumberOfChannels" units="units" - expires_after="2022-12-31"> + expires_after="2023-06-30"> <owner>hongchan@chromium.org</owner> <owner>mjwilson@chromium.org</owner> <owner>src/third_party/blink/renderer/modules/webaudio/OWNERS</owner> @@ -55,7 +55,7 @@ </histogram> <histogram name="WebAudio.AudioBuffer.SampleRateRatio384kHz" units="units" - expires_after="2022-12-31"> + expires_after="2023-06-30"> <owner>hongchan@chromium.org</owner> <owner>mjwilson@chromium.org</owner> <owner>src/third_party/blink/renderer/modules/webaudio/OWNERS</owner> @@ -67,7 +67,7 @@ </histogram> <histogram name="WebAudio.AudioContext.CreateTime" units="ms" - expires_after="2022-12-31"> + expires_after="2023-06-30"> <owner>hongchan@chromium.org</owner> <owner>mjwilson@chromium.org</owner> <owner>cduvall@chromium.org</owner> @@ -184,7 +184,7 @@ </histogram> <histogram name="WebAudio.Autoplay" enum="WebAudioAutoplayStatus" - expires_after="2022-12-31"> + expires_after="2023-06-30"> <owner>hongchan@chromium.org</owner> <owner>mjwilson@chromium.org</owner> <owner>src/third_party/blink/renderer/modules/webaudio/OWNERS</owner> @@ -196,7 +196,7 @@ </histogram> <histogram name="WebAudio.Autoplay.CrossOrigin" enum="WebAudioAutoplayStatus" - expires_after="2022-12-31"> + expires_after="2023-06-30"> <owner>hongchan@chromium.org</owner> <owner>mjwilson@chromium.org</owner> <owner>src/third_party/blink/renderer/modules/webaudio/OWNERS</owner> @@ -207,7 +207,7 @@ </histogram> <histogram name="WebAudio.Autoplay.UnlockType" - enum="WebAudioAutoplayUnlockType" expires_after="2022-12-31"> + enum="WebAudioAutoplayUnlockType" expires_after="2023-06-30"> <owner>hongchan@chromium.org</owner> <owner>mjwilson@chromium.org</owner> <owner>src/third_party/blink/renderer/modules/webaudio/OWNERS</owner> @@ -218,7 +218,7 @@ </histogram> <histogram name="WebAudio.BiquadFilter.Type" enum="BiquadFilterType" - expires_after="2022-12-31"> + expires_after="2023-06-30"> <owner>hongchan@chromium.org</owner> <owner>mjwilson@chromium.org</owner> <owner>src/third_party/blink/renderer/modules/webaudio/OWNERS</owner> @@ -241,7 +241,7 @@ </histogram> <histogram name="WebAudio.IIRFilterNode.Order" units="units" - expires_after="2022-12-31"> + expires_after="2023-06-30"> <owner>hongchan@chromium.org</owner> <owner>mjwilson@chromium.org</owner> <summary> @@ -252,7 +252,7 @@ </histogram> <histogram name="WebAudio.OfflineAudioContext.CreateTime" units="ms" - expires_after="2022-12-31"> + expires_after="2023-06-30"> <owner>hongchan@chromium.org</owner> <owner>mjwilson@chromium.org</owner> <owner>cduvall@chromium.org</owner> @@ -263,7 +263,7 @@ </histogram> <histogram name="WebAudio.PannerNode.PanningModel" enum="PanningModelType" - expires_after="2022-12-31"> + expires_after="2023-06-30"> <owner>hongchan@chromium.org</owner> <owner>mjwilson@chromium.org</owner> <owner>src/third_party/blink/renderer/modules/webaudio/OWNERS</owner>
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py index a92dec4..888e428d 100755 --- a/tools/perf/core/perf_data_generator.py +++ b/tools/perf/core/perf_data_generator.py
@@ -1103,7 +1103,7 @@ 'gpu': '8086:1626', 'os': - 'Mac-12.3', + 'Mac-12.6.1', 'pool': 'chrome.tests.perf', 'synthetic_product_name': @@ -1127,7 +1127,7 @@ 'gpu': '8086:1626', 'os': - 'Mac-10.12.6', + 'Mac-12.6.1', 'pool': 'chrome.tests.perf', 'synthetic_product_name': @@ -1241,7 +1241,7 @@ 'gpu': '1002:6821-4.0.20-3.2.8', 'os': - 'Mac-11.6.1', + 'Mac-12.6.1', 'pool': 'chrome.tests.perf', 'synthetic_product_name': @@ -1265,7 +1265,7 @@ 'gpu': '1002:6821-4.0.20-3.2.8', 'os': - 'Mac-11.6.1', + 'Mac-12.6.1', 'pool': 'chrome.tests.perf', 'synthetic_product_name':
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index b894725..5fbb1522 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,24 +5,24 @@ "full_remote_path": "perfetto-luci-artifacts/v31.0/linux-arm64/trace_processor_shell" }, "win": { - "hash": "0e631c819173c90ff71d71dca4cae4bdaef27ca3", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/13e9b7767befb6c9f3f3957278449891f28146cb/trace_processor_shell.exe" + "hash": "560bd7a695d8638142726a65b5123ad754753b80", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/c194bc190ded8849d9d6be943220c5f8f72cc022/trace_processor_shell.exe" }, "linux_arm": { "hash": "6373f26144aad58f230d11d6a91efda5a09c9873", "full_remote_path": "perfetto-luci-artifacts/v31.0/linux-arm/trace_processor_shell" }, "mac": { - "hash": "941ca66ad7b802091fcd60924eaf83ec7ee5088a", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/cf25b47c405ecca6bc775581f21ba4513e219035/trace_processor_shell" + "hash": "c61cbc4d1ceb2caaf9955c1a7964840f2d6f2d81", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/c194bc190ded8849d9d6be943220c5f8f72cc022/trace_processor_shell" }, "mac_arm64": { "hash": "5f47ee79e59d00bf3889d30ca52315522c158040", "full_remote_path": "perfetto-luci-artifacts/v31.0/mac-arm64/trace_processor_shell" }, "linux": { - "hash": "f040895f799f0d28f966722654952c35a010824e", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/13e9b7767befb6c9f3f3957278449891f28146cb/trace_processor_shell" + "hash": "1852fab01717fef0d88914b065a2721385398103", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/c194bc190ded8849d9d6be943220c5f8f72cc022/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config index dc9e9433..d8b377f 100644 --- a/tools/perf/expectations.config +++ b/tools/perf/expectations.config
@@ -32,6 +32,10 @@ crbug.com/966921 [ android ] blink_perf.layout/line-layout-fit-content-break-word.html [ Skip ] crbug.com/1308931 blink_perf.layout/multicol/tall-content-short-columns.html [ Skip ] +# Benchmark: blink_perf.owp_storage +crbug.com/1393222 [ linux ] blink_perf.owp_storage/blob-perf-ipc.html [ Skip ] +crbug.com/1393222 [ linux ] blink_perf.owp_storage/blob-perf-tiny.html [ Skip ] + # Benchmark: blink_perf.paint crbug.com/574483 [ android-low-end ] blink_perf.paint/* [ Skip ] crbug.com/859979 [ android-webview ] blink_perf.paint/paint-offset-changes.html [ Skip ]
diff --git a/ui/aura/screen_ozone.cc b/ui/aura/screen_ozone.cc index 03c7996..7c0c498b2 100644 --- a/ui/aura/screen_ozone.cc +++ b/ui/aura/screen_ozone.cc
@@ -10,6 +10,7 @@ #include "ui/aura/window.h" #include "ui/aura/window_tree_host.h" #include "ui/display/display.h" +#include "ui/display/tablet_state.h" #include "ui/ozone/public/ozone_platform.h" #include "ui/ozone/public/platform_screen.h" @@ -152,6 +153,11 @@ display::TabletState ScreenOzone::GetTabletState() const { return platform_screen_->GetTabletState(); } + +void ScreenOzone::OverrideTabletStateForTesting( + display::TabletState tablet_state) { + platform_screen_->OnTabletStateChanged(tablet_state); +} #endif gfx::NativeWindow ScreenOzone::GetNativeWindowFromAcceleratedWidget(
diff --git a/ui/aura/screen_ozone.h b/ui/aura/screen_ozone.h index f3ec534..0e0ad353 100644 --- a/ui/aura/screen_ozone.h +++ b/ui/aura/screen_ozone.h
@@ -59,6 +59,8 @@ const gfx::GpuExtraInfo& gpu_extra_info) override; #if BUILDFLAG(IS_CHROMEOS_LACROS) display::TabletState GetTabletState() const override; + void OverrideTabletStateForTesting( + display::TabletState tablet_state) override; #endif // Returns the NativeWindow associated with the AcceleratedWidget.
diff --git a/ui/base/ime/win/tsf_text_store.cc b/ui/base/ime/win/tsf_text_store.cc index 3b38d05..92fec08 100644 --- a/ui/base/ime/win/tsf_text_store.cc +++ b/ui/base/ime/win/tsf_text_store.cc
@@ -13,6 +13,7 @@ #include <algorithm> #include "base/logging.h" +#include "base/strings/string_util.h" #include "base/trace_event/trace_event.h" #include "base/win/scoped_variant.h" #include "ui/base/ime/text_input_client.h" @@ -401,6 +402,18 @@ *rect = display::win::ScreenWin::DIPToScreenRect(window_handle_, result_rect.value()) .ToRECT(); + + // Some IMEs such as Google Japanese Input does not support vertical + // writing text. So we shift the rectangle to the right side in order + // to avoid an IME candidate window over vertical text. + if ((text_input_client_->GetTextInputFlags() & + ui::TEXT_INPUT_FLAG_VERTICAL) && + IsInputProcessorWithoutVerticalWriting()) { + int width = rect->right - rect->left; + rect->left += width; + rect->right += width; + } + *clipped = FALSE; TRACE_EVENT1("ime", "TSFTextStore::GetTextExt", "screen rect", gfx::Rect(*rect).ToString()); @@ -1620,4 +1633,25 @@ return false; } +bool TSFTextStore::IsInputProcessorWithoutVerticalWriting() const { + TF_INPUTPROCESSORPROFILE profile; + if (!SUCCEEDED(input_processor_profile_mgr_->GetActiveProfile( + GUID_TFCAT_TIP_KEYBOARD, &profile))) + return false; + if (profile.dwProfileType != TF_PROFILETYPE_INPUTPROCESSOR) + return false; + Microsoft::WRL::ComPtr<ITfInputProcessorProfiles> profiles; + if (!SUCCEEDED(::CoCreateInstance(CLSID_TF_InputProcessorProfiles, nullptr, + CLSCTX_INPROC_SERVER, + IID_PPV_ARGS(&profiles)))) + return false; + BSTR description = nullptr; + if (!SUCCEEDED(profiles->GetLanguageProfileDescription( + profile.clsid, profile.langid, profile.guidProfile, &description))) + return false; + bool result = base::StartsWith(description, L"Google Japanese Input"); + ::SysFreeString(description); + return result; +} + } // namespace ui
diff --git a/ui/base/ime/win/tsf_text_store.h b/ui/base/ime/win/tsf_text_store.h index 68db955..640fe0d 100644 --- a/ui/base/ime/win/tsf_text_store.h +++ b/ui/base/ime/win/tsf_text_store.h
@@ -321,6 +321,9 @@ // Returns if current input method is an IME. bool IsInputIME() const; + // Returns if the active input processor does not support vertical wrirting. + bool IsInputProcessorWithoutVerticalWriting() const; + // Gets the style information from the display attribute for the actively // composed text. void GetStyle(const TF_DISPLAYATTRIBUTE& attribute, ImeTextSpan* span);
diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc index a2f15fc1..6dd12a54 100644 --- a/ui/compositor/layer.cc +++ b/ui/compositor/layer.cc
@@ -149,7 +149,7 @@ gfx::Vector2dF offset = snapped_offset_from_parent - scaled_offset_from_parent; - offset.Scale(1.f / device_scale_factor); + offset.InvScale(device_scale_factor); // Store key and value information for the cache. offset_ = offset;
diff --git a/ui/display/display.cc b/ui/display/display.cc index 088ec6e..466ef1fd1 100644 --- a/ui/display/display.cc +++ b/ui/display/display.cc
@@ -266,7 +266,7 @@ SetScale(device_scale_factor); gfx::RectF f(bounds_in_pixel); - f.Scale(1.f / device_scale_factor_); + f.InvScale(device_scale_factor_); bounds_ = gfx::ToEnclosedRectIgnoringError(f, kDisplaySizeAllowanceEpsilon); size_in_pixels_ = bounds_in_pixel.size(); UpdateWorkAreaFromInsets(insets);
diff --git a/ui/display/manager/managed_display_info.cc b/ui/display/manager/managed_display_info.cc index 88fa8a0..bba18e5 100644 --- a/ui/display/manager/managed_display_info.cc +++ b/ui/display/manager/managed_display_info.cc
@@ -134,7 +134,7 @@ gfx::Size ManagedDisplayMode::GetSizeInDIP() const { gfx::SizeF size_dip(size_); - size_dip.Scale(1.0f / device_scale_factor_); + size_dip.InvScale(device_scale_factor_); return gfx::ToFlooredSize(size_dip); }
diff --git a/ui/display/screen.h b/ui/display/screen.h index fb589cd5..360a1d2a 100644 --- a/ui/display/screen.h +++ b/ui/display/screen.h
@@ -201,6 +201,14 @@ virtual TabletState GetTabletState() const; #endif +#if BUILDFLAG(IS_CHROMEOS_LACROS) + // Overrides tablet state stored in screen and notifies observers only on + // Lacros side. + // Not that this method may make tablet state out-of-sync with Ash side. + virtual void OverrideTabletStateForTesting( + display::TabletState tablet_state) {} +#endif + protected: void set_shutdown(bool shutdown) { shutdown_ = shutdown; } int64_t display_id_for_new_windows() const {
diff --git a/ui/events/blink/fling_booster_unittest.cc b/ui/events/blink/fling_booster_unittest.cc index 187d17e..8a5356f 100644 --- a/ui/events/blink/fling_booster_unittest.cc +++ b/ui/events/blink/fling_booster_unittest.cc
@@ -81,7 +81,7 @@ Vector2dF DeltaFromVelocity(Vector2dF velocity, base::TimeDelta delta) { float delta_seconds = static_cast<float>(delta.InSecondsF()); Vector2dF out = velocity; - out.Scale(1.f / delta_seconds); + out.InvScale(delta_seconds); return out; }
diff --git a/ui/events/gesture_detection/gesture_provider.cc b/ui/events/gesture_detection/gesture_provider.cc index a664d20..f26af1c 100644 --- a/ui/events/gesture_detection/gesture_provider.cc +++ b/ui/events/gesture_detection/gesture_provider.cc
@@ -800,7 +800,7 @@ float dy = source_pointer_down_event->GetY(source_index) - ev2.GetY(i); delta += SubtractSlopRegion(dx, dy); } - delta.Scale(1.0 / ev2.GetPointerCount()); + delta.InvScale(ev2.GetPointerCount()); return delta; }
diff --git a/ui/file_manager/file_manager/containers/search_container.ts b/ui/file_manager/file_manager/containers/search_container.ts index 251f988..bc60a0a 100644 --- a/ui/file_manager/file_manager/containers/search_container.ts +++ b/ui/file_manager/file_manager/containers/search_container.ts
@@ -114,9 +114,7 @@ this.optionsContainer_ = optionsContainer; this.store_ = getStore(); - if (util.isSearchV2Enabled()) { - this.store_.subscribe(this); - } + this.store_.subscribe(this); this.setupEventHandlers(); } @@ -135,8 +133,8 @@ } /** - * Clears the current search query. If the query changed as a result, it posts - * a query changed event. + * Clears the current search query. If the query was not already empty, it + * closes the search box. */ clear() { const value = this.inputElement_.value; @@ -145,7 +143,6 @@ this.postQueryChangedEvent(); requestAnimationFrame(() => { this.closeSearch(); - this.searchButton_.focus(); }); } } @@ -156,7 +153,7 @@ */ setQuery(query: string) { this.inputElement_.value = query; - this.inputElement_.focus(); + this.openSearch(); } /** @@ -215,10 +212,18 @@ // Bail out early if the search part of the state has not changed. return; } + // Cache the last received search state for future comparisons. this.searchState_ = search; - if (search && search.status) { + if (!search) { + return; + } + const query = search.query; + if (query !== undefined && query !== this.getQuery()) { + this.setQuery(query); + } + if (util.isSearchV2Enabled()) { const status = search.status; - if (status === PropStatus.STARTED && search.query) { + if (status === PropStatus.STARTED && query) { this.showOptions_(); } else if (status === SearchStatus.INACTIVE) { this.hideOptions_(); @@ -362,6 +367,7 @@ }); this.clearButton_.addEventListener('click', () => { this.clear(); + this.searchButton_.focus(); }); // Hide the search if the user clicks outside it and there is no search // query entered. @@ -402,6 +408,7 @@ }, {once: true, passive: true, capture: true}); this.searchWrapper_.classList.add('has-cursor', 'has-text'); this.searchBox_.classList.add('has-cursor', 'has-text'); + this.searchButton_.tabIndex = -1; } } @@ -427,6 +434,7 @@ }, {once: true, passive: true, capture: true}); this.searchWrapper_.classList.remove('has-cursor', 'has-text'); this.searchBox_.classList.remove('has-cursor', 'has-text'); + this.searchButton_.tabIndex = 0; } }
diff --git a/ui/file_manager/file_manager/foreground/css/file_manager.css b/ui/file_manager/file_manager/foreground/css/file_manager.css index 340d4f3..689df7f 100644 --- a/ui/file_manager/file_manager/foreground/css/file_manager.css +++ b/ui/file_manager/file_manager/foreground/css/file_manager.css
@@ -247,12 +247,12 @@ display: block; } -html:not(.col-resize) #directory-tree .tree-item:not([disabled]) +html:not(.col-resize) #directory-tree .tree-item:not([disabled]) > .tree-row:not([active]):not([selected]):hover > .file-row { background-color: var(--cros-ripple-color); } -html.pointer-active #directory-tree .tree-item:not([disabled]) +html.pointer-active #directory-tree .tree-item:not([disabled]) > .tree-row:not([active]):not([selected]) > .file-row:active { background-color: var(--cros-ripple-color); }
diff --git a/ui/file_manager/file_manager/foreground/css/file_manager_gm3.css b/ui/file_manager/file_manager/foreground/css/file_manager_gm3.css index d9d7b89..7e4a42f2 100644 --- a/ui/file_manager/file_manager/foreground/css/file_manager_gm3.css +++ b/ui/file_manager/file_manager/foreground/css/file_manager_gm3.css
@@ -250,12 +250,12 @@ display: block; } -html:not(.col-resize) #directory-tree .tree-item:not([disabled]) +html:not(.col-resize) #directory-tree .tree-item:not([disabled]) > .tree-row:not([active]):not([selected]):hover > .file-row { background-color: var(--cros-ripple-color); } -html.pointer-active #directory-tree .tree-item:not([disabled]) +html.pointer-active #directory-tree .tree-item:not([disabled]) > .tree-row:not([active]):not([selected]) > .file-row:active { background-color: var(--cros-ripple-color); }
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager.js b/ui/file_manager/file_manager/foreground/js/file_manager.js index 2317353..0cc8679 100644 --- a/ui/file_manager/file_manager/foreground/js/file_manager.js +++ b/ui/file_manager/file_manager/foreground/js/file_manager.js
@@ -26,6 +26,8 @@ import {CommandHandlerDeps} from '../../externs/command_handler_deps.js'; import {FakeEntry, FilesAppDirEntry} from '../../externs/files_app_entry_interfaces.js'; import {ForegroundWindow} from '../../externs/foreground_window.js'; +import {PropStatus} from '../../externs/ts/state.js'; +import {searchAction} from '../../state/actions.js'; import {getStore} from '../../state/store.js'; import {ActionsController} from './actions_controller.js'; @@ -1371,7 +1373,8 @@ const searchQuery = this.launchParams_.searchQuery; if (searchQuery) { metrics.startInterval('Load.ProcessInitialSearchQuery'); - this.searchController_.setSearchQuery(searchQuery); + getStore().dispatch( + searchAction({query: searchQuery, status: PropStatus.STARTED})); // Show a spinner, as the crossover search function call could be slow. const hideSpinnerCallback = this.spinnerController_.show(); const queryMatchedDirEntry =
diff --git a/ui/file_manager/file_manager/foreground/js/search_controller.js b/ui/file_manager/file_manager/foreground/js/search_controller.js index 665e1bc..31ec508 100644 --- a/ui/file_manager/file_manager/foreground/js/search_controller.js +++ b/ui/file_manager/file_manager/foreground/js/search_controller.js
@@ -83,7 +83,13 @@ */ clear(opt_event) { this.directoryModel_.clearLastSearchQuery(); - this.searchContainer_.clear(); + // If the call to clear was caused by the startup code we do not clear + // the search container. This is to prevent the search container from + // hiding launch parameter search query. We detect the app start up + // condition by checking that the previous directory entry was not set. + if (opt_event && opt_event.previousDirEntry !== null) { + this.searchContainer_.clear(); + } // Only update visibility if |clear| is called from "directory-changed" // event. if (opt_event) {
diff --git a/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js b/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js index b8ee8938..696d01e9 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js +++ b/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js
@@ -442,8 +442,8 @@ item = DirectoryTree.createDirectoryItem( currentEntry.navigationModel, tree); } else { - item = new SubDirectoryItem(label, currentEntry, this, tree); - item.disabled = !!currentEntry.disabled; + item = new SubDirectoryItem( + label, currentEntry, this, tree, !!currentEntry.disabled); } this.add(item); index++; @@ -469,8 +469,8 @@ item = DirectoryTree.createDirectoryItem( currentEntry.navigationModel, tree); } else { - item = new SubDirectoryItem(label, currentEntry, this, tree); - item.disabled = !!currentEntry.disabled; + item = new SubDirectoryItem( + label, currentEntry, this, tree, !!currentEntry.disabled); } this.addAt(item, index); index++; @@ -644,7 +644,7 @@ * @param {function()=} opt_errorCallback Callback called on error. */ updateSubDirectories(recursive, opt_successCallback, opt_errorCallback) { - if (!this.entry || this.entry.createReader === undefined) { + if (!this.entry || this.disabled || this.entry.createReader === undefined) { opt_errorCallback && opt_errorCallback(); return; } @@ -678,7 +678,7 @@ * @override */ updateExpandIcon() { - if (!this.entry || this.entry.createReader === undefined) { + if (!this.entry || this.disabled || this.entry.createReader === undefined) { this.hasChildren = false; return; } @@ -855,8 +855,10 @@ * @param {DirectoryItem|ShortcutItem|DirectoryTree} parentDirItem * Parent of this item. * @param {DirectoryTree} tree Current tree, which contains this item. + * @param {boolean} disabled Whether this item is disabled. Even if the parent + * is not, the subdirectory can be. */ - constructor(label, dirEntry, parentDirItem, tree) { + constructor(label, dirEntry, parentDirItem, tree, disabled = false) { super(label, tree); this.__proto__ = SubDirectoryItem.prototype; @@ -866,7 +868,7 @@ this.dirEntry_ = dirEntry; this.entry = dirEntry; - this.disabled = parentDirItem.disabled; + this.disabled = disabled; this.delayExpansion = parentDirItem.delayExpansion; if (this.delayExpansion) { @@ -1489,7 +1491,7 @@ * @override */ updateSubDirectories(recursive) { - if (!this.entry || this.hasChildren) { + if (!this.entry || this.hasChildren || this.disabled) { return; }
diff --git a/ui/file_manager/file_manager/foreground/js/ui/directory_tree_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/directory_tree_unittest.js index 1db816f..7c4e6449 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/directory_tree_unittest.js +++ b/ui/file_manager/file_manager/foreground/js/ui/directory_tree_unittest.js
@@ -620,9 +620,10 @@ * Test case for updateSubElementsFromList. * * If some of the volumes under MyFiles are disabled, this should be reflected - * in the directory model as well. + * in the directory model as well: the children shouldn't be loaded, and + * clicking on the item or the expand icon shouldn't do anything. */ -export function testUpdateSubElementsDisabled(callback) { +export async function testUpdateSubElementsAndroidDisabled(done) { const recentItem = null; const shortcutListModel = new MockFolderShortcutDataModel([]); const androidAppListModel = createFakeAndroidAppListModel([]); @@ -651,16 +652,97 @@ directoryTree.updateSubElementsFromList(true); const myFilesItem = directoryTree.items[0]; + await waitUntil(() => myFilesItem.items.length === 1); + const androidItem = /** @type {!SubDirectoryItem} */ (myFilesItem.items[0]); + assertEquals('android_files:droid', androidItem.label); + assertTrue(androidItem.disabled); + assertFalse(androidItem.hasChildren); - reportPromise( - waitUntil(() => { - return myFilesItem.items.length === 1; - }).then(() => { - const subdir = /** @type {!SubDirectoryItem} */ (myFilesItem.items[0]); - assertEquals(subdir.label, 'android_files:droid'); - assertTrue(subdir.disabled); - }), - callback); + // Clicking on the item shouldn't select it. + androidItem.click(); + await new Promise(resolve => requestAnimationFrame(resolve)); + assertFalse(androidItem.selected); + + // The item shouldn't be expanded. + let isExpanded = androidItem.getAttribute('aria-expanded') || 'false'; + assertEquals('false', isExpanded); + // Clicking on the expand icon shouldn't expand. + androidItem.querySelector('.expand-icon').click(); + await new Promise(resolve => requestAnimationFrame(resolve)); + isExpanded = androidItem.getAttribute('aria-expanded') || 'false'; + assertEquals('false', isExpanded); + + done(); +} + +/** + * Test case for updateSubElementsFromList. + * + * If removable volumes are disabled, they should be allowed to mount/unmount, + * but cannot be selected or expanded. + */ +export async function testUpdateSubElementsRemovableDisabled(done) { + const recentItem = null; + const shortcutListModel = new MockFolderShortcutDataModel([]); + const androidAppListModel = createFakeAndroidAppListModel([]); + + // Set removable volumes as disabled. + volumeManager.isDisabled = (volume) => { + return (volume === VolumeManagerCommon.VolumeType.REMOVABLE); + }; + + const treeModel = new NavigationListModel( + volumeManager, shortcutListModel.asFolderShortcutsDataModel(), recentItem, + directoryModel, androidAppListModel, DialogType.FULL_PAGE); + + // Populate the directory tree with the mock filesystem. + let directoryTree = createElements(); + const mockMetadata = createMockMetadataModel(); + DirectoryTree.decorate( + directoryTree, directoryModel, volumeManager, mockMetadata, + fileOperationManager, true); + directoryTree.dataModel = treeModel; + + // Coerce to DirectoryTree type and update the tree. + directoryTree = /** @type {!DirectoryTree} */ (directoryTree); + directoryTree.updateSubElementsFromList(true); + + // There are 2 volumes at first. + assertEquals(2, getDirectoryTreeItemLabels(directoryTree).length); + + // Mount a removable volume. + const removableVolume = MockVolumeManager.createMockVolumeInfo( + VolumeManagerCommon.VolumeType.REMOVABLE, 'removable', + str('REMOVABLE_DIRECTORY_LABEL')); + volumeManager.volumeInfoList.add(removableVolume); + + // Asserts that a removable directory is added after the update. + directoryTree.updateSubElementsFromList(false); + assertEquals(3, getDirectoryTreeItemLabels(directoryTree).length); + + const removableItem = directoryTree.items[2]; + assertEquals(str('REMOVABLE_DIRECTORY_LABEL'), removableItem.label); + assertTrue(removableItem.disabled); + assertFalse(removableItem.hasChildren); + // Clicking on the item shouldn't select it. + removableItem.click(); + await new Promise(resolve => requestAnimationFrame(resolve)); + assertFalse(removableItem.selected); + // The item shouldn't be expanded. + let isExpanded = removableItem.getAttribute('aria-expanded') || 'false'; + assertEquals('false', isExpanded); + // Clicking on the expand icon shouldn't expand. + removableItem.querySelector('.expand-icon').click(); + await new Promise(resolve => requestAnimationFrame(resolve)); + isExpanded = removableItem.getAttribute('aria-expanded') || 'false'; + assertEquals('false', isExpanded); + + // Unmount the removable and assert that it's removed from the directory tree. + volumeManager.volumeInfoList.remove('removable'); + directoryTree.updateSubElementsFromList(false); + assertEquals(2, getDirectoryTreeItemLabels(directoryTree).length); + + done(); } /** @@ -838,7 +920,7 @@ /** * Test removing the last computer for a user. - * Computerss subtree should be removed after the change notification is + * Computers subtree should be removed after the change notification is * delivered. * * @param {!function(boolean)} callback A callback function which is called with @@ -1149,8 +1231,14 @@ callback); } -/** Test that clicking on disabled items is ignored. */ -export function testDisabledVolumes(callback) { +/** + * Test a disabled drive volume. + * + * If drive is disabled, this should be reflected in the directory model as + * well: the children shouldn't be loaded, and clicking on the item or the + * expand icon shouldn't do anything. + */ +export async function testDriveDisabled(done) { // Setup My Drive and Downloads and one folder inside each of them. fakeFileSystemURLEntries['filesystem:drive/root/folder1'] = MockDirectoryEntry.create(driveFileSystem, '/root/folder1'); @@ -1171,22 +1259,29 @@ directoryTree = /** @type {!DirectoryTree} */ (directoryTree); directoryTree.redraw(true); + // Set the drive to be disabled. We do it here since it's already added when + // the MockVolumeManager is created. const driveItem = directoryTree.items[0]; driveItem.disabled = true; + directoryTree.redraw(true); - reportPromise( - waitUntil(() => { - driveItem.click(); - return !driveItem.selected; - }).then(() => { - let ariaExpanded = driveItem.getAttribute('aria-expanded'); - assertTrue(ariaExpanded === 'false' || ariaExpanded === null); + assertEquals(str('DRIVE_DIRECTORY_LABEL'), driveItem.label); + assertTrue(driveItem.disabled); + assertFalse(driveItem.hasChildren); - driveItem.querySelector('.expand-icon').click(); - // After clicking on expand-icon, aria-expanded should be still be set - // to false. - ariaExpanded = driveItem.getAttribute('aria-expanded'); - assertTrue(ariaExpanded === 'false' || ariaExpanded === null); - }), - callback); + // Clicking on the item shouldn't select it. + driveItem.click(); + await new Promise(resolve => requestAnimationFrame(resolve)); + assertFalse(driveItem.selected); + + // The item shouldn't be expanded. + let isExpanded = driveItem.getAttribute('aria-expanded') || 'false'; + assertEquals('false', isExpanded); + // Clicking on the expand icon shouldn't expand. + driveItem.querySelector('.expand-icon').click(); + await new Promise(resolve => requestAnimationFrame(resolve)); + isExpanded = driveItem.getAttribute('aria-expanded') || 'false'; + assertEquals('false', isExpanded); + + done(); }
diff --git a/ui/gl/BUILD.gn b/ui/gl/BUILD.gn index 45fd5304..0a44499 100644 --- a/ui/gl/BUILD.gn +++ b/ui/gl/BUILD.gn
@@ -95,8 +95,6 @@ "gl_image.h", "gl_image_memory.cc", "gl_image_memory.h", - "gl_image_shared_memory.cc", - "gl_image_shared_memory.h", "gl_image_stub.cc", "gl_image_stub.h", "gl_implementation.cc", @@ -574,7 +572,6 @@ sources = [ "gl_api_unittest.cc", - "gl_image_shared_memory_unittest.cc", "gl_surface_format_unittest.cc", "gl_version_info_unittest.cc", "gpu_timing_unittest.cc",
diff --git a/ui/gl/gl_image_shared_memory.cc b/ui/gl/gl_image_shared_memory.cc deleted file mode 100644 index 9d45e8c..0000000 --- a/ui/gl/gl_image_shared_memory.cc +++ /dev/null
@@ -1,89 +0,0 @@ -// Copyright 2014 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ui/gl/gl_image_shared_memory.h" - -#include "base/logging.h" -#include "base/numerics/safe_math.h" -#include "base/process/process_handle.h" -#include "base/system/sys_info.h" -#include "base/trace_event/memory_allocator_dump.h" -#include "base/trace_event/process_memory_dump.h" -#include "ui/gfx/buffer_format_util.h" - -namespace gl { - -GLImageSharedMemory::GLImageSharedMemory(const gfx::Size& size) - : GLImageMemory(size) {} - -GLImageSharedMemory::~GLImageSharedMemory() {} - -bool GLImageSharedMemory::Initialize( - const base::UnsafeSharedMemoryRegion& region, - gfx::GenericSharedMemoryId shared_memory_id, - gfx::BufferFormat format, - size_t offset, - size_t stride) { - if (!region.IsValid()) - return false; - - if (NumberOfPlanesForLinearBufferFormat(format) != 1) - return false; - - base::CheckedNumeric<size_t> checked_size = stride; - checked_size *= GetSize().height(); - if (!checked_size.IsValid()) - return false; - - // Minimize the amount of adress space we use but make sure offset is a - // multiple of page size as required by MapAt(). - size_t memory_offset = offset % base::SysInfo::VMAllocationGranularity(); - size_t map_offset = base::SysInfo::VMAllocationGranularity() * - (offset / base::SysInfo::VMAllocationGranularity()); - - checked_size += memory_offset; - if (!checked_size.IsValid()) - return false; - - auto shared_memory_mapping = - region.MapAt(static_cast<off_t>(map_offset), checked_size.ValueOrDie()); - if (!shared_memory_mapping.IsValid()) { - DVLOG(0) << "Failed to map shared memory."; - return false; - } - - if (!GLImageMemory::Initialize( - static_cast<uint8_t*>(shared_memory_mapping.memory()) + memory_offset, - format, stride)) { - return false; - } - - DCHECK(!shared_memory_mapping_.IsValid()); - shared_memory_mapping_ = std::move(shared_memory_mapping); - shared_memory_id_ = shared_memory_id; - return true; -} - -void GLImageSharedMemory::OnMemoryDump( - base::trace_event::ProcessMemoryDump* pmd, - uint64_t process_tracing_id, - const std::string& dump_name) { - const size_t size_in_bytes = stride() * GetSize().height(); - - // Dump under "/shared_memory", as the base class may also dump to - // "/texture_memory". - base::trace_event::MemoryAllocatorDump* dump = - pmd->CreateAllocatorDump(dump_name + "/shared_memory"); - dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize, - base::trace_event::MemoryAllocatorDump::kUnitsBytes, - static_cast<uint64_t>(size_in_bytes)); - - auto shared_memory_guid = shared_memory_mapping_.guid(); - if (!shared_memory_guid.is_empty()) { - pmd->CreateSharedMemoryOwnershipEdge(dump->guid(), shared_memory_guid, - 0 /* importance */); - } -} - -} // namespace gl
diff --git a/ui/gl/gl_image_shared_memory.h b/ui/gl/gl_image_shared_memory.h deleted file mode 100644 index 1f3442b..0000000 --- a/ui/gl/gl_image_shared_memory.h +++ /dev/null
@@ -1,48 +0,0 @@ -// Copyright 2014 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef UI_GL_GL_IMAGE_SHARED_MEMORY_H_ -#define UI_GL_GL_IMAGE_SHARED_MEMORY_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <memory> - -#include "base/memory/unsafe_shared_memory_region.h" -#include "ui/gfx/generic_shared_memory_id.h" -#include "ui/gl/gl_export.h" -#include "ui/gl/gl_image_memory.h" - -namespace gl { - -class GL_EXPORT GLImageSharedMemory : public GLImageMemory { - public: - explicit GLImageSharedMemory(const gfx::Size& size); - - GLImageSharedMemory(const GLImageSharedMemory&) = delete; - GLImageSharedMemory& operator=(const GLImageSharedMemory&) = delete; - - bool Initialize(const base::UnsafeSharedMemoryRegion& shared_memory_region, - gfx::GenericSharedMemoryId shared_memory_id, - gfx::BufferFormat format, - size_t offset, - size_t stride); - - // Overridden from GLImage: - void OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd, - uint64_t process_tracing_id, - const std::string& dump_name) override; - - protected: - ~GLImageSharedMemory() override; - - private: - base::WritableSharedMemoryMapping shared_memory_mapping_; - gfx::GenericSharedMemoryId shared_memory_id_; -}; - -} // namespace gl - -#endif // UI_GL_GL_IMAGE_SHARED_MEMORY_H_
diff --git a/ui/gl/gl_image_shared_memory_unittest.cc b/ui/gl/gl_image_shared_memory_unittest.cc deleted file mode 100644 index d88cc8f..0000000 --- a/ui/gl/gl_image_shared_memory_unittest.cc +++ /dev/null
@@ -1,125 +0,0 @@ -// Copyright 2015 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stddef.h> -#include <stdint.h> - -#include "base/system/sys_info.h" -#include "build/build_config.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/gl/gl_image_shared_memory.h" -#include "ui/gl/test/gl_image_test_template.h" - -namespace gl { -namespace { - -const uint8_t kGreen[] = {0x0, 0x20, 0x0, 0xFF}; - -template <gfx::BufferFormat format> -class GLImageSharedMemoryTestDelegate : public GLImageTestDelegateBase { - public: - scoped_refptr<GLImage> CreateSolidColorImage(const gfx::Size& size, - const uint8_t color[4]) const { - DCHECK_EQ(NumberOfPlanesForLinearBufferFormat(format), 1u); - base::UnsafeSharedMemoryRegion shared_memory_region = - base::UnsafeSharedMemoryRegion::Create( - gfx::BufferSizeForBufferFormat(size, format)); - base::WritableSharedMemoryMapping shared_memory_mapping = - shared_memory_region.Map(); - DCHECK(shared_memory_mapping.IsValid()); - - GLImageTestSupport::SetBufferDataToColor( - size.width(), size.height(), - static_cast<int>(RowSizeForBufferFormat(size.width(), format, 0)), 0, - format, color, static_cast<uint8_t*>(shared_memory_mapping.memory())); - auto image = base::MakeRefCounted<GLImageSharedMemory>(size); - bool rv = image->Initialize( - shared_memory_region, gfx::GenericSharedMemoryId(0), format, 0, - gfx::RowSizeForBufferFormat(size.width(), format, 0)); - EXPECT_TRUE(rv); - return image; - } - - unsigned GetTextureTarget() const { return GL_TEXTURE_2D; } - const uint8_t* GetImageColor() { return kGreen; } - int GetAdmissibleError() const { return 0; } -}; - -using GLImageTestTypes = testing::Types< - GLImageSharedMemoryTestDelegate<gfx::BufferFormat::BGR_565>, - GLImageSharedMemoryTestDelegate<gfx::BufferFormat::RGBX_8888>, - GLImageSharedMemoryTestDelegate<gfx::BufferFormat::RGBA_8888>, - GLImageSharedMemoryTestDelegate<gfx::BufferFormat::BGRX_8888>, -#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) - // Fails on Win nVidia and linux android: the test writes nothing (we read - // back the color used to clear the buffer). - // TODO(mcasas): enable those paltforms https://crbug.com/803451. - GLImageSharedMemoryTestDelegate<gfx::BufferFormat::RGBA_1010102>, - -// https://crbug.com/830653 -#if !defined(ADDRESS_SANITIZER) && !defined(MEMORY_SANITIZER) && \ - !defined(THREAD_SANITIZER) - GLImageSharedMemoryTestDelegate<gfx::BufferFormat::BGRA_1010102>, -#endif -#endif - GLImageSharedMemoryTestDelegate<gfx::BufferFormat::BGRA_8888>>; - -INSTANTIATE_TYPED_TEST_SUITE_P(GLImageSharedMemory, - GLImageTest, - GLImageTestTypes); - -INSTANTIATE_TYPED_TEST_SUITE_P(GLImageSharedMemory, - GLImageOddSizeTest, - GLImageTestTypes); - -INSTANTIATE_TYPED_TEST_SUITE_P(GLImageSharedMemory, - GLImageCopyTest, - GLImageTestTypes); - -class GLImageSharedMemoryPoolTestDelegate : public GLImageTestDelegateBase { - public: - scoped_refptr<GLImage> CreateSolidColorImage(const gfx::Size& size, - const uint8_t color[4]) const { - // Create a shared memory segment that holds an image with a stride that is - // twice the row size and 2 pages larger than image. - size_t stride = gfx::RowSizeForBufferFormat( - size.width(), gfx::BufferFormat::RGBA_8888, 0) * - 2; - size_t pool_size = - stride * size.height() + base::SysInfo::VMAllocationGranularity() * 3; - base::UnsafeSharedMemoryRegion shared_memory_region = - base::UnsafeSharedMemoryRegion::Create(pool_size); - base::WritableSharedMemoryMapping shared_memory_mapping = - shared_memory_region.Map(); - DCHECK(shared_memory_mapping.IsValid()); - // Initialize memory to a value that is easy to recognize if test fails. - memset(shared_memory_mapping.memory(), 0x55, pool_size); - // Place buffer at a non-zero non-page-aligned offset in shared memory. - size_t buffer_offset = 3 * base::SysInfo::VMAllocationGranularity() / 2; - GLImageTestSupport::SetBufferDataToColor( - size.width(), size.height(), static_cast<int>(stride), 0, - gfx::BufferFormat::RGBA_8888, color, - static_cast<uint8_t*>(shared_memory_mapping.memory()) + buffer_offset); - auto image = base::MakeRefCounted<GLImageSharedMemory>(size); - bool rv = - image->Initialize(shared_memory_region, gfx::GenericSharedMemoryId(0), - gfx::BufferFormat::RGBA_8888, buffer_offset, stride); - EXPECT_TRUE(rv); - return image; - } - - unsigned GetTextureTarget() const { return GL_TEXTURE_2D; } - const uint8_t* GetImageColor() { return kGreen; } - int GetAdmissibleError() const { return 0; } -}; - -// Disabled on Windows, see crbug.com/1036138 -#if !BUILDFLAG(IS_WIN) -INSTANTIATE_TYPED_TEST_SUITE_P(GLImageSharedMemoryPool, - GLImageCopyTest, - GLImageSharedMemoryPoolTestDelegate); -#endif - -} // namespace -} // namespace gl
diff --git a/ui/gl/test/gl_image_test_template.cc b/ui/gl/test/gl_image_test_template.cc index 714c19f..9ba7906 100644 --- a/ui/gl/test/gl_image_test_template.cc +++ b/ui/gl/test/gl_image_test_template.cc
@@ -150,6 +150,5 @@ // These suites are instantiated in binaries that use //ui/gl:test_support. GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLImageTest); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLImageOddSizeTest); -GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GLImageCopyTest); } // namespace gl
diff --git a/ui/gl/test/gl_image_test_template.h b/ui/gl/test/gl_image_test_template.h index 160bd900..73453faf 100644 --- a/ui/gl/test/gl_image_test_template.h +++ b/ui/gl/test/gl_image_test_template.h
@@ -8,10 +8,6 @@ #ifndef UI_GL_TEST_GL_IMAGE_TEST_TEMPLATE_H_ #define UI_GL_TEST_GL_IMAGE_TEST_TEMPLATE_H_ -#include <stdint.h> - -#include <memory> - #include "base/memory/raw_ptr.h" #include "base/strings/stringize_macros.h" #include "build/build_config.h" @@ -156,87 +152,6 @@ // GLImage in order to be conformant. REGISTER_TYPED_TEST_SUITE_P_WITH_EXPANSION(GLImageOddSizeTest, MAYBE_Create); -template <typename GLImageTestDelegate> -class GLImageCopyTest : public GLImageTest<GLImageTestDelegate> {}; - -TYPED_TEST_SUITE_P(GLImageCopyTest); - -TYPED_TEST_P(GLImageCopyTest, CopyTexImage) { - if (this->delegate_.SkipTest(this->display_)) - GTEST_SKIP() << "Skip because GL initialization failed"; - - // CopyTexImage follows different code paths depending whether the image is - // > 1 MiB or not. This range of sizes should cover both possibilities - // regardless of format. - const std::vector<gfx::Size> image_size_list{ - {256, 256}, - {512, 512}, - {1024, 1024}, - }; - const uint8_t* image_color = this->delegate_.GetImageColor(); - const uint8_t texture_color[] = {0, 0, 0xff, 0xff}; - - GLuint vao = 0; - if (GLContext::GetCurrent()->GetVersionInfo()->IsAtLeastGL(3, 3)) { - // To avoid glGetVertexAttribiv(0, ...) failing. - glGenVertexArraysOES(1, &vao); - glBindVertexArrayOES(vao); - } - - for (auto image_size : image_size_list) { - LOG(INFO) << "Testing with size " << image_size.ToString(); - GLuint framebuffer = - GLTestHelper::SetupFramebuffer(image_size.width(), image_size.height()); - ASSERT_TRUE(framebuffer); - glBindFramebufferEXT(GL_FRAMEBUFFER, framebuffer); - glViewport(0, 0, image_size.width(), image_size.height()); - - // Create a solid color green image of preferred format. This must succeed - // in order for a GLImage to be conformant. - scoped_refptr<GLImage> image = - this->delegate_.CreateSolidColorImage(image_size, image_color); - ASSERT_TRUE(image); - - // Create a solid color blue texture of the same size as |image|. - unsigned target = this->delegate_.GetTextureTarget(); - GLuint texture = GLTestHelper::CreateTexture(target); - std::unique_ptr<uint8_t[]> pixels(new uint8_t[BufferSizeForBufferFormat( - image_size, gfx::BufferFormat::RGBA_8888)]); - GLImageTestSupport::SetBufferDataToColor( - image_size.width(), image_size.height(), - static_cast<int>(RowSizeForBufferFormat( - image_size.width(), gfx::BufferFormat::RGBA_8888, 0)), - 0, gfx::BufferFormat::RGBA_8888, texture_color, pixels.get()); - glBindTexture(target, texture); - glTexImage2D(target, 0, GL_RGBA, image_size.width(), image_size.height(), 0, - GL_RGBA, GL_UNSIGNED_BYTE, pixels.get()); - - // Copy |image| to |texture|. - bool rv = image->CopyTexImage(target); - EXPECT_TRUE(rv); - - // Draw |texture| to viewport. - internal::DrawTextureQuad(target, image_size); - - // Read back pixels to check expectations. - GLTestHelper::CheckPixelsWithError( - 0, 0, image_size.width(), image_size.height(), - this->delegate_.GetAdmissibleError(), image_color); - - // Clean up. - glDeleteTextures(1, &texture); - glDeleteFramebuffersEXT(1, &framebuffer); - } - - if (vao) { - glDeleteVertexArraysOES(1, &vao); - } -} - -// The GLImageCopyTest test case verifies that the GLImage implementation -// handles CopyTexImage correctly. -REGISTER_TYPED_TEST_SUITE_P(GLImageCopyTest, CopyTexImage); - } // namespace gl // Avoid polluting source files that include this header.
diff --git a/ui/ozone/platform/wayland/host/wayland_connection.cc b/ui/ozone/platform/wayland/host/wayland_connection.cc index 241d80a..7c96bb85 100644 --- a/ui/ozone/platform/wayland/host/wayland_connection.cc +++ b/ui/ozone/platform/wayland/host/wayland_connection.cc
@@ -624,7 +624,7 @@ if (!surface_submission_in_pixel_coordinates_ || !window) return location; gfx::PointF converted(location); - converted.Scale(1.0f / window->window_scale()); + converted.InvScale(window->window_scale()); return converted; }
diff --git a/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc b/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc index e59d4ee..332637b 100644 --- a/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc
@@ -438,7 +438,7 @@ gfx::Point entered_point{800, 600}; { gfx::PointF expected_position(entered_point); - expected_position.Scale(1.0f / kTripleScale); + expected_position.InvScale(kTripleScale); EXPECT_CALL(*drop_handler_, MockDragMotion(PointFNear(expected_position), _, _)); @@ -476,7 +476,7 @@ gfx::Point center_point{400, 300}; { gfx::PointF expected_position(center_point); - expected_position.Scale(1.0f / kTripleScale); + expected_position.InvScale(kTripleScale); EXPECT_CALL(*drop_handler_, MockDragMotion(PointFNear(expected_position), _, _))
diff --git a/ui/ozone/platform/wayland/host/wayland_screen.cc b/ui/ozone/platform/wayland/host/wayland_screen.cc index 43c9c54..0763e0c 100644 --- a/ui/ozone/platform/wayland/host/wayland_screen.cc +++ b/ui/ozone/platform/wayland/host/wayland_screen.cc
@@ -274,16 +274,6 @@ return 0; } -void WaylandScreen::OnTabletStateChanged(display::TabletState tablet_state) { -#if BUILDFLAG(IS_CHROMEOS_LACROS) - tablet_state_ = tablet_state; -#endif - - auto* observer_list = display_list_.observers(); - for (auto& observer : *observer_list) - observer.OnDisplayTabletStateChanged(tablet_state); -} - base::WeakPtr<WaylandScreen> WaylandScreen::GetWeakPtr() { return weak_factory_.GetWeakPtr(); } @@ -511,6 +501,16 @@ return values; } +void WaylandScreen::OnTabletStateChanged(display::TabletState tablet_state) { +#if BUILDFLAG(IS_CHROMEOS_LACROS) + tablet_state_ = tablet_state; +#endif + + auto* observer_list = display_list_.observers(); + for (auto& observer : *observer_list) + observer.OnDisplayTabletStateChanged(tablet_state); +} + #if BUILDFLAG(IS_CHROMEOS_LACROS) display::TabletState WaylandScreen::GetTabletState() const { return tablet_state_;
diff --git a/ui/ozone/platform/wayland/host/wayland_screen.h b/ui/ozone/platform/wayland/host/wayland_screen.h index 69df25f..4533557 100644 --- a/ui/ozone/platform/wayland/host/wayland_screen.h +++ b/ui/ozone/platform/wayland/host/wayland_screen.h
@@ -48,8 +48,6 @@ uint32_t GetOutputIdForDisplayId(int64_t display_id); - void OnTabletStateChanged(display::TabletState tablet_state); - base::WeakPtr<WaylandScreen> GetWeakPtr(); // PlatformScreen overrides: @@ -75,6 +73,7 @@ void RemoveObserver(display::DisplayObserver* observer) override; base::Value::List GetGpuExtraInfo( const gfx::GpuExtraInfo& gpu_extra_info) override; + void OnTabletStateChanged(display::TabletState tablet_state) override; #if BUILDFLAG(IS_CHROMEOS_LACROS) display::TabletState GetTabletState() const override; #endif
diff --git a/ui/ozone/platform/wayland/host/wayland_surface.cc b/ui/ozone/platform/wayland/host/wayland_surface.cc index 2bf80899..c94f30d 100644 --- a/ui/ozone/platform/wayland/host/wayland_surface.cc +++ b/ui/ozone/platform/wayland/host/wayland_surface.cc
@@ -687,8 +687,8 @@ if (!pending_state_.crop.IsEmpty()) { damage_uv.Offset(-pending_state_.crop.OffsetFromOrigin()); - damage_uv.Scale(1.0f / pending_state_.crop.width(), - 1.0f / pending_state_.crop.height()); + damage_uv.InvScale(pending_state_.crop.width(), + pending_state_.crop.height()); } damage_uv.Intersect(gfx::RectF(1, 1));
diff --git a/ui/ozone/platform/wayland/host/wayland_zaura_output.cc b/ui/ozone/platform/wayland/host/wayland_zaura_output.cc index da0ef72c..d07638114 100644 --- a/ui/ozone/platform/wayland/host/wayland_zaura_output.cc +++ b/ui/ozone/platform/wayland/host/wayland_zaura_output.cc
@@ -17,9 +17,8 @@ DCHECK(obj_); static constexpr zaura_output_listener kZAuraOutputListener = { - &OnScale, &OnConnection, &OnDeviceScaleFactor, - &OnInsets, &OnLogicalTransform, &OnDisplayId, - &OnActivated}; + &OnScale, &OnConnection, &OnDeviceScaleFactor, + &OnInsets, &OnLogicalTransform, &OnDisplayId}; zaura_output_add_listener(obj_.get(), &kZAuraOutputListener, this); } @@ -73,7 +72,4 @@ } } -void WaylandZAuraOutput::OnActivated(void* data, - struct zaura_output* zaura_output) {} - } // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_zaura_output.h b/ui/ozone/platform/wayland/host/wayland_zaura_output.h index f6a1a7131..3432fd2 100644 --- a/ui/ozone/platform/wayland/host/wayland_zaura_output.h +++ b/ui/ozone/platform/wayland/host/wayland_zaura_output.h
@@ -63,7 +63,6 @@ struct zaura_output* zaura_output, uint32_t display_id_hi, uint32_t display_id_lo); - static void OnActivated(void* data, struct zaura_output* zaura_output); wl::Object<zaura_output> obj_; gfx::Insets insets_;
diff --git a/ui/ozone/public/platform_screen.h b/ui/ozone/public/platform_screen.h index 96ad3d4..80ac8d5 100644 --- a/ui/ozone/public/platform_screen.h +++ b/ui/ozone/public/platform_screen.h
@@ -136,6 +136,9 @@ // Currently only used by Linux. virtual void SetDeviceScaleFactor(float scale); + // Called when tablet state is changed. + virtual void OnTabletStateChanged(display::TabletState tablet_state) {} + #if BUILDFLAG(IS_CHROMEOS_LACROS) // Returns tablet state. If a platform does not support this, returns // display::TabletState::kInClamshellMode.
diff --git a/ui/snapshot/snapshot_aura_unittest.cc b/ui/snapshot/snapshot_aura_unittest.cc index b57208a6..f633363a 100644 --- a/ui/snapshot/snapshot_aura_unittest.cc +++ b/ui/snapshot/snapshot_aura_unittest.cc
@@ -276,7 +276,7 @@ // Snapshot always captures the physical pixels. gfx::SizeF snapshot_size(test_bounds.size()); - snapshot_size.Scale(1 / kUIScale); + snapshot_size.InvScale(kUIScale); gfx::Image snapshot = GrabSnapshotForTestWindow(); EXPECT_EQ(gfx::ToRoundedSize(snapshot_size).ToString(), @@ -324,7 +324,7 @@ // Snapshot always captures the physical pixels. gfx::SizeF snapshot_size(test_bounds.size()); - snapshot_size.Scale(1 / kUIScale); + snapshot_size.InvScale(kUIScale); gfx::Image snapshot = GrabSnapshotForTestWindow(); EXPECT_EQ(gfx::ToRoundedSize(snapshot_size).ToString(),
diff --git a/ui/views/animation/ink_drop_util.cc b/ui/views/animation/ink_drop_util.cc index d492203..84fd5b9 100644 --- a/ui/views/animation/ink_drop_util.cc +++ b/ui/views/animation/ink_drop_util.cc
@@ -29,7 +29,7 @@ gfx::Vector2dF aligned_offset_in_dip = origin.OffsetFromOrigin(); aligned_offset_in_dip.set_x(std::round(aligned_offset_in_dip.x())); aligned_offset_in_dip.set_y(std::round(aligned_offset_in_dip.y())); - aligned_offset_in_dip.Scale(1.f / device_scale_factor); + aligned_offset_in_dip.InvScale(device_scale_factor); // Compute the subpixel offset correction and apply it to the transform. gfx::Transform subpixel_correction;
diff --git a/ui/views/animation/square_ink_drop_ripple.cc b/ui/views/animation/square_ink_drop_ripple.cc index 7eac52e..372d1f3 100644 --- a/ui/views/animation/square_ink_drop_ripple.cc +++ b/ui/views/animation/square_ink_drop_ripple.cc
@@ -441,7 +441,7 @@ desired_size.width() / 2.0f)); ripple_bounds.Scale(dsf); ripple_bounds = gfx::RectF(gfx::ToEnclosingRect(ripple_bounds)); - ripple_bounds.Scale(1.0f / dsf); + ripple_bounds.InvScale(dsf); size = ripple_bounds.size(); }
diff --git a/ui/views/view.h b/ui/views/view.h index 28167c8e3..97d4c12 100644 --- a/ui/views/view.h +++ b/ui/views/view.h
@@ -333,7 +333,7 @@ // |rounded_pixel_offset_| is stored in physical pixel space. Convert it // into DIP space before returning. gfx::Vector2dF subpixel_offset(rounded_pixel_offset_); - subpixel_offset.Scale(1.f / device_scale_factor_); + subpixel_offset.InvScale(device_scale_factor_); return subpixel_offset; }