diff --git a/DEPS b/DEPS index e1c1016..0f4c6079 100644 --- a/DEPS +++ b/DEPS
@@ -175,7 +175,7 @@ # luci-go CIPD package version. # Make sure the revision is uploaded by infra-packagers builder. # https://ci.chromium.org/p/infra-internal/g/infra-packagers/console - 'luci_go': 'git_revision:19175e196dd495f6e092845f7d777cb5bf157b3e', + 'luci_go': 'git_revision:e81c0c9c528d0a416922e4ccd958d0de59a64816', # This can be overridden, e.g. with custom_vars, to build clang from HEAD # instead of downloading the prebuilt pinned revision. @@ -204,11 +204,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '2558c468cc71b3cc8b671c6e55aad1d9ae8a8bba', + 'skia_revision': 'dc20847579665223826ff5f2d344a0b566e3b4b5', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '4f0f4e2a3c5ad9dc7312774da5197e0179c30863', + 'v8_revision': 'fc442e89638f38a476e53abca22aafde28c55aa5', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -283,7 +283,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': 'aa1d0c8587914c402d993da0bbda16e84d513fdf', + 'devtools_frontend_revision': '3ac2a3b23c1b647bed70be845adaa1e058416a34', # 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. @@ -327,7 +327,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': '91e0ce88f914bf9663dc6858c1a735c3d8829c47', + 'quiche_revision': '5111790e59dc91b13e47fc7742b57ee29897b139', # 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. @@ -561,7 +561,7 @@ }, 'src/ios/third_party/material_components_ios/src': { - 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'ee79f1c2b1ded032bf91dfcf01d82eb20c73fa31', + 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'bf652865ce9c4ec36498f5a38b5c948974062ecc', 'condition': 'checkout_ios', }, @@ -929,7 +929,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '36de4be91ef66852c49aa5fd9e0cc31d5ec05ae9', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '2737963b46b333e8db51f433b56af53fc17cfdc8', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), @@ -1585,7 +1585,7 @@ 'packages': [ { 'package': 'skia/tools/goldctl/windows-amd64', - 'version': 'wr5p_MyXcHVxA-eHznijCeFaqR2HUo02Hw70e0CWCIoC', + 'version': '3sDKbIeT1dc4BYnE_uMfW71xbKa-b75KWLUwVEIJF-QC', }, ], 'dep_type': 'cipd', @@ -1595,7 +1595,7 @@ 'packages': [ { 'package': 'skia/tools/goldctl/mac-amd64', - 'version': 'TPtcrf_XH3mB9pdK4W3N0QPZunsqJ08T7U7fWPvMnRAC', + 'version': 'Rbel_7KQuxv_-SIkB3oT43MBYgKlr3AUwFystGNHKJ8C', }, ], 'dep_type': 'cipd', @@ -1609,7 +1609,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@f8d6ef784e7aaa03ad2b20707944b123881ec8ab', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@9e64d40cc7c8207b7de94268052944ffb6422ab4', 'condition': 'checkout_src_internal', },
diff --git a/android_webview/BUILD.gn b/android_webview/BUILD.gn index 5ded435..0c115ad 100644 --- a/android_webview/BUILD.gn +++ b/android_webview/BUILD.gn
@@ -489,7 +489,7 @@ "java/src/org/chromium/android_webview/NullAwViewMethods.java", "java/src/org/chromium/android_webview/OverScrollGlow.java", "java/src/org/chromium/android_webview/PopupTouchHandleDrawable.java", - "java/src/org/chromium/android_webview/ScriptReference.java", + "java/src/org/chromium/android_webview/ScriptHandler.java", "java/src/org/chromium/android_webview/ScrollAccessibilityHelper.java", "java/src/org/chromium/android_webview/SslUtil.java", "java/src/org/chromium/android_webview/ViewPositionObserver.java",
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/SharedWebViewChromium.java b/android_webview/glue/java/src/com/android/webview/chromium/SharedWebViewChromium.java index 9815cf74..9f0a2a0e 100644 --- a/android_webview/glue/java/src/com/android/webview/chromium/SharedWebViewChromium.java +++ b/android_webview/glue/java/src/com/android/webview/chromium/SharedWebViewChromium.java
@@ -9,7 +9,7 @@ import org.chromium.android_webview.AwContents; import org.chromium.android_webview.AwRenderProcess; -import org.chromium.android_webview.ScriptReference; +import org.chromium.android_webview.ScriptHandler; import org.chromium.android_webview.WebMessageListener; import org.chromium.android_webview.WebViewChromiumRunQueue; import org.chromium.base.ThreadUtils; @@ -137,7 +137,7 @@ mAwContents.removeWebMessageListener(jsObjectName); } - public ScriptReference addDocumentStartJavaScript( + public ScriptHandler addDocumentStartJavaScript( final String script, final String[] allowedOriginRules) { if (checkNeedsPost()) { return mRunQueue.runOnUiThreadBlocking(
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java index b3ae70a..fc0c259 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContents.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -2621,9 +2621,9 @@ * Add a JavaScript snippet that will run after the document has been created, but before any * script in the document executes. Note that calling this method multiple times will add * multiple scripts. Added scripts will take effect from the next navigation. If want to remove - * previously set script, use the returned ScriptReference object to do so. Any JavaScript + * previously set script, use the returned ScriptHandler object to do so. Any JavaScript * objects injected by addWebMessageListener() or addJavascriptInterface() will be available to - * use in this script. Scripts can be removed using the ScriptReference object returned when + * use in this script. Scripts can be removed using the ScriptHandler object returned when * they were added. The DOM tree may not be ready at the moment that the script runs. * * If multiple scripts are added, they will be executed in the same order they were added. @@ -2634,9 +2634,9 @@ * * @throws IllegalArgumentException if one of the allowedOriginRules is invalid or one of * jsObjectName and allowedOriginRules is {@code null}. - * @return A {@link ScriptReference} for removing the script. + * @return A {@link ScriptHandler} for removing the script. */ - public ScriptReference addDocumentStartJavaScript( + public ScriptHandler addDocumentStartJavaScript( @NonNull String script, @NonNull String[] allowedOriginRules) { if (script == null) { throw new IllegalArgumentException("script shouldn't be null."); @@ -2649,7 +2649,7 @@ } } - return new ScriptReference(AwContents.this, + return new ScriptHandler(AwContents.this, AwContentsJni.get().addDocumentStartJavaScript( mNativeAwContents, AwContents.this, script, allowedOriginRules)); }
diff --git a/android_webview/java/src/org/chromium/android_webview/ScriptReference.java b/android_webview/java/src/org/chromium/android_webview/ScriptHandler.java similarity index 89% rename from android_webview/java/src/org/chromium/android_webview/ScriptReference.java rename to android_webview/java/src/org/chromium/android_webview/ScriptHandler.java index 37ee88ac1..e34486d 100644 --- a/android_webview/java/src/org/chromium/android_webview/ScriptReference.java +++ b/android_webview/java/src/org/chromium/android_webview/ScriptHandler.java
@@ -11,11 +11,11 @@ /** * Used for Js Java interaction, to delete the document start JavaScript snippet. */ -public class ScriptReference { +public class ScriptHandler { private WeakReference<AwContents> mAwContentsRef; private int mScriptId; - public ScriptReference(AwContents awContents, int scriptId) { + public ScriptHandler(AwContents awContents, int scriptId) { assert scriptId >= 0; mAwContentsRef = new WeakReference(awContents); mScriptId = scriptId;
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/JsJavaInteractionTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/JsJavaInteractionTest.java index e40a52d..a250d23f 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/JsJavaInteractionTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/JsJavaInteractionTest.java
@@ -19,7 +19,7 @@ import org.chromium.android_webview.AwContents; import org.chromium.android_webview.JsReplyProxy; -import org.chromium.android_webview.ScriptReference; +import org.chromium.android_webview.ScriptHandler; import org.chromium.android_webview.WebMessageListener; import org.chromium.android_webview.test.TestAwContentsClient.OnReceivedTitleHelper; import org.chromium.android_webview.test.util.CommonResources; @@ -1194,13 +1194,13 @@ @Feature({"AndroidWebView", "JsJavaInteraction"}) public void testDocumentStartJavaScript_removeScript() throws Throwable { addWebMessageListenerOnUiThread(mAwContents, JS_OBJECT_NAME, new String[] {"*"}, mListener); - ScriptReference[] references = new ScriptReference[2]; + ScriptHandler[] handlers = new ScriptHandler[2]; for (int i = 0; i < 2; ++i) { final String script = JS_OBJECT_NAME + ".postMessage('" + HELLO + Integer.toString(i) + "');"; // Since we are matching both origins, the script will run in both iframe and main // frame, but it will send message in only iframe. - references[i] = + handlers[i] = addDocumentStartJavaScriptOnUiThread(mAwContents, script, new String[] {"*"}); } @@ -1213,14 +1213,14 @@ Assert.assertEquals(HELLO + Integer.toString(i), data.mMessage); } - TestThreadUtils.runOnUiThreadBlocking(() -> references[0].remove()); + TestThreadUtils.runOnUiThreadBlocking(() -> handlers[0].remove()); // Load the page again. loadUrlFromPath(HELLO_WORLD_HTML); TestWebMessageListener.Data data = mListener.waitForOnPostMessage(); Assert.assertEquals(HELLO + "1", data.mMessage); - TestThreadUtils.runOnUiThreadBlocking(() -> references[1].remove()); + TestThreadUtils.runOnUiThreadBlocking(() -> handlers[1].remove()); // Load the page again. loadUrlFromPath(HELLO_WORLD_HTML); @@ -1234,7 +1234,7 @@ addWebMessageListenerOnUiThread(mAwContents, JS_OBJECT_NAME, new String[] {"*"}, mListener); final String script = JS_OBJECT_NAME + ".postMessage('" + HELLO + "');"; - ScriptReference reference = + ScriptHandler handler = addDocumentStartJavaScriptOnUiThread(mAwContents, script, new String[] {"*"}); final String url = loadUrlFromPath(HELLO_WORLD_HTML); @@ -1245,16 +1245,16 @@ Assert.assertEquals(HELLO, data.mMessage); // Remove twice, the second time should take no effect. - TestThreadUtils.runOnUiThreadBlocking(() -> reference.remove()); - TestThreadUtils.runOnUiThreadBlocking(() -> reference.remove()); + TestThreadUtils.runOnUiThreadBlocking(() -> handler.remove()); + TestThreadUtils.runOnUiThreadBlocking(() -> handler.remove()); // Load the page again. loadUrlFromPath(HELLO_WORLD_HTML); Assert.assertTrue(mListener.hasNoMoreOnPostMessage()); // Remove twice again, should have no effect. - TestThreadUtils.runOnUiThreadBlocking(() -> reference.remove()); - TestThreadUtils.runOnUiThreadBlocking(() -> reference.remove()); + TestThreadUtils.runOnUiThreadBlocking(() -> handler.remove()); + TestThreadUtils.runOnUiThreadBlocking(() -> handler.remove()); // Load the page again. loadUrlFromPath(HELLO_WORLD_HTML); @@ -1317,7 +1317,7 @@ + "</body></html>"; } - private static ScriptReference addDocumentStartJavaScriptOnUiThread( + private static ScriptHandler addDocumentStartJavaScriptOnUiThread( final AwContents awContents, final String script, final String[] allowedOriginRules) { return TestThreadUtils.runOnUiThreadBlockingNoException( () -> awContents.addDocumentStartJavaScript(script, allowedOriginRules));
diff --git a/android_webview/support_library/BUILD.gn b/android_webview/support_library/BUILD.gn index bfbe0bc..65cf647 100644 --- a/android_webview/support_library/BUILD.gn +++ b/android_webview/support_library/BUILD.gn
@@ -11,7 +11,7 @@ "java/src/org/chromium/support_lib_glue/SupportLibJsReplyProxyAdapter.java", "java/src/org/chromium/support_lib_glue/SupportLibProxyControllerAdapter.java", "java/src/org/chromium/support_lib_glue/SupportLibReflectionUtil.java", - "java/src/org/chromium/support_lib_glue/SupportLibScriptReferenceAdapter.java", + "java/src/org/chromium/support_lib_glue/SupportLibScriptHandlerAdapter.java", "java/src/org/chromium/support_lib_glue/SupportLibServiceWorkerClientAdapter.java", "java/src/org/chromium/support_lib_glue/SupportLibServiceWorkerControllerAdapter.java", "java/src/org/chromium/support_lib_glue/SupportLibServiceWorkerSettingsAdapter.java",
diff --git a/android_webview/support_library/boundary_interfaces/BUILD.gn b/android_webview/support_library/boundary_interfaces/BUILD.gn index 3221dbc8..68b6ca52 100644 --- a/android_webview/support_library/boundary_interfaces/BUILD.gn +++ b/android_webview/support_library/boundary_interfaces/BUILD.gn
@@ -12,6 +12,7 @@ "src/org/chromium/support_lib_boundary/JsReplyProxyBoundaryInterface.java", "src/org/chromium/support_lib_boundary/ProxyControllerBoundaryInterface.java", "src/org/chromium/support_lib_boundary/SafeBrowsingResponseBoundaryInterface.java", + "src/org/chromium/support_lib_boundary/ScriptHandlerBoundaryInterface.java", "src/org/chromium/support_lib_boundary/ScriptReferenceBoundaryInterface.java", "src/org/chromium/support_lib_boundary/ServiceWorkerClientBoundaryInterface.java", "src/org/chromium/support_lib_boundary/ServiceWorkerControllerBoundaryInterface.java",
diff --git a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/ScriptHandlerBoundaryInterface.java b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/ScriptHandlerBoundaryInterface.java new file mode 100644 index 0000000..4dcaa75 --- /dev/null +++ b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/ScriptHandlerBoundaryInterface.java
@@ -0,0 +1,10 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.support_lib_boundary; + +/** + * Boundary interface for AwContents.addDocumentStartJavascript(). + */ +public interface ScriptHandlerBoundaryInterface extends ScriptReferenceBoundaryInterface {}
diff --git a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/ScriptReferenceBoundaryInterface.java b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/ScriptReferenceBoundaryInterface.java index 6358e00..aba822a 100644 --- a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/ScriptReferenceBoundaryInterface.java +++ b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/ScriptReferenceBoundaryInterface.java
@@ -6,6 +6,9 @@ /** * Boundary interface for AwContents.addDocumentStartJavascript(). + * + * TODO(ctzsm): Delete this interface once we've updated the APKs on + * the AndroidX bots and move the remove method to ScriptHandlerBoundaryInterface. */ public interface ScriptReferenceBoundaryInterface { void remove();
diff --git a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/WebViewProviderBoundaryInterface.java b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/WebViewProviderBoundaryInterface.java index 843d387..d524b31 100644 --- a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/WebViewProviderBoundaryInterface.java +++ b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/WebViewProviderBoundaryInterface.java
@@ -20,7 +20,7 @@ void addWebMessageListener(String jsObjectName, String[] allowedOriginRules, /* WebMessageListener */ InvocationHandler listener); void removeWebMessageListener(String jsObjectName); - /* ScriptReference */ InvocationHandler addDocumentStartJavaScript( + /* ScriptHandler */ InvocationHandler addDocumentStartJavaScript( String script, String[] allowedOriginRules); WebViewClient getWebViewClient(); WebChromeClient getWebChromeClient();
diff --git a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/util/Features.java b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/util/Features.java index b2f55e1e..3038a4f 100644 --- a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/util/Features.java +++ b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/util/Features.java
@@ -184,5 +184,5 @@ public static final String SET_SUPPORT_LIBRARY_VERSION = "SET_SUPPORT_LIBRARY_VERSION"; // WebViewCompat.addDocumentStartJavascript - public static final String DOCUMENT_START_SCRIPT = "DOCUMENT_START_SCRIPT:1"; + public static final String DOCUMENT_START_SCRIPT = "DOCUMENT_START_SCRIPT"; }
diff --git a/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibScriptHandlerAdapter.java b/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibScriptHandlerAdapter.java new file mode 100644 index 0000000..20a6de31 --- /dev/null +++ b/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibScriptHandlerAdapter.java
@@ -0,0 +1,28 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.support_lib_glue; + +import static org.chromium.support_lib_glue.SupportLibWebViewChromiumFactory.recordApiCall; + +import org.chromium.android_webview.ScriptHandler; +import org.chromium.support_lib_boundary.ScriptHandlerBoundaryInterface; +import org.chromium.support_lib_glue.SupportLibWebViewChromiumFactory.ApiCall; + +/** + * Adapter between ScriptHandlerBoundaryInterface and ScriptHandler. + */ +class SupportLibScriptHandlerAdapter implements ScriptHandlerBoundaryInterface { + private ScriptHandler mScriptHandler; + + public SupportLibScriptHandlerAdapter(ScriptHandler scriptHandler) { + mScriptHandler = scriptHandler; + } + + @Override + public void remove() { + recordApiCall(ApiCall.REMOVE_DOCUMENT_START_SCRIPT); + mScriptHandler.remove(); + } +}
diff --git a/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibScriptReferenceAdapter.java b/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibScriptReferenceAdapter.java deleted file mode 100644 index 82b11f31..0000000 --- a/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibScriptReferenceAdapter.java +++ /dev/null
@@ -1,28 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.support_lib_glue; - -import static org.chromium.support_lib_glue.SupportLibWebViewChromiumFactory.recordApiCall; - -import org.chromium.android_webview.ScriptReference; -import org.chromium.support_lib_boundary.ScriptReferenceBoundaryInterface; -import org.chromium.support_lib_glue.SupportLibWebViewChromiumFactory.ApiCall; - -/** - * Adapter between ScriptReferenceBoundaryInterface and ScriptReference. - */ -class SupportLibScriptReferenceAdapter implements ScriptReferenceBoundaryInterface { - private ScriptReference mScriptReference; - - public SupportLibScriptReferenceAdapter(ScriptReference scriptReference) { - mScriptReference = scriptReference; - } - - @Override - public void remove() { - recordApiCall(ApiCall.REMOVE_DOCUMENT_START_SCRIPT); - mScriptReference.remove(); - } -}
diff --git a/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromium.java b/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromium.java index 5d4b908..0b0dd257 100644 --- a/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromium.java +++ b/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromium.java
@@ -89,11 +89,11 @@ } @Override - public /* ScriptReference */ InvocationHandler addDocumentStartJavaScript( + public /* ScriptHandler */ InvocationHandler addDocumentStartJavaScript( final String script, final String[] allowedOriginRules) { recordApiCall(ApiCall.ADD_DOCUMENT_START_SCRIPT); return BoundaryInterfaceReflectionUtil.createInvocationHandlerFor( - new SupportLibScriptReferenceAdapter( + new SupportLibScriptHandlerAdapter( mSharedWebViewChromium.addDocumentStartJavaScript( script, allowedOriginRules))); }
diff --git a/ash/app_list/views/app_list_item_view.cc b/ash/app_list/views/app_list_item_view.cc index 5182f81..5ea1eaf 100644 --- a/ash/app_list/views/app_list_item_view.cc +++ b/ash/app_list/views/app_list_item_view.cc
@@ -365,26 +365,16 @@ switch (ui_state) { case UI_STATE_NORMAL: title_->SetVisible(true); - if (ui_state_ == UI_STATE_DRAGGING) { + if (ui_state_ == UI_STATE_DRAGGING) ScaleAppIcon(false); - } else if (ui_state_ == UI_STATE_CARDIFY) { - title_->SetFontList(GetAppListConfig().app_title_font()); - ScaleIconImmediatly(1.0f); - } break; case UI_STATE_DRAGGING: title_->SetVisible(false); - if (ui_state_ == UI_STATE_NORMAL) + if (ui_state_ == UI_STATE_NORMAL && !in_cardified_grid_) ScaleAppIcon(true); break; case UI_STATE_DROPPING_IN_FOLDER: break; - case UI_STATE_CARDIFY: - gfx::FontList font_size = GetAppListConfig().app_title_font(); - const int size_delta = font_size.GetFontSize() * (1 - kCardifyIconScale); - title_->SetFontList(font_size.DeriveWithSizeDelta(-size_delta)); - ScaleIconImmediatly(kCardifyIconScale); - break; } ui_state_ = ui_state; @@ -993,8 +983,18 @@ SetUIState(UI_STATE_DRAGGING); } -void AppListItemView::SetCardifyUIState() { - SetUIState(UI_STATE_CARDIFY); +void AppListItemView::EnterCardifyState() { + in_cardified_grid_ = true; + gfx::FontList font_size = GetAppListConfig().app_title_font(); + const int size_delta = font_size.GetFontSize() * (1 - kCardifyIconScale); + title_->SetFontList(font_size.DeriveWithSizeDelta(-size_delta)); + ScaleIconImmediatly(kCardifyIconScale); +} + +void AppListItemView::ExitCardifyState() { + title_->SetFontList(GetAppListConfig().app_title_font()); + ScaleIconImmediatly(1.0f); + in_cardified_grid_ = false; } void AppListItemView::SetNormalUIState() {
diff --git a/ash/app_list/views/app_list_item_view.h b/ash/app_list/views/app_list_item_view.h index 751dada..a2239b7 100644 --- a/ash/app_list/views/app_list_item_view.h +++ b/ash/app_list/views/app_list_item_view.h
@@ -97,11 +97,13 @@ // Sets UI state to dragging state. void SetDragUIState(); - // Sets UI state to cardify state. - void SetCardifyUIState(); // Sets UI state to normal state. void SetNormalUIState(); + // Handles the icon's scaling and animation for a cardified grid. + void EnterCardifyState(); + void ExitCardifyState(); + // Returns the icon bounds for with |target_bounds| as the bounds of this view // and given |icon_size| and the |icon_scale| if the icon was scaled from the // original display size. @@ -157,7 +159,6 @@ UI_STATE_NORMAL, // Normal UI (icon + label) UI_STATE_DRAGGING, // Dragging UI (scaled icon only) UI_STATE_DROPPING_IN_FOLDER, // Folder dropping preview UI - UI_STATE_CARDIFY, // Cardify UI (scaled icon + label) }; // gfx::AnimationDelegate: @@ -272,6 +273,9 @@ // A11y alerts and a focus ring. bool focus_silently_ = false; + // Whether AppsGridView is in cardified state. + bool in_cardified_grid_ = false; + // The animation that runs when dragged view enters or exits this view. std::unique_ptr<gfx::SlideAnimation> dragged_view_hover_animation_;
diff --git a/ash/app_list/views/apps_grid_view.cc b/ash/app_list/views/apps_grid_view.cc index 02e49e5d..38d7633 100644 --- a/ash/app_list/views/apps_grid_view.cc +++ b/ash/app_list/views/apps_grid_view.cc
@@ -883,7 +883,7 @@ if (cardified_state_) { // Temporarily set to cardified UI State so it animates back to its position // smoothly with all other icons. - released_drag_view->SetCardifyUIState(); + released_drag_view->EnterCardifyState(); // Compensate drag_source_bounds for the translation of the items_container // during AnimateCardifiedState(). gfx::Point start_position = items_container_->origin(); @@ -2349,9 +2349,9 @@ current_bounds.Offset(translate_offset); if (cardified_state_) - entry_view->SetCardifyUIState(); + entry_view->EnterCardifyState(); else - entry_view->SetNormalUIState(); + entry_view->ExitCardifyState(); gfx::Rect target_bounds(view_model_.ideal_bounds(i)); entry_view->SetBoundsRect(target_bounds);
diff --git a/ash/public/cpp/ash_features.cc b/ash/public/cpp/ash_features.cc index e9ac0643..9cd8104 100644 --- a/ash/public/cpp/ash_features.cc +++ b/ash/public/cpp/ash_features.cc
@@ -75,9 +75,6 @@ const base::Feature kMediaSessionNotification{"MediaSessionNotification", base::FEATURE_ENABLED_BY_DEFAULT}; -const base::Feature kMovablePartialScreenshot{ - "MovablePartialScreenshot", base::FEATURE_DISABLED_BY_DEFAULT}; - const base::Feature kNightLight{"NightLight", base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature kNotificationExpansionAnimation{ @@ -305,10 +302,6 @@ return base::FeatureList::IsEnabled(kDisplayAlignAssist); } -bool IsMovablePartialScreenshotEnabled() { - return base::FeatureList::IsEnabled(kMovablePartialScreenshot); -} - bool IsNotificationsInContextMenuEnabled() { return base::FeatureList::IsEnabled(kNotificationsInContextMenu); }
diff --git a/ash/public/cpp/ash_features.h b/ash/public/cpp/ash_features.h index a658bb41..a883736 100644 --- a/ash/public/cpp/ash_features.h +++ b/ash/public/cpp/ash_features.h
@@ -270,8 +270,6 @@ ASH_PUBLIC_EXPORT bool IsDisplayAlignmentAssistanceEnabled(); -ASH_PUBLIC_EXPORT bool IsMovablePartialScreenshotEnabled(); - ASH_PUBLIC_EXPORT bool IsNotificationsInContextMenuEnabled(); ASH_PUBLIC_EXPORT bool IsTemporaryHoldingSpaceEnabled();
diff --git a/ash/shelf/shelf_layout_manager.cc b/ash/shelf/shelf_layout_manager.cc index f3eb5b5..0399f03 100644 --- a/ash/shelf/shelf_layout_manager.cc +++ b/ash/shelf/shelf_layout_manager.cc
@@ -473,6 +473,8 @@ } void ShelfLayoutManager::LayoutShelf(bool animate) { + // Do not animate if the shelf container is animating. + animate &= !IsShelfContainerAnimating(); // The ShelfWidget may be partially closed (no native widget) during shutdown // or before it's been fully initialized so skip layout. if (in_shutdown_ || !shelf_widget_->native_widget()) @@ -1088,7 +1090,11 @@ const bool was_adding_user = state_.IsAddingSecondaryUser(); const bool was_locked = state_.IsScreenLocked(); state_.session_state = state; - MaybeUpdateShelfBackground(AnimationChangeType::ANIMATE); + + // Animate shelf layout if the container is not animating. + bool animate = !IsShelfContainerAnimating(); + MaybeUpdateShelfBackground(animate ? AnimationChangeType::ANIMATE + : AnimationChangeType::IMMEDIATE); HideContextualNudges(); if (was_adding_user != state_.IsAddingSecondaryUser()) { UpdateShelfVisibilityAfterLoginUIChange(); @@ -1101,7 +1107,7 @@ UpdateShelfVisibilityAfterLoginUIChange(); CalculateTargetBoundsAndUpdateWorkArea(); - UpdateBoundsAndOpacity(true /* animate */); + UpdateBoundsAndOpacity(animate); UpdateVisibilityState(); UpdateContextualNudges(); } @@ -1940,7 +1946,7 @@ void ShelfLayoutManager::UpdateShelfVisibilityAfterLoginUIChange() { UpdateVisibilityState(); - LayoutShelf(); + LayoutShelf(/*animate=*/false); } float ShelfLayoutManager::ComputeTargetOpacity(const State& state) const { @@ -2711,4 +2717,18 @@ FROM_HERE, visibility_update_for_tray_callback_.callback()); } +bool ShelfLayoutManager::IsShelfContainerAnimating() const { + // TODO(oshima): We're re-layouting during shelf construction. We probably + // should wait and then layout once after shelf is fully constructed. + if (!shelf_widget_ || !shelf_widget_->native_widget_private() || + !shelf_widget_->GetNativeWindow()) { + return false; + } + return shelf_widget_->GetNativeWindow() + ->parent() + ->layer() + ->GetAnimator() + ->is_animating(); +} + } // namespace ash
diff --git a/ash/shelf/shelf_layout_manager.h b/ash/shelf/shelf_layout_manager.h index ff25296..9eab692 100644 --- a/ash/shelf/shelf_layout_manager.h +++ b/ash/shelf/shelf_layout_manager.h
@@ -522,6 +522,8 @@ // Updates the visibility state because of the change on a status area tray. void UpdateVisibilityStateForTrayBubbleChange(bool bubble_shown); + bool IsShelfContainerAnimating() const; + bool in_shutdown_ = false; // True if the last mouse event was a mouse drag.
diff --git a/ash/system/phonehub/phone_hub_metrics.cc b/ash/system/phonehub/phone_hub_metrics.cc index fc726a9..cb9dbf2e 100644 --- a/ash/system/phonehub/phone_hub_metrics.cc +++ b/ash/system/phonehub/phone_hub_metrics.cc
@@ -24,10 +24,10 @@ return "PhoneHub.InterstitialScreenEvent.TetherConnectionPending"; case Screen::kOnboardingExistingMultideviceUser: return "PhoneHub.InterstitialScreenEvent.Onboarding." - "ExistingMultideviceUser"; + "ExistingMultideviceUser2"; case Screen::kOnboardingNewMultideviceUser: return "PhoneHub.InterstitialScreenEvent.Onboarding." - "NewMultideviceUser"; + "NewMultideviceUser2"; case Screen::kOnboardingDismissPrompt: return "PhoneHub.InterstitialScreenEvent.OnboardingDismissPrompt"; default: @@ -41,6 +41,22 @@ void LogInterstitialScreenEvent(Screen screen, InterstitialScreenEvent event) { base::UmaHistogramEnumeration(GetInterstitialScreenEventHistogramName(screen), event); + + // NOTE(https://crbug.com/1187255): The new- and existing-user metrics were + // previously reversed. For continuity, we continue logging the old metrics in + // reverse. The new metrics + // "PhoneHub.InterstitialScreenEvent.Onboarding.NewMultideviceUser2" and + // "PhoneHub.InterstitialScreenEvent.Onboarding.ExistingMultideviceUser2" are + // logged correctly. + if (screen == Screen::kOnboardingExistingMultideviceUser) { + base::UmaHistogramEnumeration( + "PhoneHub.InterstitialScreenEvent.Onboarding.NewMultideviceUser", + event); + } else if (screen == Screen::kOnboardingNewMultideviceUser) { + base::UmaHistogramEnumeration( + "PhoneHub.InterstitialScreenEvent.Onboarding.ExistingMultideviceUser", + event); + } } void LogScreenOnBubbleOpen(Screen screen) {
diff --git a/ash/system/phonehub/phone_hub_ui_controller.cc b/ash/system/phonehub/phone_hub_ui_controller.cc index 085ea36a5..1d7724e 100644 --- a/ash/system/phonehub/phone_hub_ui_controller.cc +++ b/ash/system/phonehub/phone_hub_ui_controller.cc
@@ -188,11 +188,11 @@ return UiState::kHidden; case FeatureStatus::kEligiblePhoneButNotSetUp: - return should_show_onboarding_ui ? UiState::kOnboardingWithPhone + return should_show_onboarding_ui ? UiState::kOnboardingWithoutPhone : UiState::kHidden; case FeatureStatus::kDisabled: - return should_show_onboarding_ui ? UiState::kOnboardingWithoutPhone + return should_show_onboarding_ui ? UiState::kOnboardingWithPhone : UiState::kHidden; case FeatureStatus::kUnavailableBluetoothOff:
diff --git a/ash/system/phonehub/phone_hub_ui_controller_unittest.cc b/ash/system/phonehub/phone_hub_ui_controller_unittest.cc index f114860..2730a7a 100644 --- a/ash/system/phonehub/phone_hub_ui_controller_unittest.cc +++ b/ash/system/phonehub/phone_hub_ui_controller_unittest.cc
@@ -115,7 +115,8 @@ } TEST_F(PhoneHubUiControllerTest, ShowOnboardingUi_WithoutPhone) { - GetFeatureStatusProvider()->SetStatus(FeatureStatus::kDisabled); + GetFeatureStatusProvider()->SetStatus( + FeatureStatus::kEligiblePhoneButNotSetUp); EXPECT_TRUE(ui_state_changed_); ui_state_changed_ = false; GetOnboardingUiTracker()->SetShouldShowOnboardingUi(true); @@ -129,8 +130,7 @@ } TEST_F(PhoneHubUiControllerTest, ShowOnboardingUi_WithPhone) { - GetFeatureStatusProvider()->SetStatus( - FeatureStatus::kEligiblePhoneButNotSetUp); + GetFeatureStatusProvider()->SetStatus(FeatureStatus::kDisabled); EXPECT_TRUE(ui_state_changed_); ui_state_changed_ = false; GetOnboardingUiTracker()->SetShouldShowOnboardingUi(true);
diff --git a/ash/system/status_area_widget_delegate.cc b/ash/system/status_area_widget_delegate.cc index a68e165c..1961e64 100644 --- a/ash/system/status_area_widget_delegate.cc +++ b/ash/system/status_area_widget_delegate.cc
@@ -209,10 +209,12 @@ } void StatusAreaWidgetDelegate::UpdateLayout(bool animate) { - if (animate) + if (animate) { StatusAreaWidgetDelegateAnimationSettings settings(layer()); - - Layout(); + Layout(); + } else { + Layout(); + } } void StatusAreaWidgetDelegate::ChildPreferredSizeChanged(View* child) { @@ -221,8 +223,17 @@ if (new_size == current_size) return; // Need to re-layout the shelf when trays or items are added/removed. - StatusAreaWidgetDelegateAnimationSettings settings(layer()); - + // don't run uring login or unlock if the shelf container is animating. + std::unique_ptr<StatusAreaWidgetDelegateAnimationSettings> settings; + if (!shelf_->shelf_widget() + ->GetNativeWindow() + ->parent() + ->layer() + ->GetAnimator() + ->is_animating()) { + settings = + std::make_unique<StatusAreaWidgetDelegateAnimationSettings>(layer()); + } shelf_->shelf_layout_manager()->LayoutShelf(/*animate=*/false); }
diff --git a/ash/utility/screenshot_controller.cc b/ash/utility/screenshot_controller.cc index 0057387..c12738c 100644 --- a/ash/utility/screenshot_controller.cc +++ b/ash/utility/screenshot_controller.cc
@@ -10,7 +10,6 @@ #include "ash/accelerators/accelerator_controller_impl.h" #include "ash/display/mouse_cursor_event_filter.h" #include "ash/magnifier/magnifier_glass.h" -#include "ash/public/cpp/ash_features.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/screenshot_delegate.h" #include "ash/shell.h" @@ -21,7 +20,6 @@ #include "ui/aura/client/screen_position_client.h" #include "ui/aura/window_targeter.h" #include "ui/base/cursor/mojom/cursor_type.mojom-shared.h" -#include "ui/base/hit_test.h" #include "ui/compositor/paint_recorder.h" #include "ui/display/screen.h" #include "ui/events/event.h" @@ -30,9 +28,6 @@ #include "ui/events/pointer_details.h" #include "ui/events/types/event_type.h" #include "ui/gfx/canvas.h" -#include "ui/gfx/color_palette.h" -#include "ui/gfx/geometry/point_conversions.h" -#include "ui/gfx/scoped_canvas.h" #include "ui/views/widget/widget.h" #include "ui/wm/core/accelerator_filter.h" #include "ui/wm/core/cursor_manager.h" @@ -88,48 +83,6 @@ return true; } -// Returns the hit test component for |point| on |rect|. -int GetHTComponentForRect(const gfx::Point& point, - const gfx::Rect& rect, - int border_size) { - gfx::Rect corner(rect.origin(), gfx::Size()); - corner.Inset(-border_size, -border_size); - if (corner.Contains(point)) - return HTTOPLEFT; - - corner.Offset(rect.width(), 0); - if (corner.Contains(point)) - return HTTOPRIGHT; - - corner.Offset(0, rect.height()); - if (corner.Contains(point)) - return HTBOTTOMRIGHT; - - corner.Offset(-rect.width(), 0); - if (corner.Contains(point)) - return HTBOTTOMLEFT; - - gfx::Rect horizontal_border(rect.origin(), gfx::Size(rect.width(), 0)); - horizontal_border.Inset(0, -border_size); - if (horizontal_border.Contains(point)) - return HTTOP; - - horizontal_border.Offset(0, rect.height()); - if (horizontal_border.Contains(point)) - return HTBOTTOM; - - gfx::Rect vertical_border(rect.origin(), gfx::Size(0, rect.height())); - vertical_border.Inset(-border_size, 0); - if (vertical_border.Contains(point)) - return HTLEFT; - - vertical_border.Offset(rect.width(), 0); - if (vertical_border.Contains(point)) - return HTRIGHT; - - return HTNOWHERE; -} - } // namespace class ScreenshotController::ScreenshotLayer : public ui::LayerOwner, @@ -352,266 +305,6 @@ DISALLOW_COPY_AND_ASSIGN(ScreenshotLayer); }; -class ScreenshotController::MovableScreenshotLayer - : public ScreenshotLayer::ScreenshotLayer { - public: - MovableScreenshotLayer(ScreenshotController* controller, - ui::Layer* parent, - bool immediate_overlay) - : ScreenshotLayer(controller, parent, immediate_overlay) {} - ~MovableScreenshotLayer() override = default; - - private: - static constexpr SkColor kBorderColor = gfx::kGoogleBlue300; - static constexpr int kBorderStrokePx = 2; - static constexpr int kBorderShadowPx = 1; - static constexpr SkColor kCursorColor = SK_ColorWHITE; - static constexpr SkColor kIconTextBorderColor = - SkColorSetA(gfx::kGoogleGrey900, 0x80); // 0.5 grey900 - static constexpr int kDragHandleSize = 8; - - struct PointerInfo { - static PointerInfo ForEvent(const ui::Event& event) { - if (event.IsMouseEvent()) { - const auto& pointer_details = event.AsMouseEvent()->pointer_details(); - return {pointer_details.pointer_type, pointer_details.id}; - } - - if (event.IsTouchEvent()) { - const auto& pointer_details = event.AsTouchEvent()->pointer_details(); - return {pointer_details.pointer_type, pointer_details.id}; - } - - return PointerInfo(); - } - - bool operator==(const PointerInfo& other) const { - return type == other.type && id == other.id; - } - bool operator!=(const PointerInfo& other) const { - return !(*this == other); - } - - ui::EventPointerType type = ui::EventPointerType::kUnknown; - ui::PointerId id = ui::kPointerIdUnknown; - }; - - void StartDrag(const ui::LocatedEvent& event) { - DCHECK(!drag_pointer_.has_value()); - - gfx::Rect start_region = region(); - - if (start_region.IsEmpty()) { - start_region = gfx::Rect(event.root_location(), gfx::Size()); - start_hit_ = HTBOTTOMRIGHT; - } else { - start_hit_ = GetHTComponentForRect(event.root_location(), start_region, - kDragHandleSize); - } - - if (start_hit_ == HTNOWHERE) { - // TODO(crbug.com/1076605): Complete via confirming bubble. - if (!region().IsEmpty()) - controller()->CompletePartialScreenshot(); - return; - } - - drag_pointer_ = PointerInfo::ForEvent(event); - start_region_ = start_region; - MaybeChangeCursor(ui::mojom::CursorType::kNone); - - ContinueDrag(event); - } - - void ContinueDrag(const ui::LocatedEvent& event) { - if (!drag_pointer_.has_value() || - drag_pointer_.value() != PointerInfo::ForEvent(event)) { - return; - } - - set_cursor_location_in_root(event.root_location()); - - gfx::Point anchor = start_region_.origin(); - gfx::Point ref = event.root_location(); - - if (start_hit_ == HTTOPLEFT) { - anchor = start_region_.bottom_right(); - } - if (start_hit_ == HTTOPRIGHT) { - anchor = start_region_.bottom_left(); - } - if (start_hit_ == HTBOTTOMLEFT) { - anchor = start_region_.top_right(); - } - if (start_hit_ == HTTOP) { - anchor = start_region_.bottom_left(); - ref.set_x(start_region_.right()); - } - if (start_hit_ == HTBOTTOM) { - ref.set_x(start_region_.right()); - } - if (start_hit_ == HTLEFT) { - anchor = start_region_.top_right(); - ref.set_y(start_region_.bottom()); - } - if (start_hit_ == HTRIGHT) { - ref.set_y(start_region_.bottom()); - } - - SetRegion( - gfx::Rect(std::min(anchor.x(), ref.x()), std::min(anchor.y(), ref.y()), - ::abs(anchor.x() - ref.x()), ::abs(anchor.y() - ref.y()))); - - if (!magnifier_glass_) { - MagnifierGlass::Params params{2.0f, 64}; - magnifier_glass_ = std::make_unique<MagnifierGlass>(std::move(params)); - } - aura::Window* event_root = - static_cast<aura::Window*>(event.target())->GetRootWindow(); - magnifier_glass_->ShowFor(event_root, event.root_location()); - - // TODO(crbug.com/1076605): Create/update a magnifier glass to allow - // better alignment for selected region. - } - - void EndDrag(const ui::LocatedEvent& event) { - if (!drag_pointer_.has_value() || - drag_pointer_.value() != PointerInfo::ForEvent(event)) { - return; - } - - ContinueDrag(event); - - drag_pointer_.reset(); - start_region_ = gfx::Rect(); - start_hit_ = HTNOWHERE; - magnifier_glass_->Close(); - - MaybeChangeCursor(ui::mojom::CursorType::kCross); - } - - // ScreenshotLayer::ScreenshotLayer: - void OnPointerPressed(const ui::LocatedEvent& event) override { - if (drag_pointer_.has_value()) - return; - - StartDrag(event); - } - - void OnPointerMoved(const ui::LocatedEvent& event) override { - // TODO(crbug.com/1076605): Change cursor when on resizing border. - } - - void OnPointerDragged(const ui::LocatedEvent& event) override { - ContinueDrag(event); - } - - void OnPointerReleased(const ui::LocatedEvent& event) override { - EndDrag(event); - } - - void OnPaintLayer(const ui::PaintContext& context) override { - ui::PaintRecorder recorder(context, layer()->size()); - auto* canvas = recorder.canvas(); - - // 0.6 grey900 - const SkColor kOverlayColor = SkColorSetA(gfx::kGoogleGrey900, 0x99); - if (draw_inactive_overlay()) - canvas->DrawColor(kOverlayColor); - - if (!region().IsEmpty()) - DrawRegion(canvas); - - DrawPseudoCursor(canvas); - } - - void DrawRegion(gfx::Canvas* canvas) { - gfx::ScopedCanvas scoped_canvas(canvas); - float scale = canvas->UndoDeviceScaleFactor(); - - gfx::RectF rect(region()); - rect.Scale(scale); - - gfx::Rect fill_rect(gfx::ToEnclosingRect(rect)); - canvas->FillRect(fill_rect, SK_ColorBLACK, SkBlendMode::kClear); - - // Add space of border stroke px + shadow so that the border and its shadow - // are drawn outside |fill_rect| and would not be captured as part of the - // screenshot. - rect = gfx::RectF(fill_rect); - rect.Inset(-kBorderStrokePx / 2 - kBorderShadowPx, - -kBorderStrokePx / 2 - kBorderShadowPx); - - cc::PaintFlags flags; - flags.setAntiAlias(true); - flags.setStyle(cc::PaintFlags::kStroke_Style); - - flags.setColor(kIconTextBorderColor); - flags.setStrokeWidth(SkIntToScalar(kBorderStrokePx + 2 * kBorderShadowPx)); - canvas->DrawRect(rect, flags); - - flags.setColor(kBorderColor); - flags.setStrokeWidth(SkIntToScalar(kBorderStrokePx)); - canvas->DrawRect(rect, flags); - - // TODO(crbug.com/1076605): Draw drag handles. - } - - void DrawPseudoCursor(gfx::Canvas* canvas) { - if (!drag_pointer_.has_value()) - return; - - gfx::PointF pseudo_cursor_point(cursor_location_in_root()); - gfx::Vector2dF width(kCursorSize / 2, 0); - gfx::Vector2dF height(0, kCursorSize / 2); - - // If the cursor is above/before region, use negative offset to move - // towards outside of the region. - const int x_dir = pseudo_cursor_point.x() == region().x() ? -1 : 1; - const int y_dir = pseudo_cursor_point.y() == region().y() ? -1 : 1; - - gfx::ScopedCanvas scoped_canvas(canvas); - float scale = canvas->UndoDeviceScaleFactor(); - - pseudo_cursor_point.Scale(scale); - pseudo_cursor_point = gfx::PointF(gfx::ToCeiledPoint(pseudo_cursor_point)); - pseudo_cursor_point.Offset(x_dir * (kBorderStrokePx / 2 + kBorderShadowPx), - y_dir * (kBorderStrokePx / 2 + kBorderShadowPx)); - - width.Scale(scale); - height.Scale(scale); - - cc::PaintFlags flags; - flags.setAntiAlias(true); - flags.setStyle(cc::PaintFlags::kStroke_Style); - flags.setStrokeCap(cc::PaintFlags::kRound_Cap); - - flags.setColor(kIconTextBorderColor); - flags.setStrokeWidth(SkIntToScalar(kBorderStrokePx + 2 * kBorderShadowPx)); - canvas->DrawLine(pseudo_cursor_point - width, pseudo_cursor_point + width, - flags); - canvas->DrawLine(pseudo_cursor_point - height, pseudo_cursor_point + height, - flags); - - flags.setColor(kCursorColor); - flags.setStrokeWidth(SkIntToScalar(kBorderStrokePx)); - canvas->DrawLine(pseudo_cursor_point - width, pseudo_cursor_point + width, - flags); - canvas->DrawLine(pseudo_cursor_point - height, pseudo_cursor_point + height, - flags); - - // TODO(crbug.com/1076605): Draw cursor coordinates. - } - - base::Optional<PointerInfo> drag_pointer_; - gfx::Rect start_region_; - int start_hit_ = HTNOWHERE; - - // Shows a magnifier glass centered at mouse/touch location when changing - // the screenshot region. - std::unique_ptr<MagnifierGlass> magnifier_glass_; -}; - class ScreenshotController::ScopedCursorSetter { public: explicit ScopedCursorSetter(ui::mojom::CursorType cursor) { @@ -720,17 +413,10 @@ mode_ = PARTIAL; display::Screen::GetScreen()->AddObserver(this); for (aura::Window* root : Shell::GetAllRootWindows()) { - if (features::IsMovablePartialScreenshotEnabled()) { - layers_[root] = std::make_unique<MovableScreenshotLayer>( - this, - Shell::GetContainer(root, kShellWindowId_OverlayContainer)->layer(), - draw_overlay_immediately); - } else { - layers_[root] = std::make_unique<ScreenshotLayer>( - this, - Shell::GetContainer(root, kShellWindowId_OverlayContainer)->layer(), - draw_overlay_immediately); - } + layers_[root] = std::make_unique<ScreenshotLayer>( + this, + Shell::GetContainer(root, kShellWindowId_OverlayContainer)->layer(), + draw_overlay_immediately); } if (!pen_events_only_) {
diff --git a/ash/utility/screenshot_controller.h b/ash/utility/screenshot_controller.h index 0f5409f1..3ba1019 100644 --- a/ash/utility/screenshot_controller.h +++ b/ash/utility/screenshot_controller.h
@@ -87,7 +87,6 @@ class ScopedCursorSetter; class ScreenshotLayer; - class MovableScreenshotLayer; // Starts, ends, cancels, or updates the region selection. void CompleteWindowScreenshot();
diff --git a/ash/utility/screenshot_controller_unittest.cc b/ash/utility/screenshot_controller_unittest.cc index 10cb0c7..de7b7ee 100644 --- a/ash/utility/screenshot_controller_unittest.cc +++ b/ash/utility/screenshot_controller_unittest.cc
@@ -8,7 +8,6 @@ #include "ash/display/mirror_window_test_api.h" #include "ash/display/mouse_cursor_event_filter.h" #include "ash/display/window_tree_host_manager.h" -#include "ash/public/cpp/ash_features.h" #include "ash/screenshot_delegate.h" #include "ash/shell.h" #include "ash/test/ash_test_base.h" @@ -16,7 +15,6 @@ #include "ash/test_screenshot_delegate.h" #include "ash/wm/window_util.h" #include "base/run_loop.h" -#include "base/test/scoped_feature_list.h" #include "ui/aura/env.h" #include "ui/aura/window_event_dispatcher.h" #include "ui/base/cursor/cursor.h" @@ -152,72 +150,6 @@ EXPECT_FALSE(IsActive()); } -TEST_F(PartialScreenshotControllerTest, Movable) { - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeature(features::kMovablePartialScreenshot); - - TestScreenshotDelegate* test_delegate = GetScreenshotDelegate(); - ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow()); - - // Test data to exercise on an initial region of 10+20-50x50. - struct { - const gfx::Point drag_start; - const gfx::Point drag_end; - const gfx::Rect expected_region; - } kTestCases[] = { - // Drag from top-left. |drag_end| becomes the new origin. - {gfx::Point(10, 20), gfx::Point(20, 30), gfx::Rect(20, 30, 40, 40)}, - // Drag from top-right. |drag_end| becomes the new top-right. - {gfx::Point(60, 20), gfx::Point(20, 30), gfx::Rect(10, 30, 10, 40)}, - // Drag from bottom-left. |drag_end| becomes the new bottom-left. - {gfx::Point(10, 70), gfx::Point(20, 30), gfx::Rect(20, 20, 40, 10)}, - // Drag from bottom-right. |drag_end| becomes the new bottom-right. - {gfx::Point(60, 70), gfx::Point(20, 30), gfx::Rect(10, 20, 10, 10)}, - - // Drag from top. |drag_end|'s y becomes new top. - {gfx::Point(30, 20), gfx::Point(20, 30), gfx::Rect(10, 30, 50, 40)}, - // Drag from top. |drag_end|'s y becomes new bottom. - {gfx::Point(30, 20), gfx::Point(20, 80), gfx::Rect(10, 70, 50, 10)}, - - // Drag from left. |drag_end|'x becomes the new left. - {gfx::Point(10, 30), gfx::Point(20, 30), gfx::Rect(20, 20, 40, 50)}, - // Drag from left. |drag_end|'x becomes the new right. - {gfx::Point(10, 30), gfx::Point(70, 30), gfx::Rect(60, 20, 10, 50)}, - - // Drag from right. |drag_end|'x becomes the new right. - {gfx::Point(60, 30), gfx::Point(20, 30), gfx::Rect(10, 20, 10, 50)}, - // Drag from right. |drag_end|'x becomes the new left. - {gfx::Point(60, 30), gfx::Point(5, 30), gfx::Rect(5, 20, 5, 50)}, - - // Drag from bottom. |drag_end|'y becomes the new bottom. - {gfx::Point(30, 70), gfx::Point(20, 30), gfx::Rect(10, 20, 50, 10)}, - // Drag from bottom. |drag_end|'y becomes the new top. - {gfx::Point(30, 70), gfx::Point(20, 10), gfx::Rect(10, 10, 50, 10)}, - }; - for (size_t i = 0; i < base::size(kTestCases); ++i) { - const auto& test = kTestCases[i]; - SCOPED_TRACE(testing::Message() - << ", i=" << i << "start=" << test.drag_start.ToString() - << ", end=" << test.drag_end.ToString() - << ", expect=" << test.expected_region.ToString()); - - StartPartialScreenshotSession(); - generator.MoveMouseTo(10, 20); - generator.DragMouseBy(50, 50); - - generator.MoveMouseTo(test.drag_start); - generator.DragMouseTo(test.drag_end); - - // Complete partial screenshot selection by clicking outside the region. - generator.MoveMouseTo(0, 0); - generator.ClickLeftButton(); - - EXPECT_EQ(test.expected_region, test_delegate->last_rect()); - EXPECT_EQ(static_cast<int>(i + 1), - test_delegate->handle_take_partial_screenshot_count()); - } -} - TEST_F(PartialScreenshotControllerTest, BasicTouch) { StartPartialScreenshotSession(); TestScreenshotDelegate* test_delegate = GetScreenshotDelegate();
diff --git a/base/BUILD.gn b/base/BUILD.gn index 5288a27..43bd572 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -2240,6 +2240,8 @@ "trace_event/memory_dump_scheduler.h", "trace_event/memory_infra_background_allowlist.cc", "trace_event/memory_infra_background_allowlist.h", + "trace_event/memory_pressure_level_proto.cc", + "trace_event/memory_pressure_level_proto.h", "trace_event/memory_usage_estimator.cc", "trace_event/memory_usage_estimator.h", "trace_event/optional_trace_event.h",
diff --git a/base/allocator/partition_allocator/pcscan.cc b/base/allocator/partition_allocator/pcscan.cc index 43d20dc..5d533b0a 100644 --- a/base/allocator/partition_allocator/pcscan.cc +++ b/base/allocator/partition_allocator/pcscan.cc
@@ -1259,10 +1259,13 @@ [](Root* root) { return root->IsQuarantineEnabled(); })); #endif - if (state_.exchange(State::kScheduled, std::memory_order_acq_rel) != - State::kNotRunning) { - // Bail out if PCScan is already in progress. - return; + { + // If scanning is already in progress, bail out. + State expected = State::kNotRunning; + if (!state_.compare_exchange_strong(expected, State::kScheduled, + std::memory_order_acq_rel, + std::memory_order_relaxed)) + return; } quarantine_data_.ResetAndAdvanceEpoch();
diff --git a/base/logging.cc b/base/logging.cc index 3311c49..b4d44d9 100644 --- a/base/logging.cc +++ b/base/logging.cc
@@ -794,6 +794,11 @@ severity = FX_LOG_ERROR; break; } + // TODO(https://crbug.com/1188820): Integrate verbose levels with the switch + // statement. + if (severity_ <= LOGGING_VERBOSE) { + severity = FX_LOG_DEBUG; + } fx_logger_t* logger = fx_log_get_logger(); if (logger) {
diff --git a/base/memory/memory_pressure_listener.cc b/base/memory/memory_pressure_listener.cc index 391d4e8d..623ae26 100644 --- a/base/memory/memory_pressure_listener.cc +++ b/base/memory/memory_pressure_listener.cc
@@ -7,6 +7,11 @@ #include "base/observer_list_threadsafe.h" #include "base/threading/sequenced_task_runner_handle.h" #include "base/trace_event/base_tracing.h" +#include "base/tracing_buildflags.h" + +#if BUILDFLAG(ENABLE_BASE_TRACING) +#include "base/trace_event/memory_pressure_level_proto.h" // no-presubmit-check +#endif namespace base { @@ -66,23 +71,6 @@ } // namespace -#if BUILDFLAG(ENABLE_BASE_TRACING) -// static -perfetto::protos::pbzero::MemoryPressureLevel -MemoryPressureListener::LevelAsTraceEnum( - MemoryPressureListener::MemoryPressureLevel memory_pressure_level) { - using ProtoLevel = perfetto::protos::pbzero::MemoryPressureLevel; - switch (memory_pressure_level) { - case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE: - return ProtoLevel::MEMORY_PRESSURE_LEVEL_NONE; - case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE: - return ProtoLevel::MEMORY_PRESSURE_LEVEL_MODERATE; - case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL: - return ProtoLevel::MEMORY_PRESSURE_LEVEL_CRITICAL; - } -} -#endif - MemoryPressureListener::MemoryPressureListener( const base::Location& creation_location, const MemoryPressureListener::MemoryPressureCallback& callback) @@ -111,7 +99,8 @@ [&](perfetto::EventContext ctx) { auto* event = ctx.event<perfetto::protos::pbzero::ChromeTrackEvent>(); auto* data = event->set_chrome_memory_pressure_notification(); - data->set_level(LevelAsTraceEnum(memory_pressure_level)); + data->set_level( + trace_event::MemoryPressureLevelToTraceEnum(memory_pressure_level)); data->set_creation_location_iid( base::trace_event::InternedSourceLocation::Get( &ctx, @@ -137,7 +126,8 @@ [&](perfetto::EventContext ctx) { auto* event = ctx.event<perfetto::protos::pbzero::ChromeTrackEvent>(); auto* data = event->set_chrome_memory_pressure_notification(); - data->set_level(LevelAsTraceEnum(memory_pressure_level)); + data->set_level( + trace_event::MemoryPressureLevelToTraceEnum(memory_pressure_level)); }); if (AreNotificationsSuppressed()) return;
diff --git a/base/memory/memory_pressure_listener.h b/base/memory/memory_pressure_listener.h index 7ae221d..802d4c7 100644 --- a/base/memory/memory_pressure_listener.h +++ b/base/memory/memory_pressure_listener.h
@@ -16,10 +16,6 @@ #include "base/macros.h" #include "base/tracing_buildflags.h" -#if BUILDFLAG(ENABLE_BASE_TRACING) -#include "base/tracing/protos/chrome_track_event.pbzero.h" // nogncheck -#endif - namespace base { // To start listening, create a new instance, passing a callback to a @@ -77,11 +73,6 @@ kMaxValue = MEMORY_PRESSURE_LEVEL_CRITICAL, }; -#if BUILDFLAG(ENABLE_BASE_TRACING) - static perfetto::protos::pbzero::MemoryPressureLevel LevelAsTraceEnum( - MemoryPressureListener::MemoryPressureLevel memory_pressure_level); -#endif - using MemoryPressureCallback = RepeatingCallback<void(MemoryPressureLevel)>; using SyncMemoryPressureCallback = RepeatingCallback<void(MemoryPressureLevel)>;
diff --git a/base/trace_event/memory_pressure_level_proto.cc b/base/trace_event/memory_pressure_level_proto.cc new file mode 100644 index 0000000..3b4a594a --- /dev/null +++ b/base/trace_event/memory_pressure_level_proto.cc
@@ -0,0 +1,31 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// MemoryPressure provides static APIs for handling memory pressure on +// platforms that have such signals, such as Android and ChromeOS. +// The app will try to discard buffers that aren't deemed essential (individual +// modules will implement their own policy). + +#include "base/trace_event/memory_pressure_level_proto.h" + +#include "base/tracing/protos/chrome_track_event.pbzero.h" // nogncheck + +namespace base { +namespace trace_event { + +perfetto::protos::pbzero::MemoryPressureLevel MemoryPressureLevelToTraceEnum( + MemoryPressureListener::MemoryPressureLevel memory_pressure_level) { + using ProtoLevel = perfetto::protos::pbzero::MemoryPressureLevel; + switch (memory_pressure_level) { + case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE: + return ProtoLevel::MEMORY_PRESSURE_LEVEL_NONE; + case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE: + return ProtoLevel::MEMORY_PRESSURE_LEVEL_MODERATE; + case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL: + return ProtoLevel::MEMORY_PRESSURE_LEVEL_CRITICAL; + } +} + +} // namespace trace_event +} // namespace base
diff --git a/base/trace_event/memory_pressure_level_proto.h b/base/trace_event/memory_pressure_level_proto.h new file mode 100644 index 0000000..d60d43dc --- /dev/null +++ b/base/trace_event/memory_pressure_level_proto.h
@@ -0,0 +1,27 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// MemoryPressure provides static APIs for handling memory pressure on +// platforms that have such signals, such as Android and ChromeOS. +// The app will try to discard buffers that aren't deemed essential (individual +// modules will implement their own policy). + +#ifndef BASE_TRACE_EVENT_MEMORY_PRESSURE_LEVEL_PROTO_H_ +#define BASE_TRACE_EVENT_MEMORY_PRESSURE_LEVEL_PROTO_H_ + +#include "base/base_export.h" +#include "base/memory/memory_pressure_listener.h" +#include "base/tracing/protos/chrome_track_event.pbzero.h" + +namespace base { +namespace trace_event { + +BASE_EXPORT perfetto::protos::pbzero::MemoryPressureLevel +MemoryPressureLevelToTraceEnum( + MemoryPressureListener::MemoryPressureLevel memory_pressure_level); + +} +} // namespace base + +#endif // BASE_TRACE_EVENT_MEMORY_PRESSURE_LEVEL_PROTO_H_
diff --git a/base/util/memory_pressure/multi_source_memory_pressure_monitor.cc b/base/util/memory_pressure/multi_source_memory_pressure_monitor.cc index ce5d8c0..32cbc1e 100644 --- a/base/util/memory_pressure/multi_source_memory_pressure_monitor.cc +++ b/base/util/memory_pressure/multi_source_memory_pressure_monitor.cc
@@ -10,8 +10,13 @@ #include "base/metrics/histogram_macros.h" #include "base/time/time.h" #include "base/trace_event/base_tracing.h" +#include "base/tracing_buildflags.h" #include "base/util/memory_pressure/system_memory_pressure_evaluator.h" +#if BUILDFLAG(ENABLE_BASE_TRACING) +#include "base/trace_event/memory_pressure_level_proto.h" // no-presubmit-check +#endif + namespace util { MultiSourceMemoryPressureMonitor::MultiSourceMemoryPressureMonitor() @@ -86,7 +91,8 @@ [&](perfetto::EventContext ctx) { auto* event = ctx.event<perfetto::protos::pbzero::ChromeTrackEvent>(); auto* data = event->set_chrome_memory_pressure_notification(); - data->set_level(base::MemoryPressureListener::LevelAsTraceEnum(level)); + data->set_level( + base::trace_event::MemoryPressureLevelToTraceEnum(level)); }); // Records the duration of the latest pressure session, there are 4
diff --git a/base/win/embedded_i18n/language_selector.h b/base/win/embedded_i18n/language_selector.h index 84d1e9cd..c439edd 100644 --- a/base/win/embedded_i18n/language_selector.h +++ b/base/win/embedded_i18n/language_selector.h
@@ -22,7 +22,7 @@ namespace i18n { // Selects a language from a set of available translations based on the user's -// preferred language list. An optional preferred langauge may be provided to +// preferred language list. An optional preferred language may be provided to // override selection should a corresponding translation be available. class BASE_EXPORT LanguageSelector { public: @@ -40,8 +40,8 @@ span<const LangToOffset> languages_to_offset); // Constructor for testing purposes. - // |candidates| is a list of all candiate languages that can be used to - // determine which langauge to use. + // |candidates| is a list of all candidate languages that can be used to + // determine which language to use. // |languages_to_offset_begin| and |languages_to_offset_end| point to a sorted // array of language identifiers (and their offsets) for which translations // are available.
diff --git a/build/android/test_runner.py b/build/android/test_runner.py index b11ce23..ae7d1bcb 100755 --- a/build/android/test_runner.py +++ b/build/android/test_runner.py
@@ -904,6 +904,27 @@ global_tags=list(global_results_tags), indent=2) + test_class_to_file_name_dict = {} + # Test Location is only supported for instrumentation tests as it + # requires the size-info file. + if test_instance.TestType() == 'instrumentation': + test_class_to_file_name_dict = _CreateClassToFileNameDict(args.test_apk) + + if result_sink_client: + for run in all_raw_results: + for results in run: + for r in results.GetAll(): + # Matches chrome.page_info.PageInfoViewTest#testChromePage + match = re.search(r'^(.+\..+)#', r.GetName()) + test_file_name = test_class_to_file_name_dict.get( + match.group(1)) if match else None + # Some tests put in non utf-8 char as part of the test + # which breaks uploads, so need to decode and re-encode. + result_sink_client.Post( + r.GetName(), r.GetType(), r.GetDuration(), + r.GetLog().decode('utf-8', 'replace').encode('utf-8'), + test_file_name) + @contextlib.contextmanager def upload_logcats_file(): try: @@ -964,29 +985,11 @@ for r in reversed(raw_results): iteration_results.AddTestRunResults(r) all_iteration_results.append(iteration_results) - - test_class_to_file_name_dict = {} - # Test Location is only supported for instrumentation tests as it - # requires the size-info file. - if test_instance.TestType() == 'instrumentation': - test_class_to_file_name_dict = _CreateClassToFileNameDict( - args.test_apk) - iteration_count += 1 - for r in iteration_results.GetAll(): - if result_sink_client: - # Matches chrome.page_info.PageInfoViewTest#testChromePage - match = re.search(r'^(.+\..+)#', r.GetName()) - test_file_name = test_class_to_file_name_dict.get( - match.group(1)) if match else None - # Some tests put in non utf-8 char as part of the test - # which breaks uploads, so need to decode and re-encode. - result_sink_client.Post( - r.GetName(), r.GetType(), r.GetDuration(), - r.GetLog().decode('utf-8', 'replace').encode('utf-8'), - test_file_name) + for r in iteration_results.GetAll(): result_counts[r.GetName()][r.GetType()] += 1 + report_results.LogFull( results=iteration_results, test_type=test_instance.TestType(),
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java index f6d9c1a2..7cb2128 100644 --- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java +++ b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java
@@ -651,18 +651,21 @@ public boolean onBackPressed() { boolean isOnHomepage = mStartSurfaceState == StartSurfaceState.SHOWN_HOMEPAGE; + // When the SecondaryTasksSurface is shown, the TabGridDialog is controlled by + // mSecondaryTasksSurfaceController, while the TabSelectionEditor dialog is controlled + // by mController. Therefore, we need to check both controllers whether any dialog is + // visible. If so, the corresponding controller will handle the back button. + // When the Start surface is shown, tapping "Group Tabs" from menu will also show the + // the TabSelectionEditor dialog. Therefore, we need to check both controllers as well. + if (mSecondaryTasksSurfaceController != null + && mSecondaryTasksSurfaceController.isDialogVisible()) { + return mSecondaryTasksSurfaceController.onBackPressed(isOnHomepage); + } else if (mController.isDialogVisible()) { + return mController.onBackPressed(isOnHomepage); + } + if (mStartSurfaceState == StartSurfaceState.SHOWN_TABSWITCHER) { - // When the SecondaryTasksSurface is shown, the TabGridDialog is controlled by - // mSecondaryTasksSurfaceController, while the TabSelectionEditor dialog is controlled - // by mController. Therefore, we need to check both controllers whether any dialog is - // visible. If so, the corresponding controller will handle the back button. - if (mSecondaryTasksSurfaceController != null - && mSecondaryTasksSurfaceController.isDialogVisible()) { - return mSecondaryTasksSurfaceController.onBackPressed(isOnHomepage); - } else if (mController.isDialogVisible()) { - return mController.onBackPressed(isOnHomepage); - } else if (mPreviousStartSurfaceState == StartSurfaceState.SHOWN_HOMEPAGE - && !mIsIncognito) { + if (mPreviousStartSurfaceState == StartSurfaceState.SHOWN_HOMEPAGE && !mIsIncognito) { // Secondary tasks surface is used as the main surface in incognito mode. // If we reached Tab switcher from HomePage, and there isn't any dialog shown, // updates the state, and ChromeTabbedActivity will handle the back button.
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java index 964a755..9f4f5e7 100644 --- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java +++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java
@@ -57,6 +57,7 @@ import android.widget.LinearLayout; import android.widget.TextView; +import androidx.recyclerview.widget.RecyclerView; import androidx.test.espresso.Espresso; import androidx.test.espresso.UiController; import androidx.test.espresso.ViewAction; @@ -1683,6 +1684,82 @@ @Test @LargeTest @Feature({"StartSurface"}) + @EnableFeatures(ChromeFeatureList.TAB_GROUPS_ANDROID) + // clang-format off + @CommandLineFlags.Add({BASE_PARAMS + "/single"}) + public void testShow_SingleAsHomepage_BackButtonOnHomepageWithGroupTabsDialog() + throws ExecutionException { + // clang-format on + backButtonOnHomepageWithGroupTabsDialogImpl(); + } + + @Test + @LargeTest + @Feature({"StartSurface"}) + @EnableFeatures(ChromeFeatureList.TAB_GROUPS_ANDROID) + // clang-format off + @CommandLineFlags.Add({BASE_PARAMS + "/single/show_last_active_tab_only/true"}) + public void testShow_SingleAsHomepageV2_BackButtonOnHomepageWithGroupTabsDialog() + throws ExecutionException { + // clang-format on + backButtonOnHomepageWithGroupTabsDialogImpl(); + } + + private void backButtonOnHomepageWithGroupTabsDialogImpl() throws ExecutionException { + if (!mImmediateReturn) { + pressHomePageButton(); + } + + ChromeTabbedActivity cta = mActivityTestRule.getActivity(); + CriteriaHelper.pollUiThread( + () -> cta.getLayoutManager() != null && cta.getLayoutManager().overviewVisible()); + waitForTabModel(); + TabUiTestHelper.verifyTabModelTabCount(cta, 1, 0); + onViewWaiting(withId(R.id.logo)); + + // Launches the first site in MV tiles to create the second tab for grouping. + LinearLayout tilesLayout = + cta.findViewById(org.chromium.chrome.tab_ui.R.id.mv_tiles_layout); + TestThreadUtils.runOnUiThreadBlocking(() -> tilesLayout.getChildAt(0).performClick()); + CriteriaHelper.pollUiThread(() -> !cta.getLayoutManager().overviewVisible()); + // Verifies a new Tab is created. + TabUiTestHelper.verifyTabModelTabCount(cta, 2, 0); + + // When show_last_active_tab_only is enabled, we need to enter the tab switcher first to + // initialize the secondary task surface which shows the TabSelectionEditor dialog. + onViewWaiting(withId(org.chromium.chrome.tab_ui.R.id.tab_switcher_button)); + TabUiTestHelper.enterTabSwitcher(cta); + waitForView(withId(R.id.secondary_tasks_surface_view)); + List<Tab> tabs = + getTabsInCurrentTabModel(mActivityTestRule.getActivity().getCurrentTabModel()); + TabSelectionEditorTestingRobot robot = new TabSelectionEditorTestingRobot(); + + // Enters the homepage, and shows the TabSelectionEditor dialog. + pressHomePageButton(); + waitForView(withId(R.id.primary_tasks_surface_view)); + + StartSurfaceCoordinator startSurfaceCoordinator = getStartSurfaceFromUIThread(); + TestThreadUtils.runOnUiThreadBlocking( + () -> startSurfaceCoordinator.showTabSelectionEditorForTesting(tabs)); + robot.resultRobot.verifyTabSelectionEditorIsVisible() + .verifyToolbarActionButtonDisabled() + .verifyToolbarActionButtonWithResourceId( + org.chromium.chrome.tab_ui.R.string.tab_selection_editor_group) + .verifyToolbarSelectionTextWithResourceId( + org.chromium.chrome.tab_ui.R.string + .tab_selection_editor_toolbar_select_tabs) + .verifyAdapterHasItemCount(tabs.size()) + .verifyHasAtLeastNItemVisible(2); + + // Verifies that tapping the back button will close the TabSelectionEditor. + pressBack(); + robot.resultRobot.verifyTabSelectionEditorIsHidden(); + onView(allOf(withId(R.id.primary_tasks_surface_view), isDisplayed())); + } + + @Test + @LargeTest + @Feature({"StartSurface"}) @DisableIf.Build(sdk_is_less_than = M, message = "https://crbug.com/1170553") @CommandLineFlags.Add({BASE_PARAMS + "/single/omnibox_focused_on_new_tab/true"}) public void testOmnibox_FocusedOnNewTabInSingleSurface() { @@ -1985,6 +2062,142 @@ .check(matches(withEffectiveVisibility(GONE))); } + @Test + @LargeTest + @Feature({"StartSurface"}) + // clang-format off + @CommandLineFlags.Add({BASE_PARAMS + "/single/show_tabs_in_mru_order/true"}) + public void testShow_SingleAsHomepage_ShowTabsInMRUOrder() throws ExecutionException { + // clang-format on + if (!mImmediateReturn) { + pressHomePageButton(); + } + + ChromeTabbedActivity cta = mActivityTestRule.getActivity(); + CriteriaHelper.pollUiThread( + () -> cta.getLayoutManager() != null && cta.getLayoutManager().overviewVisible()); + waitForTabModel(); + TabUiTestHelper.verifyTabModelTabCount(cta, 1, 0); + onViewWaiting(withId(R.id.logo)); + Tab tab1 = cta.getCurrentTabModel().getTabAt(0); + + // Launches the first site in MV tiles. + LinearLayout tilesLayout = + cta.findViewById(org.chromium.chrome.tab_ui.R.id.mv_tiles_layout); + TestThreadUtils.runOnUiThreadBlocking(() -> tilesLayout.getChildAt(0).performClick()); + CriteriaHelper.pollUiThread(() -> !cta.getLayoutManager().overviewVisible()); + TabUiTestHelper.verifyTabModelTabCount(cta, 2, 0); + Tab tab2 = cta.getActivityTab(); + // Verifies that the titles of the two Tabs are different. + TestThreadUtils.runOnUiThreadBlocking( + () -> { Assert.assertNotEquals(tab1.getTitle(), tab2.getTitle()); }); + + // Returns to the Start surface. + OverviewModeBehaviorWatcher overviewModeWatcher = new OverviewModeBehaviorWatcher( + mActivityTestRule.getActivity().getLayoutManager(), true, false); + pressHomePageButton(); + overviewModeWatcher.waitForBehavior(); + waitForView(allOf( + withParent(withId(org.chromium.chrome.tab_ui.R.id.carousel_tab_switcher_container)), + withId(org.chromium.chrome.tab_ui.R.id.tab_list_view))); + + RecyclerView recyclerView = mActivityTestRule.getActivity().findViewById( + org.chromium.chrome.tab_ui.R.id.tab_list_view); + assertEquals(2, recyclerView.getChildCount()); + // Verifies that the tabs are shown in MRU order: the first card in the carousel Tab + // switcher is the last created Tab by tapping the MV tile; the second card is the Tab + // created or restored in setup(). + RecyclerView.ViewHolder firstViewHolder = recyclerView.findViewHolderForAdapterPosition(0); + TextView title1 = + firstViewHolder.itemView.findViewById(org.chromium.chrome.tab_ui.R.id.tab_title); + TestThreadUtils.runOnUiThreadBlocking( + () -> Assert.assertEquals(tab2.getTitle(), title1.getText())); + + RecyclerView.ViewHolder secondViewHolder = recyclerView.findViewHolderForAdapterPosition(1); + TextView title2 = + secondViewHolder.itemView.findViewById(org.chromium.chrome.tab_ui.R.id.tab_title); + TestThreadUtils.runOnUiThreadBlocking( + () -> Assert.assertEquals(tab1.getTitle(), title2.getText())); + } + + @Test + @LargeTest + @Feature({"StartSurface"}) + // clang-format off + @CommandLineFlags.Add({BASE_PARAMS + "/single/show_tabs_in_mru_order/true"}) + public void testShow_TabSwitcher_ShowTabsInMRUOrder() throws ExecutionException { + // clang-format on + tabSwitcher_ShowTabsInMRUOrderImpl(); + } + + @Test + @LargeTest + @Feature({"StartSurface"}) + @EnableFeatures(ChromeFeatureList.TAB_GROUPS_ANDROID) + // clang-format off + @CommandLineFlags.Add({BASE_PARAMS + + "/single/show_tabs_in_mru_order/true/show_last_active_tab_only/true"}) + public void testShowV2_TabSwitcher_ShowTabsInMRUOrder() throws ExecutionException { + // clang-format on + tabSwitcher_ShowTabsInMRUOrderImpl(); + } + + private void tabSwitcher_ShowTabsInMRUOrderImpl() throws ExecutionException { + if (!mImmediateReturn) { + pressHomePageButton(); + } + + ChromeTabbedActivity cta = mActivityTestRule.getActivity(); + CriteriaHelper.pollUiThread( + () -> cta.getLayoutManager() != null && cta.getLayoutManager().overviewVisible()); + waitForTabModel(); + TabUiTestHelper.verifyTabModelTabCount(cta, 1, 0); + onViewWaiting(withId(R.id.logo)); + Tab tab1 = cta.getCurrentTabModel().getTabAt(0); + + // Launches the first site in MV tiles. + LinearLayout tilesLayout = + cta.findViewById(org.chromium.chrome.tab_ui.R.id.mv_tiles_layout); + TestThreadUtils.runOnUiThreadBlocking(() -> tilesLayout.getChildAt(0).performClick()); + CriteriaHelper.pollUiThread(() -> !cta.getLayoutManager().overviewVisible()); + TabUiTestHelper.verifyTabModelTabCount(cta, 2, 0); + Tab tab2 = cta.getActivityTab(); + + // Verifies that the titles of the two Tabs are different. + TestThreadUtils.runOnUiThreadBlocking( + () -> { Assert.assertNotEquals(tab1.getTitle(), tab2.getTitle()); }); + + if (isInstantReturn()) { + // TODO(crbug.com/1076274): fix toolbar to avoid wrongly focusing on the toolbar + // omnibox. + return; + } + // Enter the Tab switcher. + TabUiTestHelper.enterTabSwitcher(cta); + waitForView(allOf(withParent(withId(R.id.secondary_tasks_surface_view)), + withId(org.chromium.chrome.tab_ui.R.id.tab_list_view))); + + ViewGroup secondaryTaskSurface = + mActivityTestRule.getActivity().findViewById(R.id.secondary_tasks_surface_view); + RecyclerView recyclerView = + secondaryTaskSurface.findViewById(org.chromium.chrome.tab_ui.R.id.tab_list_view); + assertEquals(2, recyclerView.getChildCount()); + // Verifies that the tabs are shown in MRU order: the first card in the Tab switcher is the + // last created Tab by tapping the MV tile; the second card is the Tab created or restored + // in setup(). + RecyclerView.ViewHolder firstViewHolder = recyclerView.findViewHolderForAdapterPosition(0); + TextView title1 = + firstViewHolder.itemView.findViewById(org.chromium.chrome.tab_ui.R.id.tab_title); + TestThreadUtils.runOnUiThreadBlocking( + () -> Assert.assertEquals(tab2.getTitle(), title1.getText())); + + RecyclerView.ViewHolder secondViewHolder = recyclerView.findViewHolderForAdapterPosition(1); + TextView title2 = + secondViewHolder.itemView.findViewById(org.chromium.chrome.tab_ui.R.id.tab_title); + TestThreadUtils.runOnUiThreadBlocking( + () -> Assert.assertEquals(tab1.getTitle(), title2.getText())); + } + private void scrollToolbar() { waitForTabModel(); TabUiTestHelper.verifyTabModelTabCount(mActivityTestRule.getActivity(), 1, 0);
diff --git a/chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/start_surface/StartSurfaceConfiguration.java b/chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/start_surface/StartSurfaceConfiguration.java index e9d6fa5d..20212e82 100644 --- a/chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/start_surface/StartSurfaceConfiguration.java +++ b/chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/start_surface/StartSurfaceConfiguration.java
@@ -92,6 +92,11 @@ new StringCachedFieldTrialParameter( ChromeFeatureList.START_SURFACE_ANDROID, NEW_SURFACE_PARAM, ""); + private static final String SHOW_TABS_IN_MRU_ORDER_PARAM = "show_tabs_in_mru_order"; + public static final BooleanCachedFieldTrialParameter SHOW_TABS_IN_MRU_ORDER = + new BooleanCachedFieldTrialParameter( + ChromeFeatureList.START_SURFACE_ANDROID, SHOW_TABS_IN_MRU_ORDER_PARAM, false); + private static final String STARTUP_UMA_PREFIX = "Startup.Android."; private static final String INSTANT_START_SUBFIX = ".Instant"; private static final String REGULAR_START_SUBFIX = ".NoInstant";
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java index 3aa50ae..c822ab28 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java
@@ -730,13 +730,15 @@ @Override public boolean onBackPressed(boolean isOnHomepage) { - if (!mContainerViewModel.get(IS_VISIBLE)) return false; - + // The TabSelectionEditor dialog can be shown on the Start surface without showing the Grid + // Tab switcher, so skip the check of visibility of mContainerViewModel here. if (mTabSelectionEditorController != null && mTabSelectionEditorController.handleBackPressed()) { return true; } + if (!mContainerViewModel.get(IS_VISIBLE)) return false; + if (mTabGridDialogController != null && mTabGridDialogController.handleBackPressed()) { return true; } @@ -810,7 +812,9 @@ */ static boolean isShowingTabsInMRUOrder() { String feature = StartSurfaceConfiguration.START_SURFACE_VARIATION.getValue(); - return TextUtils.equals(feature, "twopanes"); + return TextUtils.equals(feature, "twopanes") + || StartSurfaceConfiguration.SHOW_TABS_IN_MRU_ORDER.getValue() + && TextUtils.equals(feature, "single"); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/DEPS b/chrome/android/java/src/org/chromium/chrome/browser/DEPS index 0ab8300..e126ddae 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/DEPS +++ b/chrome/android/java/src/org/chromium/chrome/browser/DEPS
@@ -205,9 +205,6 @@ "AndroidPaymentApp\.java": [ "+chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java", ], - "CardEditor\.java": [ - "+chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java", - ], "ChromePaymentRequestFactory\.java": [ "+chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java", ],
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 cb7c439..fec9372 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
@@ -72,7 +72,6 @@ ChromeFeatureList.PAINT_PREVIEW_DEMO, ChromeFeatureList.PAINT_PREVIEW_SHOW_ON_STARTUP, ChromeFeatureList.PRIORITIZE_BOOTSTRAP_TASKS, - ChromeFeatureList.SHARE_BY_DEFAULT_IN_CCT, ChromeFeatureList.START_SURFACE_ANDROID, ChromeFeatureList.SWAP_PIXEL_FORMAT_TO_FIX_CONVERT_FROM_TRANSLUCENT, ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID, @@ -106,6 +105,7 @@ StartSurfaceConfiguration.HOME_BUTTON_ON_GRID_TAB_SWITCHER, StartSurfaceConfiguration.NEW_SURFACE_FROM_HOME_BUTTON, StartSurfaceConfiguration.OMNIBOX_FOCUSED_ON_NEW_TAB, + StartSurfaceConfiguration.SHOW_TABS_IN_MRU_ORDER, StartSurfaceConfiguration.START_SURFACE_EXCLUDE_MV_TILES, StartSurfaceConfiguration.START_SURFACE_HIDE_INCOGNITO_SWITCH_NO_TAB, StartSurfaceConfiguration.START_SURFACE_LAST_ACTIVE_TAB_ONLY,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/tabmodel/TabModelOrchestrator.java b/chrome/android/java/src/org/chromium/chrome/browser/app/tabmodel/TabModelOrchestrator.java index 4b11b6a..2f38382 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/tabmodel/TabModelOrchestrator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/tabmodel/TabModelOrchestrator.java
@@ -4,7 +4,6 @@ package org.chromium.chrome.browser.app.tabmodel; -import org.chromium.base.supplier.ObservableSupplierImpl; import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager; import org.chromium.chrome.browser.tabmodel.TabModelSelectorImpl; import org.chromium.chrome.browser.tabmodel.TabPersistentStore; @@ -133,15 +132,6 @@ } protected void wireSelectorAndStore() { - // Supply TabModelSelectorImpl with TabPersistentStore. - // - // TODO(crbug.com/1138561): Remove this dependency by making TabModelSelectorImpl emit - // events and TabPersistentStore react to them as an observer. - ObservableSupplierImpl<TabPersistentStore> tabPersistentStoreSupplier = - new ObservableSupplierImpl<>(); - tabPersistentStoreSupplier.set(mTabPersistentStore); - mTabModelSelector.setTabPersistentStoreSupplier(tabPersistentStoreSupplier); - // Notify TabModelSelectorImpl when TabPersistentStore initializes tab state final TabPersistentStoreObserver persistentStoreObserver = new TabPersistentStoreObserver() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivitySettingsLauncher.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivitySettingsLauncher.java index f7581c3..3bb3d21 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivitySettingsLauncher.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivitySettingsLauncher.java
@@ -53,14 +53,14 @@ */ public static void launchForWebApkPackageName( Context context, String packageName, String webApkUrl) { + // Handle the case when settings are selected but Chrome was not running. + ChromeWebApkHost.init(); if (!WebApkValidator.canWebApkHandleUrl(context, packageName, webApkUrl)) { Log.d(TAG, "WebApk " + packageName + " can't handle url " + webApkUrl); return; } if (getApplicationUid(context, packageName) == null) return; - // Handle the case when settings are selected but Chrome was not running. - ChromeWebApkHost.init(); openSingleWebsitePrefs(context, webApkUrl); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/crash/MinidumpUploadServiceImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/crash/MinidumpUploadServiceImpl.java index c0a97b2..3f7667c6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/crash/MinidumpUploadServiceImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/crash/MinidumpUploadServiceImpl.java
@@ -15,6 +15,8 @@ import androidx.annotation.StringDef; import androidx.annotation.VisibleForTesting; +import org.chromium.base.ApplicationState; +import org.chromium.base.ApplicationStatus.ApplicationStateListener; import org.chromium.base.ContextUtils; import org.chromium.base.Log; import org.chromium.base.StreamUtil; @@ -120,6 +122,13 @@ MinidumpUploadJobService.scheduleUpload(builder); } + private ApplicationStateListener createApplicationStateListener() { + return newState -> { + SharedPreferencesManager.getInstance().writeInt( + ChromePreferenceKeys.LAST_SESSION_APPLICATION_STATE, newState); + }; + } + /** * Stores the successes and failures from uploading crash to UMA, */ @@ -127,11 +136,24 @@ sBrowserCrashMetricsInitialized.set(true); SharedPreferencesManager sharedPrefs = SharedPreferencesManager.getInstance(); - int previous_pid = sharedPrefs.readInt(ChromePreferenceKeys.LAST_SESSION_BROWSER_PID); + int previousPid = sharedPrefs.readInt(ChromePreferenceKeys.LAST_SESSION_BROWSER_PID); + @ApplicationState + int applicationExitState = + sharedPrefs.readInt(ChromePreferenceKeys.LAST_SESSION_APPLICATION_STATE); + String umaSuffix; + if (applicationExitState == ApplicationState.HAS_RUNNING_ACTIVITIES + || applicationExitState == ApplicationState.HAS_PAUSED_ACTIVITIES) { + umaSuffix = "Foreground"; + } else { + umaSuffix = "Background"; + } sharedPrefs.writeInt(ChromePreferenceKeys.LAST_SESSION_BROWSER_PID, Process.myPid()); - if (previous_pid != 0) { - ProcessExitReasonFromSystem.recordExitReasonToUma( - previous_pid, "Stability.Android.SystemExitReason.Browser"); + if (previousPid != 0) { + int reason = ProcessExitReasonFromSystem.getExitReason(previousPid); + ProcessExitReasonFromSystem.recordAsEnumHistogram( + "Stability.Android.SystemExitReason.Browser", reason); + ProcessExitReasonFromSystem.recordAsEnumHistogram( + "Stability.Android.SystemExitReason.Browser." + umaSuffix, reason); } for (String type : TYPES) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java index 25f37616..d2f1f46 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
@@ -41,7 +41,6 @@ import org.chromium.chrome.browser.browserservices.intents.BrowserServicesIntentDataProvider; import org.chromium.chrome.browser.browserservices.intents.CustomButtonParams; import org.chromium.chrome.browser.flags.ActivityType; -import org.chromium.chrome.browser.flags.CachedFeatureFlags; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.gsa.GSAState; import org.chromium.chrome.browser.version.ChromeVersionInfo; @@ -467,9 +466,7 @@ int shareState = IntentUtils.safeGetIntExtra( intent, CustomTabsIntent.EXTRA_SHARE_STATE, CustomTabsIntent.SHARE_STATE_DEFAULT); if (shareState == CustomTabsIntent.SHARE_STATE_ON - || (shareState == CustomTabsIntent.SHARE_STATE_DEFAULT - && CachedFeatureFlags.isEnabled( - ChromeFeatureList.SHARE_BY_DEFAULT_IN_CCT))) { + || shareState == CustomTabsIntent.SHARE_STATE_DEFAULT) { if (mToolbarButtons.isEmpty()) { mToolbarButtons.add( CustomButtonParamsImpl.createShareButton(context, getToolbarColor()));
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationFactory.java index e2b4610..4ddf398 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationFactory.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationFactory.java
@@ -26,7 +26,6 @@ import android.content.Intent; import android.os.Build; import android.os.Bundle; -import android.text.TextUtils; import androidx.core.app.NotificationCompat; @@ -41,13 +40,12 @@ import org.chromium.components.browser_ui.notifications.NotificationMetadata; import org.chromium.components.browser_ui.notifications.NotificationWrapperBuilder; import org.chromium.components.browser_ui.notifications.PendingIntentProvider; -import org.chromium.components.embedder_support.util.UrlUtilities; +import org.chromium.components.browser_ui.util.DownloadUtils; import org.chromium.components.offline_items_collection.ContentId; import org.chromium.components.offline_items_collection.LegacyHelpers; import org.chromium.components.offline_items_collection.OfflineItem; import org.chromium.components.offline_items_collection.PendingState; -import org.chromium.components.url_formatter.SchemeDisplay; -import org.chromium.components.url_formatter.UrlFormatter; +import org.chromium.url.GURL; /** * Creates and updates notifications related to downloads. @@ -350,18 +348,11 @@ setSubText(builder, context.getResources().getString( R.string.download_notification_incognito_subtext)); - } else if (downloadUpdate.getShouldPromoteOrigin() - && !TextUtils.isEmpty(downloadUpdate.getOriginalUrl())) { + } else if (downloadUpdate.getShouldPromoteOrigin()) { // Always show the origin URL if available (for normal profiles). - String formattedUrl = UrlFormatter.formatUrlForSecurityDisplay( - downloadUpdate.getOriginalUrl(), SchemeDisplay.OMIT_HTTP_AND_HTTPS); - - if (formattedUrl.length() > MAX_ORIGIN_LENGTH) { - // The origin is too long. Strip down to eTLD+1. - formattedUrl = UrlUtilities.getDomainAndRegistry( - downloadUpdate.getOriginalUrl(), false /* includePrivateRegistries */); - } - setSubText(builder, formattedUrl); + String formattedUrl = DownloadUtils.formatUrlForDisplayInNotification( + new GURL(downloadUpdate.getOriginalUrl())); + if (formattedUrl != null) setSubText(builder, formattedUrl); } return builder.build();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateCompactInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateCompactInfoBar.java index f63e5739..038b84b0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateCompactInfoBar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/TranslateCompactInfoBar.java
@@ -183,12 +183,12 @@ @Override public void onPreferenceChange() { if (mNativeTranslateInfoBarPtr != 0) { - String[] currentContentLangauges = + String[] currentContentLanguages = TranslateCompactInfoBarJni.get().getContentLanguagesCodes( mNativeTranslateInfoBarPtr, TranslateCompactInfoBar.this); - mOptions.updateContentLanguages(currentContentLangauges); + mOptions.updateContentLanguages(currentContentLanguages); if (mLanguageMenuHelper != null) { - mLanguageMenuHelper.onContentLanguagesChanged(currentContentLangauges); + mLanguageMenuHelper.onContentLanguagesChanged(currentContentLanguages); } } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/CardEditor.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/CardEditor.java index 3c0b64e..04bf0d1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/CardEditor.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/CardEditor.java
@@ -15,10 +15,10 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.Callback; +import org.chromium.base.supplier.Supplier; import org.chromium.base.task.AsyncTask; import org.chromium.base.task.BackgroundOnlyAsyncTask; import org.chromium.chrome.R; -import org.chromium.chrome.browser.app.ChromeActivity; import org.chromium.chrome.browser.autofill.CreditCardScanner; import org.chromium.chrome.browser.autofill.PersonalDataManager; import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile; @@ -30,11 +30,14 @@ import org.chromium.chrome.browser.autofill.prefeditor.EditorModel; import org.chromium.chrome.browser.autofill.settings.AutofillProfileBridge.DropdownKeyValue; import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; +import org.chromium.chrome.browser.tabmodel.TabModelSelector; +import org.chromium.chrome.browser.tabmodel.TabModelSelectorSupplier; import org.chromium.components.payments.BasicCardUtils; import org.chromium.components.payments.MethodStrings; import org.chromium.components.payments.PaymentRequestService; import org.chromium.content_public.browser.WebContents; import org.chromium.payments.mojom.PaymentMethodData; +import org.chromium.ui.base.WindowAndroid; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -265,8 +268,19 @@ }; mCalendar.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); - ChromeActivity activity = ChromeActivity.fromWebContents(mWebContents); - mIsIncognito = activity != null && activity.getCurrentTabModel().isIncognito(); + mIsIncognito = resolveIncognitoState(mWebContents.getTopLevelNativeWindow()); + } + + /** Returns whether the user is currently incognito, defaults to false. */ + private boolean resolveIncognitoState(@Nullable WindowAndroid windowAndroid) { + if (windowAndroid == null) return false; + + Supplier<TabModelSelector> tabModelSelectorSupplier = + TabModelSelectorSupplier.from(windowAndroid); + assert tabModelSelectorSupplier != null; + if (!tabModelSelectorSupplier.hasValue()) return false; + + return tabModelSelectorSupplier.get().isIncognitoSelected(); } private boolean isCardNumberLengthMaximum(@Nullable CharSequence value) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelImplCreator.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelImplCreator.java index a01082d..300e373c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelImplCreator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelImplCreator.java
@@ -24,7 +24,6 @@ private final TabCreator mIncognitoTabCreator; private final TabModelOrderController mOrderController; private final TabContentManager mTabContentManager; - private final TabPersistentStore mTabSaver; private final NextTabPolicySupplier mNextTabPolicySupplier; private final AsyncTabParamsManager mAsyncTabParamsManager; private final TabModelDelegate mModelDelegate; @@ -46,7 +45,6 @@ * @param incognitoTabCreator Creates incognito tabs. * @param orderController Determines the order for inserting new Tabs. * @param tabContentManager Manages the display content of the tab. - * @param tabSaver Handler for saving tabs. * @param nextTabPolicySupplier Supplies the policy to pick a next tab if the current is closed * @param asyncTabParamsManager An {@link AsyncTabParamsManager} instance. * @param modelDelegate Delegate to handle external dependencies and interactions. @@ -54,14 +52,13 @@ IncognitoTabModelImplCreator(@Nullable Supplier<WindowAndroid> windowAndroidSupplier, TabCreator regularTabCreator, TabCreator incognitoTabCreator, TabModelOrderController orderController, TabContentManager tabContentManager, - TabPersistentStore tabSaver, NextTabPolicySupplier nextTabPolicySupplier, + NextTabPolicySupplier nextTabPolicySupplier, AsyncTabParamsManager asyncTabParamsManager, TabModelDelegate modelDelegate) { mWindowAndroidSupplier = windowAndroidSupplier; mRegularTabCreator = regularTabCreator; mIncognitoTabCreator = incognitoTabCreator; mOrderController = orderController; mTabContentManager = tabContentManager; - mTabSaver = tabSaver; mNextTabPolicySupplier = nextTabPolicySupplier; mAsyncTabParamsManager = asyncTabParamsManager; mModelDelegate = modelDelegate; @@ -89,7 +86,7 @@ public TabModel createTabModel() { Profile otrProfile = getOTRProfile(); return new TabModelImpl(otrProfile, false, mRegularTabCreator, mIncognitoTabCreator, - mOrderController, mTabContentManager, mTabSaver, mNextTabPolicySupplier, + mOrderController, mTabContentManager, mNextTabPolicySupplier, mAsyncTabParamsManager, mModelDelegate, false); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelImpl.java index d978aa0..d887dcfe 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelImpl.java
@@ -59,7 +59,6 @@ private final TabCreator mIncognitoTabCreator; private final TabModelOrderController mOrderController; private final TabContentManager mTabContentManager; - private final TabPersistentStore mTabSaver; private final TabModelDelegate mModelDelegate; private final ObserverList<TabModelObserver> mObservers; private final NextTabPolicySupplier mNextTabPolicySupplier; @@ -90,7 +89,7 @@ public TabModelImpl(@NonNull Profile profile, boolean isTabbedActivity, TabCreator regularTabCreator, TabCreator incognitoTabCreator, TabModelOrderController orderController, TabContentManager tabContentManager, - TabPersistentStore tabSaver, NextTabPolicySupplier nextTabPolicySupplier, + NextTabPolicySupplier nextTabPolicySupplier, AsyncTabParamsManager asyncTabParamsManager, TabModelDelegate modelDelegate, boolean supportUndo) { super(profile, isTabbedActivity); @@ -98,7 +97,6 @@ mIncognitoTabCreator = incognitoTabCreator; mOrderController = orderController; mTabContentManager = tabContentManager; - mTabSaver = tabSaver; mNextTabPolicySupplier = nextTabPolicySupplier; mAsyncTabParamsManager = asyncTabParamsManager; mModelDelegate = modelDelegate; @@ -355,9 +353,6 @@ } } - // Re-save the tab list now that it is being kept. - mTabSaver.saveTabListAsynchronously(); - for (TabModelObserver obs : mObservers) obs.tabClosureUndone(tab); } @@ -449,7 +444,7 @@ @Override public void closeAllTabs(boolean allowDelegation, boolean uponExit) { - mTabSaver.cancelLoadingTabs(isIncognito()); + for (TabModelObserver obs : mObservers) obs.willCloseAllTabs(isIncognito()); if (uponExit) { commitAllTabClosures(); @@ -662,11 +657,11 @@ */ private void finalizeTabClosure(Tab tab, boolean notifyTabClosureCommitted) { if (mTabContentManager != null) mTabContentManager.removeTabThumbnail(tab.getId()); - mTabSaver.removeTabFromQueues(tab); PersistedTabData.onTabClose(tab); if (!isIncognito()) HistoricalTabSaver.createHistoricalTab(tab); + for (TabModelObserver obs : mObservers) obs.didCloseTab(tab); for (TabModelObserver obs : mObservers) obs.didCloseTab(tab.getId(), tab.isIncognito()); if (notifyTabClosureCommitted) { for (TabModelObserver obs : mObservers) obs.tabClosureCommitted(tab);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImpl.java index 66566ffdb..aa13c8d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImpl.java
@@ -44,10 +44,6 @@ private final TabModelOrderController mOrderController; - // TODO(crbug.com/1138561): Remove the dependency from TabModelSelectorImpl to - // TabPersistentStore. - private Supplier<TabPersistentStore> mTabSaver; - private final AsyncTabParamsManager mAsyncTabParamsManager; private NextTabPolicySupplier mNextTabPolicySupplier; @@ -84,19 +80,6 @@ mAsyncTabParamsManager = asyncTabParamsManager; } - /** - * TODO(crbug.com/1138561): Do not add more parameters here. This is temporary while the - * dependency from TabModelSelectorImpl to TabPersistentStore is removed. - * - * This must be called after the constructor; NPEs are expected, otherwise. - * A Supplier that supplies null can be passed in tests. - */ - public void setTabPersistentStoreSupplier( - Supplier<TabPersistentStore> tabPersistentStoreSupplier) { - assert mTabSaver == null; - mTabSaver = tabPersistentStoreSupplier; - } - @Override public void markTabStateInitialized() { super.markTabStateInitialized(); @@ -133,14 +116,14 @@ (ChromeTabCreator) getTabCreatorManager().getTabCreator(true); TabModelImpl normalModel = new TabModelImpl(Profile.getLastUsedRegularProfile(), mIsTabbedActivityForSync, regularTabCreator, incognitoTabCreator, mOrderController, - mTabContentManager, mTabSaver.get(), mNextTabPolicySupplier, mAsyncTabParamsManager, - this, mIsUndoSupported); + mTabContentManager, mNextTabPolicySupplier, mAsyncTabParamsManager, this, + mIsUndoSupported); regularTabCreator.setTabModel(normalModel, mOrderController); - IncognitoTabModel incognitoModel = new IncognitoTabModelImpl( - new IncognitoTabModelImplCreator(mWindowAndroidSupplier, regularTabCreator, - incognitoTabCreator, mOrderController, mTabContentManager, mTabSaver.get(), - mNextTabPolicySupplier, mAsyncTabParamsManager, this)); + IncognitoTabModel incognitoModel = + new IncognitoTabModelImpl(new IncognitoTabModelImplCreator(mWindowAndroidSupplier, + regularTabCreator, incognitoTabCreator, mOrderController, + mTabContentManager, mNextTabPolicySupplier, mAsyncTabParamsManager, this)); incognitoTabCreator.setTabModel(incognitoModel, mOrderController); onNativeLibraryReadyInternal(tabContentProvider, normalModel, incognitoModel); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java index 34bec149..ebbb516 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java
@@ -92,6 +92,7 @@ /** Prevents two TabPersistentStores from saving the same file simultaneously. */ private static final Object SAVE_LIST_LOCK = new Object(); + private TabModelObserver mTabModelObserver; public void onNativeLibraryReady(TabContentManager tabContentManager) { setTabContentManager(tabContentManager); @@ -126,6 +127,26 @@ addTabToSaveQueue(tab); } }; + + mTabModelObserver = new TabModelObserver() { + @Override + public void didCloseTab(Tab tab) { + removeTabFromQueues(tab); + } + + @Override + public void willCloseAllTabs(boolean incognito) { + cancelLoadingTabs(incognito); + } + + @Override + public void tabClosureUndone(Tab tab) { + saveTabListAsynchronously(); + } + }; + + mTabModelSelector.getModel(false).addObserver(mTabModelObserver); + mTabModelSelector.getModel(true).addObserver(mTabModelObserver); } /** @@ -847,6 +868,11 @@ public void destroy() { mDestroyed = true; + if (mTabModelObserver != null) { + mTabModelSelector.getModel(false).removeObserver(mTabModelObserver); + mTabModelSelector.getModel(true).removeObserver(mTabModelObserver); + mTabModelObserver = null; + } mPersistencePolicy.destroy(); if (mTabLoader != null) mTabLoader.cancel(true); mTabsToSave.clear();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/ManageTrustedWebActivityDataActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/ManageTrustedWebActivityDataActivityTest.java index 99c5fdd..9bbab5ec 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/ManageTrustedWebActivityDataActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/ManageTrustedWebActivityDataActivityTest.java
@@ -36,9 +36,8 @@ public class ManageTrustedWebActivityDataActivityTest { private static final String SETTINGS_ACTIVITY_NAME = "org.chromium.chrome.browser.settings.SettingsActivity"; - private static final String WEBAPK_TEST_URL = "https://www.example.com"; - private static final String TEST_PACKAGE_NAME = - InstrumentationRegistry.getTargetContext().getPackageName(); + private static final String WEBAPK_TEST_URL = "https://pwa-directory.appspot.com/"; + private static final String TEST_PACKAGE_NAME = "org.chromium.webapk.test"; @Test @MediumTest @@ -74,7 +73,7 @@ Intent intent = new Intent(); intent.setAction( "android.support.customtabs.action.ACTION_MANAGE_TRUSTED_WEB_ACTIVITY_DATA"); - intent.setPackage(packageName); + intent.setPackage(InstrumentationRegistry.getTargetContext().getPackageName()); intent.setData(uri); intent.putExtra(WebApkConstants.EXTRA_IS_WEBAPK, true); // The following flag is required because the test starts the intent outside of an activity.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTestRule.java index e832ecf..7799a8b3 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTestRule.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTestRule.java
@@ -10,15 +10,11 @@ import org.junit.Assert; -import org.chromium.base.FeatureList; import org.chromium.base.test.util.ScalableTimeout; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabTestUtils; import org.chromium.chrome.test.ChromeActivityTestRule; -import java.util.Collections; - /** * Custom ActivityTestRule for all instrumentation tests that require a {@link CustomTabActivity}. */ @@ -46,10 +42,6 @@ @Override public void launchActivity(@NonNull Intent intent) { - if (!FeatureList.hasTestFeatures()) { - FeatureList.setTestFeatures( - Collections.singletonMap(ChromeFeatureList.SHARE_BY_DEFAULT_IN_CCT, true)); - } putCustomTabIdInIntent(intent); super.launchActivity(intent); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationTest.java index af348f0..932e722 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationTest.java
@@ -44,7 +44,6 @@ import org.chromium.chrome.browser.customtabs.CustomTabActivity; import org.chromium.chrome.browser.customtabs.CustomTabsTestUtils; import org.chromium.chrome.browser.document.ChromeLauncherActivity; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.locale.DefaultSearchEngineDialogHelperUtils; import org.chromium.chrome.browser.locale.LocaleManager; import org.chromium.chrome.browser.locale.LocaleManager.SearchEnginePromoType; @@ -68,7 +67,6 @@ * Integration test suite for the first run experience. */ @RunWith(ChromeJUnit4ClassRunner.class) -@Features.EnableFeatures(ChromeFeatureList.SHARE_BY_DEFAULT_IN_CCT) public class FirstRunIntegrationTest { private static final long DEFERRED_START_UP_POLL_TIME = 10000L; @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/media/MediaLauncherActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/media/MediaLauncherActivityTest.java index 1cb1eab..0b81ef8d 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/media/MediaLauncherActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/media/MediaLauncherActivityTest.java
@@ -27,7 +27,6 @@ import org.chromium.base.test.util.CriteriaHelper; import org.chromium.base.test.util.UrlUtils; import org.chromium.chrome.browser.customtabs.CustomTabActivity; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; @@ -45,7 +44,6 @@ */ @RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) -@Features.EnableFeatures(ChromeFeatureList.SHARE_BY_DEFAULT_IN_CCT) public class MediaLauncherActivityTest { @Rule public MultiActivityTestRule mTestRule = new MultiActivityTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/reengagement/ReengagementNotificationControllerIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/reengagement/ReengagementNotificationControllerIntegrationTest.java index 5a9fb236..309ace7 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/reengagement/ReengagementNotificationControllerIntegrationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/reengagement/ReengagementNotificationControllerIntegrationTest.java
@@ -378,7 +378,6 @@ // as expected with test values. features.put(ChromeFeatureList.SEARCH_ENGINE_PROMO_EXISTING_DEVICE, false); features.put(ChromeFeatureList.OMNIBOX_SEARCH_ENGINE_LOGO, false); - features.put(ChromeFeatureList.SHARE_BY_DEFAULT_IN_CCT, true); features.put(ChromeFeatureList.VOICE_SEARCH_AUDIO_CAPTURE_POLICY, false); FeatureList.setTestFeatures(features); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorObserverTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorObserverTestRule.java index a49f1686..b655bedf 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorObserverTestRule.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorObserverTestRule.java
@@ -73,9 +73,6 @@ TabContentManager tabContentManager = new TabContentManager( InstrumentationRegistry.getTargetContext(), null, false, mSelector::getTabById); tabContentManager.initWithNative(); - TabPersistencePolicy persistencePolicy = new TabbedModeTabPersistencePolicy(0, false); - TabPersistentStore tabPersistentStore = - new TabPersistentStore(persistencePolicy, mSelector, null); NextTabPolicySupplier nextTabPolicySupplier = () -> NextTabPolicy.HIERARCHICAL; AsyncTabParamsManager asyncTabParamsManager = AsyncTabParamsManagerSingleton.getInstance(); @@ -115,13 +112,12 @@ }; mNormalTabModel = new TabModelSelectorTestTabModel(Profile.getLastUsedRegularProfile(), - orderController, tabContentManager, tabPersistentStore, nextTabPolicySupplier, - asyncTabParamsManager, delegate); + orderController, tabContentManager, nextTabPolicySupplier, asyncTabParamsManager, + delegate); mIncognitoTabModel = new TabModelSelectorTestIncognitoTabModel( Profile.getLastUsedRegularProfile().getPrimaryOTRProfile(), orderController, - tabContentManager, tabPersistentStore, nextTabPolicySupplier, asyncTabParamsManager, - delegate); + tabContentManager, nextTabPolicySupplier, asyncTabParamsManager, delegate); mSelector.initialize(mNormalTabModel, mIncognitoTabModel); } @@ -134,11 +130,10 @@ public TabModelSelectorTestTabModel(Profile profile, TabModelOrderController orderController, TabContentManager tabContentManager, - TabPersistentStore tabPersistentStore, NextTabPolicySupplier nextTabPolicySupplier, + NextTabPolicySupplier nextTabPolicySupplier, AsyncTabParamsManager asyncTabParamsManager, TabModelDelegate modelDelegate) { super(profile, false, null, null, orderController, tabContentManager, - tabPersistentStore, nextTabPolicySupplier, asyncTabParamsManager, modelDelegate, - false); + nextTabPolicySupplier, asyncTabParamsManager, modelDelegate, false); } @Override @@ -165,11 +160,10 @@ extends TabModelSelectorTestTabModel implements IncognitoTabModel { public TabModelSelectorTestIncognitoTabModel(Profile profile, TabModelOrderController orderController, TabContentManager tabContentManager, - TabPersistentStore tabPersistentStore, NextTabPolicySupplier nextTabPolicySupplier, + NextTabPolicySupplier nextTabPolicySupplier, AsyncTabParamsManager asyncTabParamsManager, TabModelDelegate modelDelegate) { super(Profile.getLastUsedRegularProfile().getPrimaryOTRProfile(), orderController, - tabContentManager, tabPersistentStore, nextTabPolicySupplier, - asyncTabParamsManager, modelDelegate); + tabContentManager, nextTabPolicySupplier, asyncTabParamsManager, modelDelegate); } @Override
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java index 7ee7be6..164506d 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java
@@ -152,7 +152,7 @@ return new TabModelImpl(Profile.getLastUsedRegularProfile(), false, getTabCreatorManager().getTabCreator(false), getTabCreatorManager().getTabCreator(true), mTabModelOrderController, - null, mTabPersistentStore, nextTabPolicySupplier, + null, nextTabPolicySupplier, AsyncTabParamsManagerSingleton.getInstance(), TestTabModelSelector.this, true); } @@ -162,7 +162,7 @@ new IncognitoTabModelImpl(new IncognitoTabModelImplCreator(null, getTabCreatorManager().getTabCreator(false), getTabCreatorManager().getTabCreator(true), mTabModelOrderController, - null, mTabPersistentStore, nextTabPolicySupplier, + null, nextTabPolicySupplier, AsyncTabParamsManagerSingleton.getInstance(), this)); initialize(regularTabModel, incognitoTabModel); }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProviderTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProviderTest.java index 00068f1d..dcbd5c0 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProviderTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProviderTest.java
@@ -36,7 +36,6 @@ import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.chrome.R; import org.chromium.chrome.browser.document.ChromeLauncherActivity; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.test.util.browser.Features; import org.chromium.device.mojom.ScreenOrientationLockType; @@ -46,7 +45,6 @@ /** Tests for {@link CustomTabIntentDataProvider}. */ @RunWith(BaseRobolectricTestRunner.class) @Config(manifest = Config.NONE) -@Features.EnableFeatures({ChromeFeatureList.SHARE_BY_DEFAULT_IN_CCT}) public class CustomTabIntentDataProviderTest { @Rule public TestRule mProcessor = new Features.JUnitProcessor(); @@ -203,22 +201,6 @@ } @Test - @Features.DisableFeatures({ChromeFeatureList.SHARE_BY_DEFAULT_IN_CCT}) - public void shareStateDefaultFlagDisabled_hasShareItemInMenu() { - Context context = ApplicationProvider.getApplicationContext(); - Intent intent = new Intent() - .putExtra(CustomTabsIntent.EXTRA_SHARE_STATE, - CustomTabsIntent.SHARE_STATE_DEFAULT) - .putExtra(CustomTabsIntent.EXTRA_DEFAULT_SHARE_MENU_ITEM, true); - - CustomTabIntentDataProvider dataProvider = - new CustomTabIntentDataProvider(intent, context, COLOR_SCHEME_LIGHT); - - assertTrue(dataProvider.getCustomButtonsOnToolbar().isEmpty()); - assertTrue(dataProvider.shouldShowShareMenuItem()); - } - - @Test public void shareStateOff_noShareItems() { Context context = ApplicationProvider.getApplicationContext(); Intent intent = new Intent().putExtra(
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImplTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImplTest.java index c2d7144..9b86933 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImplTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImplTest.java
@@ -60,7 +60,6 @@ mMockTabModelFilterFactory, mNextTabPolicySupplier, realAsyncTabParamsManager, /*supportUndo=*/false, /*isTabbedActivity=*/false, /*startIncognito=*/false); - mTabModelSelector.setTabPersistentStoreSupplier(() -> null); mTabCreatorManager.initialize(mTabModelSelector); mTabModelSelector.onNativeLibraryReadyInternal(mMockTabContentManager, new MockTabModel(false, null), new MockTabModel(true, null));
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt index 28d8a3a..8afb8ae 100644 --- a/chrome/android/profiles/newest.txt +++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-91.0.4448.0_rc-r1-merged.afdo.bz2 +chromeos-chrome-amd64-91.0.4449.0_rc-r1-merged.afdo.bz2
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 8685553..9db2d22 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -953,6 +953,8 @@ "optimization_guide/optimization_guide_keyed_service_factory.h", "optimization_guide/optimization_guide_navigation_data.cc", "optimization_guide/optimization_guide_navigation_data.h", + "optimization_guide/optimization_guide_tab_url_provider.cc", + "optimization_guide/optimization_guide_tab_url_provider.h", "optimization_guide/optimization_guide_top_host_provider.cc", "optimization_guide/optimization_guide_top_host_provider.h", "optimization_guide/optimization_guide_web_contents_observer.cc", @@ -1542,8 +1544,6 @@ "sharesheet/sharesheet_types.h", "sharing/ack_message_handler.cc", "sharing/ack_message_handler.h", - "sharing/click_to_call/feature.cc", - "sharing/click_to_call/feature.h", "sharing/features.cc", "sharing/features.h", "sharing/ping_message_handler.cc", @@ -3049,6 +3049,8 @@ "offline_pages/prefetch/notifications/prefetch_notification_service_factory.h", "optimization_guide/android/optimization_guide_bridge.cc", "optimization_guide/android/optimization_guide_bridge.h", + "optimization_guide/android/optimization_guide_tab_url_provider_android.cc", + "optimization_guide/android/optimization_guide_tab_url_provider_android.h", "page_load_metrics/observers/android_page_load_metrics_observer.cc", "page_load_metrics/observers/android_page_load_metrics_observer.h", "password_check/android/password_check_bridge.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index a65db7c..bf106f3 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -49,7 +49,6 @@ #include "chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_params.h" #include "chrome/browser/prefetch/search_prefetch/field_trial_settings.h" #include "chrome/browser/resource_coordinator/tab_manager_features.h" -#include "chrome/browser/sharing/click_to_call/feature.h" #include "chrome/browser/sharing/features.h" #include "chrome/browser/sharing/shared_clipboard/feature_flags.h" #include "chrome/browser/sharing/sms/sms_flags.h" @@ -1811,7 +1810,8 @@ {"omnibox_focused_on_new_tab", "true"}, {"home_button_on_grid_tab_switcher", "true"}, {"new_home_surface_from_home_button", "hide_tab_switcher_only"}, - {"hide_switch_when_no_incognito_tabs", "true"}}; + {"hide_switch_when_no_incognito_tabs", "true"}, + {"show_tabs_in_mru_order", "true"}}; const FeatureEntry::FeatureParam kStartSurfaceAndroid_SingleSurface_V2[] = { {"start_surface_variation", "single"}, @@ -1824,7 +1824,8 @@ {"show_last_active_tab_only", "true"}, {"omnibox_focused_on_new_tab", "true"}, {"home_button_on_grid_tab_switcher", "true"}, - {"new_home_surface_from_home_button", "hide_tab_switcher_only"}}; + {"new_home_surface_from_home_button", "hide_tab_switcher_only"}, + {"show_tabs_in_mru_order", "true"}}; const FeatureEntry::FeatureParam kStartSurfaceAndroid_SingleSurfaceWithoutMvTiles[] = { @@ -3372,9 +3373,6 @@ {"chrome-sharing-hub-v1-5", flag_descriptions::kChromeSharingHubV15Name, flag_descriptions::kChromeSharingHubV15Description, kOsAndroid, FEATURE_VALUE_TYPE(chrome::android::kChromeSharingHubV15)}, - {"share-by-default-in-cct", flag_descriptions::kShareByDefaultInCCTName, - flag_descriptions::kShareByDefaultInCCTDescription, kOsAndroid, - FEATURE_VALUE_TYPE(chrome::android::kShareByDefaultInCCT)}, #endif // OS_ANDROID {"in-product-help-demo-mode-choice", flag_descriptions::kInProductHelpDemoModeChoiceName, @@ -3573,6 +3571,11 @@ flag_descriptions::kDesktopPWAsRunOnOsLoginDescription, kOsWin | kOsLinux | kOsMac, FEATURE_VALUE_TYPE(features::kDesktopPWAsRunOnOsLogin)}, + {"enable-desktop-pwas-protocol-handling", + flag_descriptions::kDesktopPWAsProtocolHandlingName, + flag_descriptions::kDesktopPWAsProtocolHandlingDescription, + kOsWin | kOsLinux | kOsMac, + FEATURE_VALUE_TYPE(blink::features::kWebAppEnableProtocolHandlers)}, {"enable-desktop-pwas-url-handling", flag_descriptions::kDesktopPWAsUrlHandlingName, flag_descriptions::kDesktopPWAsUrlHandlingDescription, @@ -5379,12 +5382,6 @@ FEATURE_VALUE_TYPE(chromeos::assistant::features::kAssistantTimersV2)}, #endif // BUILDFLAG(IS_CHROMEOS_ASH) -#if BUILDFLAG(ENABLE_CLICK_TO_CALL) - {"click-to-call-ui", flag_descriptions::kClickToCallUIName, - flag_descriptions::kClickToCallUIDescription, kOsDesktop, - FEATURE_VALUE_TYPE(kClickToCallUI)}, -#endif // BUILDFLAG(ENABLE_CLICK_TO_CALL) - #if defined(OS_WIN) || defined(OS_MAC) || defined(OS_LINUX) || \ defined(OS_CHROMEOS) {"remote-copy-receiver", flag_descriptions::kRemoteCopyReceiverName, @@ -5815,10 +5812,6 @@ kOsWin | kOsLinux | kOsCrOS | kOsAndroid, FEATURE_VALUE_TYPE(features::kFormControlsRefresh)}, - {"color-picker-eye-dropper", flag_descriptions::kColorPickerEyeDropperName, - flag_descriptions::kColorPickerEyeDropperDescription, kOsWin | kOsMac, - FEATURE_VALUE_TYPE(features::kEyeDropper)}, - #if BUILDFLAG(IS_CHROMEOS_ASH) {"auto-screen-brightness", flag_descriptions::kAutoScreenBrightnessName, flag_descriptions::kAutoScreenBrightnessDescription, kOsCrOS, @@ -6383,7 +6376,7 @@ flag_descriptions::kPaintPreviewStartupDescription, kOsAndroid, FEATURE_WITH_PARAMS_VALUE_TYPE(paint_preview::kPaintPreviewShowOnStartup, kPaintPreviewStartupVariations, - "PaintPreviewStartup")}, + "PaintPreviewShowOnStartup")}, #endif // ENABLE_PAINT_PREVIEW && defined(OS_ANDROID) #if defined(OS_ANDROID) @@ -6593,11 +6586,6 @@ {"enable-palm-suppression", flag_descriptions::kEnablePalmSuppressionName, flag_descriptions::kEnablePalmSuppressionDescription, kOsCrOS, FEATURE_VALUE_TYPE(ui::kEnablePalmSuppression)}, - - {"movable-partial-screenshot-region", - flag_descriptions::kMovablePartialScreenshotName, - flag_descriptions::kMovablePartialScreenshotDescription, kOsCrOS, - FEATURE_VALUE_TYPE(ash::features::kMovablePartialScreenshot)}, #endif // BUILDFLAG(IS_CHROMEOS_ASH) {"enable-experimental-cookie-features",
diff --git a/chrome/browser/ash/login/quick_unlock/pin_storage_cryptohome.cc b/chrome/browser/ash/login/quick_unlock/pin_storage_cryptohome.cc index 45e9b171..09bf839 100644 --- a/chrome/browser/ash/login/quick_unlock/pin_storage_cryptohome.cc +++ b/chrome/browser/ash/login/quick_unlock/pin_storage_cryptohome.cc
@@ -244,6 +244,7 @@ if (return_code != cryptohome::MOUNT_ERROR_NONE) { can_authenticate_cache_[account_id] = false; std::move(callback).Run(false); + return; } const std::vector<cryptohome::KeyDefinition>& key_definitions =
diff --git a/chrome/browser/chromeos/external_protocol_dialog.cc b/chrome/browser/chromeos/external_protocol_dialog.cc index 9b093db40..cd644df 100644 --- a/chrome/browser/chromeos/external_protocol_dialog.cc +++ b/chrome/browser/chromeos/external_protocol_dialog.cc
@@ -8,7 +8,6 @@ #include "chrome/browser/chromeos/arc/intent_helper/arc_external_protocol_dialog.h" #include "chrome/browser/chromeos/guest_os/guest_os_external_protocol_handler.h" #include "chrome/browser/external_protocol/external_protocol_handler.h" -#include "chrome/browser/sharing/click_to_call/feature.h" #include "chrome/browser/tab_contents/tab_util.h" #include "chrome/browser/ui/browser_dialogs.h" #include "chrome/browser/ui/views/external_protocol_dialog.h" @@ -117,12 +116,9 @@ ExternalProtocolNoHandlersDialog::~ExternalProtocolNoHandlersDialog() = default; std::u16string ExternalProtocolNoHandlersDialog::GetWindowTitle() const { - // If click to call feature is available, we display a message to the user on - // how to use the feature. - // TODO(crbug.com/1007995) - This is a hotfix for M78 and we plan to use our - // own dialog with more information in the future. - if (scheme_ == url::kTelScheme && - base::FeatureList::IsEnabled(kClickToCallUI)) { + // If this dialog is shown for a tel link, we display a message to the user on + // how to use the Click to Call feature. + if (scheme_ == url::kTelScheme) { return l10n_util::GetStringUTF16( IDS_BROWSER_SHARING_CLICK_TO_CALL_DIALOG_HELP_TEXT_NO_DEVICES); }
diff --git a/chrome/browser/enterprise/connectors/file_system/box_api_call_flow.cc b/chrome/browser/enterprise/connectors/file_system/box_api_call_flow.cc index e29a293..308886c 100644 --- a/chrome/browser/enterprise/connectors/file_system/box_api_call_flow.cc +++ b/chrome/browser/enterprise/connectors/file_system/box_api_call_flow.cc
@@ -6,7 +6,9 @@ #include <string> +#include "base/base64.h" #include "base/files/file_util.h" +#include "base/hash/sha1.h" #include "base/json/json_writer.h" #include "base/task/post_task.h" #include "base/values.h" @@ -441,7 +443,7 @@ // https://developer.box.com/reference/post-files-upload-sessions/ BoxCreateUploadSessionApiCallFlow::BoxCreateUploadSessionApiCallFlow( - Callback callback, + TaskCallback callback, const std::string& folder_id, const size_t file_size, const std::string& file_name) @@ -524,13 +526,123 @@ } //////////////////////////////////////////////////////////////////////////////// +// ChunkedUpload: PartFileUpload +//////////////////////////////////////////////////////////////////////////////// +// BoxApiCallFlow interface. +// API reference: +// https://developer.box.com/reference/put-files-upload-sessions-id/ + +BoxPartFileUploadApiCallFlow::BoxPartFileUploadApiCallFlow( + TaskCallback callback, + const std::string& upload_endpoint, + const std::string& file_part_content, + const size_t byte_from, + const size_t byte_to, + const size_t byte_total) + : callback_(std::move(callback)), + upload_endpoint_(upload_endpoint), + part_content_(file_part_content), + content_range_(base::StringPrintf("bytes %zu-%zu/%zu", + byte_from, + byte_to, + byte_total)), + sha_digest_(CreateFileDigest(file_part_content)) { + DCHECK(upload_endpoint_.is_valid()); +} + +BoxPartFileUploadApiCallFlow::~BoxPartFileUploadApiCallFlow() = default; + +std::string BoxPartFileUploadApiCallFlow::CreateFileDigest( + const std::string& content) { + // Box API requires the digest to be SHA1 and Base64 encoded. + std::string sha_encoded; + base::Base64Encode(base::SHA1HashString(content), &sha_encoded); + + std::string sha_digest("sha="); + sha_digest.append(sha_encoded); + sha_digest.append("="); + return sha_digest; +} + +GURL BoxPartFileUploadApiCallFlow::CreateApiCallUrl() { + return upload_endpoint_; +} + +net::HttpRequestHeaders BoxPartFileUploadApiCallFlow::CreateApiCallHeaders() { + net::HttpRequestHeaders headers; + headers.SetHeader("content-range", content_range_); + headers.SetHeader("digest", sha_digest_); + return headers; +} + +std::string BoxPartFileUploadApiCallFlow::CreateApiCallBody() { + return part_content_; +} +// TODO read the file in parts? #include "net/base/upload_file_element_reader.h" + +std::string BoxPartFileUploadApiCallFlow::CreateApiCallBodyContentType() { + return "application/octet-stream"; +} + +std::string BoxPartFileUploadApiCallFlow::GetRequestTypeForBody( + const std::string& body) { + CHECK(!body.empty()); + return "PUT"; +} + +bool BoxPartFileUploadApiCallFlow::IsExpectedSuccessCode(int code) const { + return code == net::HTTP_OK; +} + +void BoxPartFileUploadApiCallFlow::ProcessApiCallSuccess( + const network::mojom::URLResponseHead* head, + std::unique_ptr<std::string> body) { + DCHECK(body); + data_decoder::DataDecoder::ParseJsonIsolated( + *body, base::BindOnce(&BoxPartFileUploadApiCallFlow::OnJsonParsed, + factory_.GetWeakPtr())); +} + +void BoxPartFileUploadApiCallFlow::ProcessApiCallFailure( + int net_error, + const network::mojom::URLResponseHead* head, + std::unique_ptr<std::string> body) { + auto response_code = head->headers->response_code(); + DVLOG(1) << "[BoxApiCallFlow] PartFileUplaod failed. Error code " + << response_code; + std::move(callback_).Run(false, response_code, base::Value()); +} + +void BoxPartFileUploadApiCallFlow::OnJsonParsed( + data_decoder::DataDecoder::ValueOrError result) { + if (!result.value) { + DVLOG(1) << "[BoxApiCallFlow] PartFileUplaod OnJsonParsed Error: " + << (result.error ? result.error->data() + : "<no error info available>"); + std::move(callback_).Run(false, net::HTTP_OK, base::Value()); + return; + } + + base::Value* part = result.value ? result.value->FindPath("part") : nullptr; + if (!part) { + const char* msg = + result.value ? "<no part>" + : (result.error ? result.error->data() : "<no error>"); + DVLOG(1) << "BoxPartFileUploadApiCallFlow::OnJsonParsed: " << msg; + std::move(callback_).Run(false, net::HTTP_OK, base::Value()); + return; + } + std::move(callback_).Run(true, net::HTTP_OK, std::move(*part)); +} + +//////////////////////////////////////////////////////////////////////////////// // ChunkedUpload: CommitUploadSession //////////////////////////////////////////////////////////////////////////////// // BoxApiCallFlow interface. // API reference: // https://developer.box.com/reference/post-files-upload-sessions-id-commit/ BoxCommitUploadSessionApiCallFlow::BoxCommitUploadSessionApiCallFlow( - Callback callback, + TaskCallback callback, const std::string& commit_endpoint, const base::Value& parts, const std::string digest)
diff --git a/chrome/browser/enterprise/connectors/file_system/box_api_call_flow.h b/chrome/browser/enterprise/connectors/file_system/box_api_call_flow.h index f21f1754..59ef4aa8 100644 --- a/chrome/browser/enterprise/connectors/file_system/box_api_call_flow.h +++ b/chrome/browser/enterprise/connectors/file_system/box_api_call_flow.h
@@ -17,6 +17,9 @@ // be implemented by subclasses. class BoxApiCallFlow : public OAuth2ApiCallFlow { public: + // Callback args are: whether request returned success, and + // net::HttpStatusCode. + using TaskCallback = base::OnceCallback<void(bool, int)>; BoxApiCallFlow(); ~BoxApiCallFlow() override; @@ -33,9 +36,11 @@ static const size_t kWholeFileUploadMaxSize; }; -// Helper for finding the downloads folder in box. +// Helper for finding the downloads folder in Box. class BoxFindUpstreamFolderApiCallFlow : public BoxApiCallFlow { public: + // Additional callback arg is: folder_id for the downloads folder found in + // Box. using TaskCallback = base::OnceCallback<void(bool, int, const std::string&)>; explicit BoxFindUpstreamFolderApiCallFlow(TaskCallback callback); ~BoxFindUpstreamFolderApiCallFlow() override; @@ -61,6 +66,8 @@ // Helper for creating an upstream downloads folder in box. class BoxCreateUpstreamFolderApiCallFlow : public BoxApiCallFlow { public: + // Additional callback arg is: folder_id for the downloads folder created in + // Box. using TaskCallback = base::OnceCallback<void(bool, int, const std::string&)>; explicit BoxCreateUpstreamFolderApiCallFlow(TaskCallback callback); ~BoxCreateUpstreamFolderApiCallFlow() override; @@ -89,7 +96,6 @@ // downloads folder in box. class BoxWholeFileUploadApiCallFlow : public BoxApiCallFlow { public: - using TaskCallback = base::OnceCallback<void(bool, int)>; BoxWholeFileUploadApiCallFlow(TaskCallback callback, const std::string& folder_id, const base::FilePath& target_file_name, @@ -157,8 +163,10 @@ // in Box. class BoxCreateUploadSessionApiCallFlow : public BoxApiCallFlow { public: - using Callback = base::OnceCallback<void(bool, int, base::Value)>; - BoxCreateUploadSessionApiCallFlow(Callback callback, + // Additional callback arg is: session endpoints provided in API request + // response. + using TaskCallback = base::OnceCallback<void(bool, int, base::Value)>; + BoxCreateUploadSessionApiCallFlow(TaskCallback callback, const std::string& folder_id, const size_t file_size, const std::string& file_name); @@ -178,19 +186,65 @@ private: void OnJsonParsed(data_decoder::DataDecoder::ValueOrError result); - Callback callback_; + TaskCallback callback_; const std::string folder_id_; const size_t file_size_; const std::string file_name_; base::WeakPtrFactory<BoxCreateUploadSessionApiCallFlow> factory_{this}; }; +// Helper for uploading a part of the file to Box. +class BoxPartFileUploadApiCallFlow : public BoxApiCallFlow { + public: + // Additional callback arg is: uploaded file part info in API request response + // that needs to be attached in CommitUploadSession request. + // Callback invoked when the file part upload completes. The bool argument is + // true if the upload succeeded and false otherwise. The int argument + // represents the final HTTP status code of the request. The Value holds a + // JSON part object as returned by the Box Upload Part API, which is valid + // only on success. + using TaskCallback = base::OnceCallback<void(bool, int, base::Value)>; + BoxPartFileUploadApiCallFlow(TaskCallback callback, + const std::string& upload_endpoint, + const std::string& file_part_content, + const size_t byte_from, + const size_t byte_to, + const size_t byte_total); + ~BoxPartFileUploadApiCallFlow() override; + + // Helper method. + static std::string CreateFileDigest(const std::string& content); + + protected: + // BoxApiCallFlow interface. + GURL CreateApiCallUrl() override; + net::HttpRequestHeaders CreateApiCallHeaders() override; + std::string CreateApiCallBody() override; + std::string CreateApiCallBodyContentType() override; + std::string GetRequestTypeForBody(const std::string& body) override; + bool IsExpectedSuccessCode(int code) const override; + void ProcessApiCallSuccess(const network::mojom::URLResponseHead* head, + std::unique_ptr<std::string> body) override; + void ProcessApiCallFailure(int net_error, + const network::mojom::URLResponseHead* head, + std::unique_ptr<std::string> body) override; + + private: + void OnJsonParsed(data_decoder::DataDecoder::ValueOrError result); + + TaskCallback callback_; + const GURL upload_endpoint_; + const std::string& part_content_; + const std::string content_range_; + const std::string sha_digest_; + base::WeakPtrFactory<BoxPartFileUploadApiCallFlow> factory_{this}; +}; + // Helper for committing an upload session once all the parts are uploaded // successfully. class BoxCommitUploadSessionApiCallFlow : public BoxApiCallFlow { public: - using Callback = base::OnceCallback<void(bool, int)>; - BoxCommitUploadSessionApiCallFlow(Callback callback, + BoxCommitUploadSessionApiCallFlow(TaskCallback callback, const std::string& commit_endpoint, const base::Value& parts, const std::string digest); @@ -209,7 +263,7 @@ std::unique_ptr<std::string> body) override; private: - Callback callback_; + TaskCallback callback_; const std::string commit_endpoint_; const base::Value upload_session_parts_; const std::string sha_digest_;
diff --git a/chrome/browser/enterprise/connectors/file_system/box_api_call_flow_unittest.cc b/chrome/browser/enterprise/connectors/file_system/box_api_call_flow_unittest.cc index 6d6cbc7..a7dbb1d 100644 --- a/chrome/browser/enterprise/connectors/file_system/box_api_call_flow_unittest.cc +++ b/chrome/browser/enterprise/connectors/file_system/box_api_call_flow_unittest.cc
@@ -8,6 +8,7 @@ #include <memory> +#include "base/base64.h" #include "base/bind.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" @@ -633,6 +634,146 @@ } //////////////////////////////////////////////////////////////////////////////// +// PartFileUpload +//////////////////////////////////////////////////////////////////////////////// + +class BoxPartFileUploadApiCallFlowForTest + : public BoxPartFileUploadApiCallFlow { + public: + using BoxPartFileUploadApiCallFlow::BoxPartFileUploadApiCallFlow; + using BoxPartFileUploadApiCallFlow::CreateApiCallBody; + using BoxPartFileUploadApiCallFlow::CreateApiCallBodyContentType; + using BoxPartFileUploadApiCallFlow::CreateApiCallHeaders; + using BoxPartFileUploadApiCallFlow::CreateApiCallUrl; + using BoxPartFileUploadApiCallFlow::CreateFileDigest; + using BoxPartFileUploadApiCallFlow::GetRequestTypeForBody; + using BoxPartFileUploadApiCallFlow::IsExpectedSuccessCode; + using BoxPartFileUploadApiCallFlow::ProcessApiCallFailure; + using BoxPartFileUploadApiCallFlow::ProcessApiCallSuccess; +}; + +class BoxPartFileUploadApiCallFlowTest + : public BoxApiCallFlowTest<BoxPartFileUploadApiCallFlowForTest> { + protected: + BoxPartFileUploadApiCallFlowTest() + : file_content_("random file part content"), + expected_sha_( + BoxPartFileUploadApiCallFlow::CreateFileDigest(file_content_)), + expected_content_range_(base::StringPrintf("bytes 0-%zu/%zu", + file_content_.size(), + file_content_.size())) {} + + void SetUp() override { + flow_ = std::make_unique<BoxPartFileUploadApiCallFlowForTest>( + base::BindOnce(&BoxPartFileUploadApiCallFlowTest::OnResponse, + factory_.GetWeakPtr()), + upload_endpoint_, file_content_, 0, file_content_.size(), + file_content_.size()); + } + + void OnResponse(bool success, int response_code, base::Value) { + processed_success_ = success; + response_code_ = response_code; + if (quit_closure_) + std::move(quit_closure_).Run(); + } + + const std::string upload_endpoint_ = "https://provider.com/upload/id=12345"; + const std::string file_content_; + const std::string expected_sha_; + const std::string expected_content_range_; + + base::test::SingleThreadTaskEnvironment task_environment_; + data_decoder::test::InProcessDataDecoder decoder_; + base::OnceClosure quit_closure_; + base::WeakPtrFactory<BoxPartFileUploadApiCallFlowTest> factory_{this}; +}; + +TEST_F(BoxPartFileUploadApiCallFlowTest, CreateApiCallUrl) { + ASSERT_EQ(flow_->CreateApiCallUrl(), upload_endpoint_); +} + +TEST_F(BoxPartFileUploadApiCallFlowTest, CreateApiCallHeaders) { + net::HttpRequestHeaders headers = flow_->CreateApiCallHeaders(); + std::string digest; + headers.GetHeader("digest", &digest); + base::Base64Decode(digest, &digest); + EXPECT_EQ(digest, expected_sha_); + + std::string content_range; + headers.GetHeader("content-range", &content_range); + EXPECT_EQ(content_range, expected_content_range_) << headers.ToString(); +} + +TEST_F(BoxPartFileUploadApiCallFlowTest, CreateApiCallBody) { + std::string body = flow_->CreateApiCallBody(); + ASSERT_EQ(body, file_content_); +} + +TEST_F(BoxPartFileUploadApiCallFlowTest, CreateApiCallBodyContentType) { + std::string type = flow_->CreateApiCallBodyContentType(); + ASSERT_EQ(type, "application/octet-stream"); +} + +TEST_F(BoxPartFileUploadApiCallFlowTest, GetRequestTypeForBody) { + std::string type = flow_->GetRequestTypeForBody(file_content_); + ASSERT_EQ(type, "PUT"); +} + +TEST_F(BoxPartFileUploadApiCallFlowTest, IsExpectedSuccessCode) { + ASSERT_TRUE(flow_->IsExpectedSuccessCode(200)); + ASSERT_FALSE(flow_->IsExpectedSuccessCode(201)); + ASSERT_FALSE(flow_->IsExpectedSuccessCode(202)); + ASSERT_FALSE(flow_->IsExpectedSuccessCode(400)); + ASSERT_FALSE(flow_->IsExpectedSuccessCode(404)); + ASSERT_FALSE(flow_->IsExpectedSuccessCode(409)); + ASSERT_FALSE(flow_->IsExpectedSuccessCode(412)); +} + +TEST_F(BoxPartFileUploadApiCallFlowTest, ProcessApiCallSuccess) { + auto http_head = network::CreateURLResponseHead(net::HTTP_OK); + std::string body(R"({ + "part": { + "offset": 16777216, + "part_id": "6F2D3486", + "sha1": "134b65991ed521fcfe4724b7d814ab8ded5185dc", + "size": 3222784 + } + })"); + flow_->ProcessApiCallSuccess(http_head.get(), + std::make_unique<std::string>(body)); + base::RunLoop().RunUntilIdle(); + ASSERT_TRUE(processed_success_); + ASSERT_EQ(response_code_, net::HTTP_OK); +} + +TEST_F(BoxPartFileUploadApiCallFlowTest, ProcessApiCallSuccess_ParseError) { + auto http_head = network::CreateURLResponseHead(net::HTTP_OK); + flow_->ProcessApiCallSuccess(http_head.get(), + std::make_unique<std::string>()); + base::RunLoop().RunUntilIdle(); + ASSERT_FALSE(processed_success_); + ASSERT_EQ(response_code_, net::HTTP_OK); +} + +TEST_F(BoxPartFileUploadApiCallFlowTest, ProcessApiCallSuccess_EmptyResponse) { + auto http_head = network::CreateURLResponseHead(net::HTTP_OK); + flow_->ProcessApiCallSuccess( + http_head.get(), std::make_unique<std::string>(kEmptyResponseBody)); + base::RunLoop().RunUntilIdle(); + ASSERT_FALSE(processed_success_); + ASSERT_EQ(response_code_, net::HTTP_OK); +} + +TEST_F(BoxPartFileUploadApiCallFlowTest, ProcessApiCallFailure) { + auto http_head = network::CreateURLResponseHead(net::HTTP_CONFLICT); + flow_->ProcessApiCallFailure(net::OK, http_head.get(), {}); + base::RunLoop().RunUntilIdle(); + ASSERT_FALSE(processed_success_); + ASSERT_EQ(response_code_, net::HTTP_CONFLICT); +} + +//////////////////////////////////////////////////////////////////////////////// // CommitUploadSession ////////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/enterprise/connectors/file_system/box_api_call_test_helper.cc b/chrome/browser/enterprise/connectors/file_system/box_api_call_test_helper.cc index 543d94b..012bf7d 100644 --- a/chrome/browser/enterprise/connectors/file_system/box_api_call_test_helper.cc +++ b/chrome/browser/enterprise/connectors/file_system/box_api_call_test_helper.cc
@@ -10,6 +10,8 @@ const char kFileSystemBoxCreateFolderUrl[] = "https://api.box.com/2.0/folders"; const char kFileSystemBoxWholeFileUploadUrl[] = "https://upload.box.com/api/2.0/files/content"; + +const char kEmptyResponseBody[] = R"({})"; const char kFileSystemBoxFindFolderResponseBody[] = R"({ "entries": [ {
diff --git a/chrome/browser/enterprise/connectors/file_system/box_api_call_test_helper.h b/chrome/browser/enterprise/connectors/file_system/box_api_call_test_helper.h index 545d33a..39a4083 100644 --- a/chrome/browser/enterprise/connectors/file_system/box_api_call_test_helper.h +++ b/chrome/browser/enterprise/connectors/file_system/box_api_call_test_helper.h
@@ -12,9 +12,10 @@ extern const char kFileSystemBoxCreateFolderUrl[]; extern const char kFileSystemBoxWholeFileUploadUrl[]; -// Expected responses for calls to Box endpoints; used for -// network::TestURLLoaderFactory. +// Expected responses for calls to Box endpoints. +// Empty response body. +extern const char kEmptyResponseBody[]; // Expected response from kFileSystemBoxFindFolderUrl. extern const char kFileSystemBoxFindFolderResponseBody[]; // Expected folder id extracted from kFileSystemBoxFindFolderResponseBody.
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index acc80217..b72095a0 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -116,7 +116,7 @@ }, { "name": "android-detailed-language-settings", - "owners": [ "perrier", "chrome-langauge@google.com" ], + "owners": [ "perrier", "chrome-language@google.com" ], "expiry_milestone": 91 }, { @@ -595,11 +595,6 @@ "expiry_milestone": 78 }, { - "name": "click-to-call-ui", - "owners": [ "//chrome/browser/sharing/OWNERS" ], - "expiry_milestone": 90 - }, - { "name": "client-storage-access-context-auditing", "owners": [ "sauski", @@ -619,11 +614,6 @@ "expiry_milestone": 80 }, { - "name": "color-picker-eye-dropper", - "owners": [ "iopopesc@microsoft.com", "masonfreed" ], - "expiry_milestone": 90 - }, - { "name": "color-provider-redirection", "owners": [ "//ui/color/OWNERS" ], "expiry_milestone": 88 @@ -964,7 +954,7 @@ }, { "name": "desktop-restructured-language-settings", - "owners": [ "joshsantana", "chrome-langauge@google.com"], + "owners": [ "joshsantana", "chrome-language@google.com"], "expiry_milestone": 93 }, { @@ -999,8 +989,8 @@ }, { "name": "diagnostics-app", - "owners": [ "baileyberro", "jimmyxgong", "zentaro"], - "expiry_milestone": 90 + "owners": [ "//chromeos/components/diagnostics_ui/OWNERS" ], + "expiry_milestone": 92 }, { "name": "dice-web-signin-interception", @@ -1643,6 +1633,11 @@ "expiry_milestone": 93 }, { + "name": "enable-desktop-pwas-protocol-handling", + "owners": [ "samtan@microsoft.com", "desktop-pwas-team@google.com" ], + "expiry_milestone": 95 + }, + { "name": "enable-desktop-pwas-remove-status-bar", "owners": [ "dmurph@chromium.org", "desktop-pwas-team@google.com" ], "expiry_milestone": 91 @@ -1799,7 +1794,7 @@ { "name": "enable-generic-sensor-extra-classes", "owners": [ "reillyg@chromium.org", "raphael.kubo.da.costa@intel.com" ], - "expiry_milestone": 90 + "expiry_milestone": 94 }, { "name": "enable-google-srp-isolated-prerender-nsp", @@ -3585,11 +3580,6 @@ "expiry_milestone": 84 }, { - "name": "movable-partial-screenshot-region", - "owners": [ "xiyuan", "chromeos-wmp-eng" ], - "expiry_milestone": 90 - }, - { "name": "nearby-sharing", "owners": [ "vecore@google.com", "cros-system-services@google.com", "cross-device-team@google.com" ], "expiry_milestone": 95 @@ -4665,11 +4655,6 @@ "expiry_milestone": 92 }, { - "name": "share-by-default-in-cct", - "owners": [ "sophey", "chrome-sharing-eng@google.com" ], - "expiry_milestone": 90 - }, - { "name": "shared-clipboard-ui", "owners": [ "//chrome/browser/sharing/OWNERS" ], "expiry_milestone": 90
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 417e19b..208018d 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -736,6 +736,11 @@ "user logs in. Launching a PWA while the browser is not running is known " "to cause a failure to restore sessions. See https://crbug.com/938759."; +const char kDesktopPWAsProtocolHandlingName[] = "Desktop PWA Protocol handling"; +const char kDesktopPWAsProtocolHandlingDescription[] = + "Enable web app manifests to declare protocol handling behavior." + "See: https://crbug.com/1019239."; + const char kDesktopPWAsUrlHandlingName[] = "Desktop PWA URL handling"; const char kDesktopPWAsUrlHandlingDescription[] = "Enable web app manifests to declare URL handling behavior. Prototype " @@ -1210,11 +1215,6 @@ const char kFormControlsRefreshDescription[] = "If enabled, HTML forms elements will be rendered using an updated style."; -const char kColorPickerEyeDropperName[] = "Color Picker Eye Dropper Support"; -const char kColorPickerEyeDropperDescription[] = - "If enabled, the color picker will contain an eye dropper control that " - "can be used to pick colors."; - const char kGlobalMediaControlsName[] = "Global Media Controls"; const char kGlobalMediaControlsDescription[] = "Enables the Global Media Controls UI in the toolbar."; @@ -2124,10 +2124,6 @@ const char kSidePanelName[] = "Side panel"; const char kSidePanelDescription[] = "Host some content in a side panel."; -const char kShareByDefaultInCCTName[] = "Enable sharing by default in CCT."; -const char kShareByDefaultInCCTDescription[] = - "Enables a sharing option by default in Chrome Custom Tabs."; - const char kSharedClipboardUIName[] = "Enable shared clipboard feature signals to be handled"; const char kSharedClipboardUIDescription[] = @@ -4071,11 +4067,6 @@ const char kDriveFsBidirectionalNativeMessagingDescription[] = "Enable enhanced native messaging host to communicate with DriveFS."; -const char kMovablePartialScreenshotName[] = - "Movable/resizable partial screenshot region"; -const char kMovablePartialScreenshotDescription[] = - "Allow partial screenshot region to be moved/resized via mouse/touch."; - const char kEnableAppDataSearchName[] = "Enable app data search in launcher"; const char kEnableAppDataSearchDescription[] = "Allow launcher search to access data available through Firebase App " @@ -5044,14 +5035,6 @@ "rather than crashing. If enabled, DCHECKs will crash the calling process."; #endif // defined(DCHECK_IS_CONFIGURABLE) -#if BUILDFLAG(ENABLE_CLICK_TO_CALL) -const char kClickToCallUIName[] = - "Enable click to call feature signals to be handled on desktop"; -const char kClickToCallUIDescription[] = - "Enables click to call feature signals to be handled on desktop by showing " - "a list of user's available devices with telephony functionality."; -#endif // BUILDFLAG(ENABLE_CLICK_TO_CALL) - #if BUILDFLAG(ENABLE_DICE_SUPPORT) const char kDiceWebSigninInterceptionName[] = "Dice Web-Signin Interception"; const char kDiceWebSigninInterceptionDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 7957510..26360f2 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -459,6 +459,9 @@ extern const char kDesktopPWAsRunOnOsLoginName[]; extern const char kDesktopPWAsRunOnOsLoginDescription[]; +extern const char kDesktopPWAsProtocolHandlingName[]; +extern const char kDesktopPWAsProtocolHandlingDescription[]; + extern const char kDesktopPWAsUrlHandlingName[]; extern const char kDesktopPWAsUrlHandlingDescription[]; @@ -727,9 +730,6 @@ extern const char kFormControlsRefreshName[]; extern const char kFormControlsRefreshDescription[]; -extern const char kColorPickerEyeDropperName[]; -extern const char kColorPickerEyeDropperDescription[]; - extern const char kGlobalMediaControlsName[]; extern const char kGlobalMediaControlsDescription[]; @@ -1248,9 +1248,6 @@ extern const char kSidePanelName[]; extern const char kSidePanelDescription[]; -extern const char kShareByDefaultInCCTName[]; -extern const char kShareByDefaultInCCTDescription[]; - extern const char kSharedClipboardUIName[]; extern const char kSharedClipboardUIDescription[]; @@ -2367,9 +2364,6 @@ extern const char kDriveFsBidirectionalNativeMessagingName[]; extern const char kDriveFsBidirectionalNativeMessagingDescription[]; -extern const char kMovablePartialScreenshotName[]; -extern const char kMovablePartialScreenshotDescription[]; - extern const char kEnableAdvancedPpdAttributesName[]; extern const char kEnableAdvancedPpdAttributesDescription[]; @@ -2974,11 +2968,6 @@ extern const char kDcheckIsFatalDescription[]; #endif // defined(DCHECK_IS_CONFIGURABLE) -#if BUILDFLAG(ENABLE_CLICK_TO_CALL) -extern const char kClickToCallUIName[]; -extern const char kClickToCallUIDescription[]; -#endif // BUILDFLAG(ENABLE_CLICK_TO_CALL) - #if BUILDFLAG(ENABLE_DICE_SUPPORT) extern const char kDiceWebSigninInterceptionName[]; extern const char kDiceWebSigninInterceptionDescription[];
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc index 58aff9f..46b6240f 100644 --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -217,7 +217,6 @@ &kServiceManagerForBackgroundPrefetch, &kServiceManagerForDownload, &kShareButtonInTopToolbar, - &kShareByDefaultInCCT, &kSharedClipboardUI, &kShoppingAssist, &kSpannableInlineAutocomplete, @@ -608,9 +607,6 @@ const base::Feature kShareButtonInTopToolbar{"ShareButtonInTopToolbar", base::FEATURE_DISABLED_BY_DEFAULT}; -const base::Feature kShareByDefaultInCCT{"ShareByDefaultInCCT", - base::FEATURE_ENABLED_BY_DEFAULT}; - const base::Feature kShoppingAssist{"ShoppingAssist", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h index 2db7380..5c24425e 100644 --- a/chrome/browser/flags/android/chrome_feature_list.h +++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -109,7 +109,6 @@ extern const base::Feature kServiceManagerForBackgroundPrefetch; extern const base::Feature kServiceManagerForDownload; extern const base::Feature kShareButtonInTopToolbar; -extern const base::Feature kShareByDefaultInCCT; extern const base::Feature kShoppingAssist; extern const base::Feature kSpannableInlineAutocomplete; extern const base::Feature kSpecialLocaleWrapper;
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java index 4c6752b..db71456 100644 --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java
@@ -60,7 +60,6 @@ put(ChromeFeatureList.EARLY_LIBRARY_LOAD, false); put(ChromeFeatureList.PRIORITIZE_BOOTSTRAP_TASKS, true); put(ChromeFeatureList.IMMERSIVE_UI_MODE, false); - put(ChromeFeatureList.SHARE_BY_DEFAULT_IN_CCT, true); put(ChromeFeatureList.SWAP_PIXEL_FORMAT_TO_FIX_CONVERT_FROM_TRANSLUCENT, true); put(ChromeFeatureList.START_SURFACE_ANDROID, false); put(ChromeFeatureList.PAINT_PREVIEW_DEMO, false);
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 f114d9d4..460b32c5 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
@@ -428,7 +428,6 @@ "ServiceManagerForBackgroundPrefetch"; public static final String SERVICE_MANAGER_FOR_DOWNLOAD = "ServiceManagerForDownload"; public static final String SHARE_BUTTON_IN_TOP_TOOLBAR = "ShareButtonInTopToolbar"; - public static final String SHARE_BY_DEFAULT_IN_CCT = "ShareByDefaultInCCT"; public static final String SHARED_CLIPBOARD_UI = "SharedClipboardUI"; public static final String SHOW_TRUSTED_PUBLISHER_URL = "ShowTrustedPublisherURL"; public static final String SMART_SUGGESTION_FOR_LARGE_DOWNLOADS =
diff --git a/chrome/browser/history/history_service_factory.cc b/chrome/browser/history/history_service_factory.cc index 8ae55f1..4acc96a 100644 --- a/chrome/browser/history/history_service_factory.cc +++ b/chrome/browser/history/history_service_factory.cc
@@ -8,7 +8,6 @@ #include "chrome/browser/history/chrome_history_client.h" #include "chrome/browser/profiles/incognito_helpers.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/common/pref_names.h" #include "components/bookmarks/browser/bookmark_model.h" #include "components/history/content/browser/content_visit_delegate.h" #include "components/history/content/browser/history_database_helper.h"
diff --git a/chrome/browser/language/android/java/res/xml/languages_detailed_preferences.xml b/chrome/browser/language/android/java/res/xml/languages_detailed_preferences.xml index 82983e2..02154c9 100644 --- a/chrome/browser/language/android/java/res/xml/languages_detailed_preferences.xml +++ b/chrome/browser/language/android/java/res/xml/languages_detailed_preferences.xml
@@ -17,7 +17,7 @@ </PreferenceCategory> <PreferenceCategory - android:key="content_langauges_section" + android:key="content_languages_section" android:title="@string/languages_content_title" android:order="2" app:allowDividerAbove="true">
diff --git a/chrome/browser/media/webrtc/webrtc_event_log_manager_unittest.cc b/chrome/browser/media/webrtc/webrtc_event_log_manager_unittest.cc index 1e10791..96cc0f3 100644 --- a/chrome/browser/media/webrtc/webrtc_event_log_manager_unittest.cc +++ b/chrome/browser/media/webrtc/webrtc_event_log_manager_unittest.cc
@@ -2274,7 +2274,9 @@ ExpectRemoteFileContents(*file_path, std::string()); } -TEST_F(WebRtcEventLogManagerTest, RemoteLogFileCreatedInCorrectDirectory) { +// TODO(crbug.com/1185008): Fix this flaky test. +TEST_F(WebRtcEventLogManagerTest, + DISABLED_RemoteLogFileCreatedInCorrectDirectory) { // Set up separate browser contexts; each one will get one log. constexpr size_t kLogsNum = 3; std::unique_ptr<TestingProfile> browser_contexts[kLogsNum];
diff --git a/chrome/browser/media_galleries/chromeos/mtp_device_task_helper.cc b/chrome/browser/media_galleries/chromeos/mtp_device_task_helper.cc index e644dc6..a2bd9ca 100644 --- a/chrome/browser/media_galleries/chromeos/mtp_device_task_helper.cc +++ b/chrome/browser/media_galleries/chromeos/mtp_device_task_helper.cc
@@ -435,10 +435,10 @@ uint32_t bytes_to_read = std::min(base::checked_cast<uint32_t>(request.buf_len), base::saturated_cast<uint32_t>(file_info.size - request.offset)); - + auto file_id = request.file_id; + auto offset = base::checked_cast<uint32_t>(request.offset); GetMediaTransferProtocolManager()->ReadFileChunk( - device_handle_, request.file_id, - base::checked_cast<uint32_t>(request.offset), bytes_to_read, + device_handle_, file_id, offset, bytes_to_read, base::BindOnce(&MTPDeviceTaskHelper::OnDidReadBytes, weak_ptr_factory_.GetWeakPtr(), std::move(request), file_info));
diff --git a/chrome/browser/optimization_guide/android/DEPS b/chrome/browser/optimization_guide/android/DEPS index 0d019e1..5bbfd42 100644 --- a/chrome/browser/optimization_guide/android/DEPS +++ b/chrome/browser/optimization_guide/android/DEPS
@@ -1,3 +1,4 @@ include_rules = [ "+content/public/android/java", + "+content/public/test", ]
diff --git a/chrome/browser/optimization_guide/android/optimization_guide_bridge_unittest.cc b/chrome/browser/optimization_guide/android/optimization_guide_bridge_unittest.cc index b1be12f1..c50edb82 100644 --- a/chrome/browser/optimization_guide/android/optimization_guide_bridge_unittest.cc +++ b/chrome/browser/optimization_guide/android/optimization_guide_bridge_unittest.cc
@@ -38,6 +38,7 @@ pref_service, /*hint_store=*/nullptr, /*top_host_provider=*/nullptr, + /*tab_url_provider=*/nullptr, /*url_loader_factory=*/nullptr) {} ~MockOptimizationGuideHintsManager() override = default; MOCK_METHOD4(CanApplyOptimizationAsync,
diff --git a/chrome/browser/optimization_guide/android/optimization_guide_tab_url_provider_android.cc b/chrome/browser/optimization_guide/android/optimization_guide_tab_url_provider_android.cc new file mode 100644 index 0000000..b5b50ff --- /dev/null +++ b/chrome/browser/optimization_guide/android/optimization_guide_tab_url_provider_android.cc
@@ -0,0 +1,42 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/optimization_guide/android/optimization_guide_tab_url_provider_android.h" + +#include "chrome/browser/android/tab_android.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/android/tab_model/tab_model.h" +#include "chrome/browser/ui/android/tab_model/tab_model_list.h" +#include "content/public/browser/web_contents.h" + +namespace optimization_guide { +namespace android { + +OptimizationGuideTabUrlProviderAndroid::OptimizationGuideTabUrlProviderAndroid( + Profile* profile) + : OptimizationGuideTabUrlProvider(profile) {} +OptimizationGuideTabUrlProviderAndroid:: + ~OptimizationGuideTabUrlProviderAndroid() = default; + +const std::vector<content::WebContents*> +OptimizationGuideTabUrlProviderAndroid::GetAllWebContentsForProfile( + Profile* profile) { + std::vector<content::WebContents*> web_contents_list; + for (auto tab_model = TabModelList::begin(); tab_model != TabModelList::end(); + ++tab_model) { + if ((*tab_model)->GetProfile() != profile) + continue; + + int tab_count = (*tab_model)->GetTabCount(); + for (int i = 0; i < tab_count; i++) { + content::WebContents* web_contents = (*tab_model)->GetWebContentsAt(i); + if (web_contents) + web_contents_list.push_back(web_contents); + } + } + return web_contents_list; +} + +} // namespace android +} // namespace optimization_guide
diff --git a/chrome/browser/optimization_guide/android/optimization_guide_tab_url_provider_android.h b/chrome/browser/optimization_guide/android/optimization_guide_tab_url_provider_android.h new file mode 100644 index 0000000..7c9cc87 --- /dev/null +++ b/chrome/browser/optimization_guide/android/optimization_guide_tab_url_provider_android.h
@@ -0,0 +1,30 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_OPTIMIZATION_GUIDE_ANDROID_OPTIMIZATION_GUIDE_TAB_URL_PROVIDER_ANDROID_H_ +#define CHROME_BROWSER_OPTIMIZATION_GUIDE_ANDROID_OPTIMIZATION_GUIDE_TAB_URL_PROVIDER_ANDROID_H_ + +#include "chrome/browser/optimization_guide/optimization_guide_tab_url_provider.h" + +namespace optimization_guide { +namespace android { + +// Implementation of OptimizationGuideTabUrlProvider that gets URLs from Android +// browser windows. +class OptimizationGuideTabUrlProviderAndroid + : public OptimizationGuideTabUrlProvider { + public: + explicit OptimizationGuideTabUrlProviderAndroid(Profile* profile); + ~OptimizationGuideTabUrlProviderAndroid() override; + + private: + // OptimizationGuideTabUrlProvider: + const std::vector<content::WebContents*> GetAllWebContentsForProfile( + Profile* profile) override; +}; + +} // namespace android +} // namespace optimization_guide + +#endif // CHROME_BROWSER_OPTIMIZATION_GUIDE_ANDROID_OPTIMIZATION_GUIDE_TAB_URL_PROVIDER_ANDROID_H_
diff --git a/chrome/browser/optimization_guide/android/optimization_guide_tab_url_provider_android_unittest.cc b/chrome/browser/optimization_guide/android/optimization_guide_tab_url_provider_android_unittest.cc new file mode 100644 index 0000000..5a4d9ac --- /dev/null +++ b/chrome/browser/optimization_guide/android/optimization_guide_tab_url_provider_android_unittest.cc
@@ -0,0 +1,140 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/optimization_guide/android/optimization_guide_tab_url_provider_android.h" + +#include "chrome/browser/android/tab_android.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/android/tab_model/tab_model.h" +#include "chrome/browser/ui/android/tab_model/tab_model_list.h" +#include "chrome/test/base/chrome_render_view_host_test_harness.h" +#include "content/public/test/web_contents_tester.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace optimization_guide { +namespace android { +namespace { + +using ::testing::ElementsAre; + +// FakeTabModel that can be used for testing Android tab behavior. +class FakeTabModel : public TabModel { + public: + explicit FakeTabModel( + Profile* profile, + const std::vector<content::WebContents*>& web_contents_list) + : TabModel(profile, /*is_tabbed_activity=*/false), + web_contents_list_(web_contents_list) {} + + int GetTabCount() const override { + return static_cast<int>(web_contents_list_.size()); + } + int GetActiveIndex() const override { return 0; } + content::WebContents* GetWebContentsAt(int index) const override { + if (index < static_cast<int>(web_contents_list_.size())) + return web_contents_list_[index]; + return nullptr; + } + + base::android::ScopedJavaLocalRef<jobject> GetJavaObject() const override { + return nullptr; + } + void CreateTab(TabAndroid* parent, + content::WebContents* web_contents) override {} + void HandlePopupNavigation(TabAndroid* parent, + NavigateParams* params) override {} + content::WebContents* CreateNewTabForDevTools(const GURL& url) override { + return nullptr; + } + bool IsSessionRestoreInProgress() const override { return false; } + bool IsActiveModel() const override { return false; } + TabAndroid* GetTabAt(int index) const override { return nullptr; } + void SetActiveIndex(int index) override {} + void CloseTabAt(int index) override {} + void AddObserver(TabModelObserver* observer) override {} + void RemoveObserver(TabModelObserver* observer) override {} + + private: + std::vector<content::WebContents*> web_contents_list_; +}; + +class OptimizationGuideTabUrlProviderAndroidTest + : public ChromeRenderViewHostTestHarness { + public: + OptimizationGuideTabUrlProviderAndroidTest() = default; + ~OptimizationGuideTabUrlProviderAndroidTest() override = default; + + void SetUp() override { + ChromeRenderViewHostTestHarness::SetUp(); + tab_url_provider_ = + std::make_unique<OptimizationGuideTabUrlProviderAndroid>(profile()); + } + + void TearDown() override { + tab_url_provider_.reset(); + ChromeRenderViewHostTestHarness::TearDown(); + } + + OptimizationGuideTabUrlProviderAndroid* tab_url_provider() const { + return tab_url_provider_.get(); + } + + private: + std::unique_ptr<OptimizationGuideTabUrlProviderAndroid> tab_url_provider_; +}; + +TEST_F(OptimizationGuideTabUrlProviderAndroidTest, + GetUrlsOfActiveTabsNoOpenTabs) { + std::vector<GURL> urls = + tab_url_provider()->GetUrlsOfActiveTabs(base::TimeDelta::FromDays(90)); + EXPECT_TRUE(urls.empty()); +} + +TEST_F(OptimizationGuideTabUrlProviderAndroidTest, + GetUrlsOfActiveTabsFiltersOutTabs) { + std::unique_ptr<content::WebContents> web_contents = + content::WebContentsTester::CreateTestWebContents( + browser_context(), content::SiteInstance::Create(browser_context())); + content::WebContentsTester* web_contents_tester = + content::WebContentsTester::For(web_contents.get()); + web_contents_tester->SetLastCommittedURL(GURL("https://example.com/a")); + std::unique_ptr<content::WebContents> web_contents2 = + content::WebContentsTester::CreateTestWebContents( + browser_context(), content::SiteInstance::Create(browser_context())); + content::WebContentsTester* web_contents_tester2 = + content::WebContentsTester::For(web_contents2.get()); + web_contents_tester2->SetLastCommittedURL(GURL("https://example.com/b")); + web_contents_tester2->SetLastActiveTime(base::TimeTicks::Now() - + base::TimeDelta::FromDays(2)); + std::unique_ptr<content::WebContents> stale_web_contents = + content::WebContentsTester::CreateTestWebContents( + browser_context(), content::SiteInstance::Create(browser_context())); + content::WebContentsTester* stale_web_contents_tester = + content::WebContentsTester::For(stale_web_contents.get()); + stale_web_contents_tester->SetLastActiveTime(base::TimeTicks::Now() - + base::TimeDelta::FromDays(100)); + stale_web_contents_tester->SetLastCommittedURL(GURL("https://stale.com")); + FakeTabModel tab_model(profile(), {web_contents.get(), web_contents2.get(), + stale_web_contents.get()}); + TabModelList::AddTabModel(&tab_model); + + std::unique_ptr<content::WebContents> otr_web_contents = + content::WebContentsTester::CreateTestWebContents( + browser_context(), content::SiteInstance::Create(browser_context())); + content::WebContentsTester* otr_web_contents_tester = + content::WebContentsTester::For(otr_web_contents.get()); + otr_web_contents_tester->SetLastCommittedURL(GURL("https://incognito.com")); + FakeTabModel otr_tab_model(profile()->GetPrimaryOTRProfile(), + {otr_web_contents.get()}); + TabModelList::AddTabModel(&otr_tab_model); + + std::vector<GURL> urls = + tab_url_provider()->GetUrlsOfActiveTabs(base::TimeDelta::FromDays(90)); + EXPECT_THAT(urls, ElementsAre(GURL("https://example.com/a"), + GURL("https://example.com/b"))); +} + +} // namespace +} // namespace android +} // namespace optimization_guide
diff --git a/chrome/browser/optimization_guide/optimization_guide_hints_manager.cc b/chrome/browser/optimization_guide/optimization_guide_hints_manager.cc index ed431f2..72353c7 100644 --- a/chrome/browser/optimization_guide/optimization_guide_hints_manager.cc +++ b/chrome/browser/optimization_guide/optimization_guide_hints_manager.cc
@@ -44,6 +44,7 @@ #include "components/optimization_guide/core/optimization_guide_util.h" #include "components/optimization_guide/core/optimization_hints_component_update_listener.h" #include "components/optimization_guide/core/optimization_metadata.h" +#include "components/optimization_guide/core/tab_url_provider.h" #include "components/optimization_guide/core/top_host_provider.h" #include "components/optimization_guide/proto/models.pb.h" #include "components/prefs/pref_service.h" @@ -64,11 +65,6 @@ // startup will have a newer version than it. constexpr char kManualConfigComponentVersion[] = "0.0.0"; -// Delay until successfully fetched hints should be updated by requesting from -// the remote Optimization Guide Service. -constexpr base::TimeDelta kUpdateFetchedHintsDelay = - base::TimeDelta::FromHours(24); - // Provides a random time delta in seconds between |kFetchRandomMinDelay| and // |kFetchRandomMaxDelay|. base::TimeDelta RandomFetchDelay() { @@ -255,6 +251,7 @@ PrefService* pref_service, optimization_guide::OptimizationGuideStore* hint_store, optimization_guide::TopHostProvider* top_host_provider, + optimization_guide::TabUrlProvider* tab_url_provider, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) : background_task_runner_(base::ThreadPool::CreateSequencedTaskRunner( {base::MayBlock(), base::TaskPriority::BEST_EFFORT})), @@ -276,6 +273,7 @@ optimization_guide::features:: ExternalAppPackageNamesApprovedForFetch()), top_host_provider_(top_host_provider), + tab_url_provider_(tab_url_provider), clock_(base::DefaultClock::GetInstance()) { g_browser_process->network_quality_tracker() ->AddEffectiveConnectionTypeObserver(this); @@ -596,7 +594,7 @@ optimization_guide::kComponentHintsUpdatedResultHistogramString, hints_updated); - MaybeScheduleTopHostsHintsFetch(); + MaybeScheduleActiveTabsHintsFetch(); MaybeRunUpdateClosure(std::move(update_closure)); } @@ -619,56 +617,81 @@ clock_ = clock; } -void OptimizationGuideHintsManager::MaybeScheduleTopHostsHintsFetch() { - if (!top_host_provider_ || - !optimization_guide::IsUserPermittedToFetchFromRemoteOptimizationGuide( +void OptimizationGuideHintsManager::MaybeScheduleActiveTabsHintsFetch() { + if (!optimization_guide::IsUserPermittedToFetchFromRemoteOptimizationGuide( profile_->IsOffTheRecord(), pref_service_)) { return; } - if (!optimization_guide::features::ShouldBatchUpdateHintsForTopHosts()) - return; - if (optimization_guide::switches::ShouldOverrideFetchHintsTimer()) { SetLastHintsFetchAttemptTime(clock_->Now()); - FetchTopHostsHints(); - } else if (!top_hosts_hints_fetch_timer_.IsRunning()) { + FetchHintsForActiveTabs(); + } else if (!active_tabs_hints_fetch_timer_.IsRunning()) { // Only Schedule this is the time is not already running. - ScheduleTopHostsHintsFetch(); + ScheduleActiveTabsHintsFetch(); } } -void OptimizationGuideHintsManager::ScheduleTopHostsHintsFetch() { - DCHECK(!top_hosts_hints_fetch_timer_.IsRunning()); +void OptimizationGuideHintsManager::ScheduleActiveTabsHintsFetch() { + DCHECK(!active_tabs_hints_fetch_timer_.IsRunning()); - const base::TimeDelta time_until_update_time = - hint_cache_->GetFetchedHintsUpdateTime() - clock_->Now(); - base::TimeDelta fetcher_delay; - if (time_until_update_time <= base::TimeDelta()) { + const base::TimeDelta active_tabs_refresh_duration = + optimization_guide::features::GetActiveTabsFetchRefreshDuration(); + const base::TimeDelta time_since_last_fetch = + clock_->Now() - GetLastHintsFetchAttemptTime(); + if (time_since_last_fetch >= active_tabs_refresh_duration) { // Fetched hints in the store should be updated and an attempt has not - // been made in last |kUpdateFetchedHintsDelay|. + // been made in last + // |optimization_guide::features::GetActiveTabsFetchRefreshDuration()|. SetLastHintsFetchAttemptTime(clock_->Now()); - top_hosts_hints_fetch_timer_.Start( + active_tabs_hints_fetch_timer_.Start( FROM_HERE, RandomFetchDelay(), this, - &OptimizationGuideHintsManager::FetchTopHostsHints); + &OptimizationGuideHintsManager::FetchHintsForActiveTabs); } else { // If the fetched hints in the store are still up-to-date, set a timer // for when the hints need to be updated. - fetcher_delay = time_until_update_time; - top_hosts_hints_fetch_timer_.Start( + base::TimeDelta fetcher_delay = + active_tabs_refresh_duration - time_since_last_fetch; + active_tabs_hints_fetch_timer_.Start( FROM_HERE, fetcher_delay, this, - &OptimizationGuideHintsManager::ScheduleTopHostsHintsFetch); + &OptimizationGuideHintsManager::ScheduleActiveTabsHintsFetch); } } -void OptimizationGuideHintsManager::FetchTopHostsHints() { - DCHECK(top_host_provider_); +const std::vector<GURL> +OptimizationGuideHintsManager::GetActiveTabURLsToRefresh() { + if (!tab_url_provider_) + return {}; + + std::vector<GURL> active_tab_urls = tab_url_provider_->GetUrlsOfActiveTabs( + optimization_guide::features::GetActiveTabsStalenessTolerance()); + + std::set<GURL> urls_to_refresh; + for (const auto& url : active_tab_urls) { + if (!hint_cache_->HasURLKeyedEntryForURL(url)) + urls_to_refresh.insert(url); + } + return std::vector<GURL>(urls_to_refresh.begin(), urls_to_refresh.end()); +} + +void OptimizationGuideHintsManager::FetchHintsForActiveTabs() { + active_tabs_hints_fetch_timer_.Stop(); + active_tabs_hints_fetch_timer_.Start( + FROM_HERE, + optimization_guide::features::GetActiveTabsFetchRefreshDuration(), this, + &OptimizationGuideHintsManager::ScheduleActiveTabsHintsFetch); if (!HasOptimizationTypeToFetchFor()) return; - std::vector<std::string> top_hosts = top_host_provider_->GetTopHosts(); - if (top_hosts.empty()) + std::vector<std::string> top_hosts; + if (top_host_provider_) + top_hosts = top_host_provider_->GetTopHosts(); + + const std::vector<GURL> active_tab_urls_to_refresh = + GetActiveTabURLsToRefresh(); + + if (top_hosts.empty() && active_tab_urls_to_refresh.empty()) return; if (!batch_update_hints_fetcher_) { @@ -676,28 +699,47 @@ batch_update_hints_fetcher_ = hints_fetcher_factory_->BuildInstance(); } + // Add hosts of active tabs to list of hosts to fetch for. Since we are mainly + // fetching for updated information on tabs, add those to the front of the + // list. + base::flat_set<std::string> top_hosts_set = + base::flat_set<std::string>(top_hosts.begin(), top_hosts.end()); + for (const auto& url : active_tab_urls_to_refresh) { + if (!url.has_host() || + top_hosts_set.find(url.host()) == top_hosts_set.end()) { + continue; + } + if (!hint_cache_->HasHint(url.host())) { + top_hosts_set.insert(url.host()); + top_hosts.insert(top_hosts.begin(), url.host()); + } + } + batch_update_hints_fetcher_->FetchOptimizationGuideServiceHints( - top_hosts, std::vector<GURL>{}, registered_optimization_types_, + top_hosts, active_tab_urls_to_refresh, registered_optimization_types_, optimization_guide::proto::CONTEXT_BATCH_UPDATE, base::BindOnce( - &OptimizationGuideHintsManager::OnTopHostsHintsFetched, - ui_weak_ptr_factory_.GetWeakPtr(), - base::flat_set<std::string>(top_hosts.begin(), top_hosts.end()))); + &OptimizationGuideHintsManager::OnHintsForActiveTabsFetched, + ui_weak_ptr_factory_.GetWeakPtr(), top_hosts_set, + base::flat_set<GURL>(active_tab_urls_to_refresh.begin(), + active_tab_urls_to_refresh.end()))); } -void OptimizationGuideHintsManager::OnTopHostsHintsFetched( +void OptimizationGuideHintsManager::OnHintsForActiveTabsFetched( const base::flat_set<std::string>& hosts_fetched, + const base::flat_set<GURL>& urls_fetched, base::Optional<std::unique_ptr<optimization_guide::proto::GetHintsResponse>> get_hints_response) { if (!get_hints_response) return; hint_cache_->UpdateFetchedHints( - std::move(*get_hints_response), clock_->Now() + kUpdateFetchedHintsDelay, - hosts_fetched, - /*urls_fetched=*/{}, + std::move(*get_hints_response), + clock_->Now() + + optimization_guide::features::GetActiveTabsFetchRefreshDuration(), + hosts_fetched, urls_fetched, base::BindOnce( - &OptimizationGuideHintsManager::OnFetchedTopHostsHintsStored, + &OptimizationGuideHintsManager::OnFetchedActiveTabsHintsStored, ui_weak_ptr_factory_.GetWeakPtr())); } @@ -717,7 +759,9 @@ } hint_cache_->UpdateFetchedHints( - std::move(*get_hints_response), clock_->Now() + kUpdateFetchedHintsDelay, + std::move(*get_hints_response), + clock_->Now() + + optimization_guide::features::GetActiveTabsFetchRefreshDuration(), page_navigation_hosts_requested, page_navigation_urls_requested, base::BindOnce( &OptimizationGuideHintsManager::OnFetchedPageNavigationHintsStored, @@ -725,7 +769,7 @@ navigation_url, page_navigation_hosts_requested)); } -void OptimizationGuideHintsManager::OnFetchedTopHostsHintsStored() { +void OptimizationGuideHintsManager::OnFetchedActiveTabsHintsStored() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); LOCAL_HISTOGRAM_BOOLEAN("OptimizationGuide.FetchedHints.Stored", true); @@ -738,11 +782,6 @@ } hint_cache_->PurgeExpiredFetchedHints(); - - top_hosts_hints_fetch_timer_.Stop(); - top_hosts_hints_fetch_timer_.Start( - FROM_HERE, hint_cache_->GetFetchedHintsUpdateTime() - clock_->Now(), this, - &OptimizationGuideHintsManager::ScheduleTopHostsHintsFetch); } void OptimizationGuideHintsManager::OnFetchedPageNavigationHintsStored(
diff --git a/chrome/browser/optimization_guide/optimization_guide_hints_manager.h b/chrome/browser/optimization_guide/optimization_guide_hints_manager.h index 332e92a..e9f40c4 100644 --- a/chrome/browser/optimization_guide/optimization_guide_hints_manager.h +++ b/chrome/browser/optimization_guide/optimization_guide_hints_manager.h
@@ -48,6 +48,7 @@ enum class OptimizationTargetDecision; enum class OptimizationTypeDecision; class StoreUpdateData; +class TabUrlProvider; class TopHostProvider; } // namespace optimization_guide @@ -65,6 +66,7 @@ PrefService* pref_service, optimization_guide::OptimizationGuideStore* hint_store, optimization_guide::TopHostProvider* top_host_provider, + optimization_guide::TabUrlProvider* tab_url_provider, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory); ~OptimizationGuideHintsManager() override; @@ -251,24 +253,29 @@ void OnComponentHintsUpdated(base::OnceClosure update_closure, bool hints_updated); - // Method to decide whether to fetch new hints for user's top sites and - // proceeds to schedule the fetch. - void MaybeScheduleTopHostsHintsFetch(); + // Returns the URLs that are currently in the active tab model that do not + // have a hint available in |hint_cache_|. + const std::vector<GURL> GetActiveTabURLsToRefresh(); - // Schedules |hints_fetch_timer_| to fire based on: - // 1. The update time for the fetched hints in the store and - // 2. The last time a fetch attempt was made. - void ScheduleTopHostsHintsFetch(); + // Method to decide whether to fetch new hints for tab URLs and proceeds to + // schedule the fetch if so. + void MaybeScheduleActiveTabsHintsFetch(); + + // Schedules |active_tabs_hints_fetch_timer_| to fire based on the last time a + // fetch attempt was made. + void ScheduleActiveTabsHintsFetch(); // Called to make a request to fetch hints from the remote Optimization Guide - // Service. Used to fetch hints for origins frequently visited by the user. - void FetchTopHostsHints(); + // Service. Used to fetch hints for origins frequently visited by the user and + // URLs open in the active tab model. + void FetchHintsForActiveTabs(); - // Called when the hints for the top hosts have been fetched from the remote + // Called when the hints for active tabs have been fetched from the remote // Optimization Guide Service and are ready for parsing. This is used when // fetching hints in batch mode. - void OnTopHostsHintsFetched( + void OnHintsForActiveTabsFetched( const base::flat_set<std::string>& hosts_fetched, + const base::flat_set<GURL>& urls_fetched, base::Optional< std::unique_ptr<optimization_guide::proto::GetHintsResponse>> get_hints_response); @@ -291,7 +298,7 @@ // Called when the fetched hints have been stored in |hint_cache| and are // ready to be used. This is used when hints were fetched in batch mode. - void OnFetchedTopHostsHintsStored(); + void OnFetchedActiveTabsHintsStored(); // Called when the fetched hints have been stored in |hint_cache| and are // ready to be used. This is used when hints were fetched in real-time. @@ -456,9 +463,12 @@ // The top host provider that can be queried. Not owned. optimization_guide::TopHostProvider* top_host_provider_ = nullptr; + // The tab URL provider that can be queried. Not owned. + optimization_guide::TabUrlProvider* tab_url_provider_ = nullptr; + // The timer used to schedule fetching hints from the remote Optimization // Guide Service. - base::OneShotTimer top_hosts_hints_fetch_timer_; + base::OneShotTimer active_tabs_hints_fetch_timer_; // The clock used to schedule fetching from the remote Optimization Guide // Service.
diff --git a/chrome/browser/optimization_guide/optimization_guide_hints_manager_unittest.cc b/chrome/browser/optimization_guide/optimization_guide_hints_manager_unittest.cc index 5247e4c..754c0f7e 100644 --- a/chrome/browser/optimization_guide/optimization_guide_hints_manager_unittest.cc +++ b/chrome/browser/optimization_guide/optimization_guide_hints_manager_unittest.cc
@@ -15,6 +15,7 @@ #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "chrome/browser/optimization_guide/optimization_guide_navigation_data.h" +#include "chrome/browser/optimization_guide/optimization_guide_tab_url_provider.h" #include "chrome/browser/optimization_guide/optimization_guide_web_contents_observer.h" #include "chrome/test/base/testing_profile.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h" @@ -48,10 +49,8 @@ namespace { -// Retry delay is 16 minutes to allow for kFetchRetryDelaySecs + -// kFetchRandomMaxDelaySecs to pass. -constexpr int kTestFetchRetryDelaySecs = 60 * 16; -constexpr int kUpdateFetchHintsTimeSecs = 24 * 60 * 60; // 24 hours. +// Allows for default hour to pass + random delay between 30 and 60 seconds. +constexpr int kUpdateFetchHintsTimeSecs = 61 * 60; // 1 hours and 1 minutes. const int kDefaultHostBloomFilterNumHashFunctions = 7; const int kDefaultHostBloomFilterNumBits = 511; @@ -133,7 +132,7 @@ std::vector<std::string> GetTopHosts() override { num_top_hosts_called_++; - return top_hosts_; + return top_hosts_; } int get_num_top_hosts_called() const { return num_top_hosts_called_; } @@ -143,6 +142,24 @@ int num_top_hosts_called_ = 0; }; +// A mock class implementation of TabUrlProvider. +class FakeTabUrlProvider : public optimization_guide::TabUrlProvider { + public: + const std::vector<GURL> GetUrlsOfActiveTabs( + const base::TimeDelta& duration_since_last_shown) override { + num_urls_called_++; + return urls_; + } + + void SetUrls(const std::vector<GURL>& urls) { urls_ = urls; } + + int get_num_urls_called() const { return num_urls_called_; } + + private: + std::vector<GURL> urls_; + int num_urls_called_ = 0; +}; + enum class HintsFetcherEndState { kFetchFailed = 0, kFetchSuccessWithHostHints = 1, @@ -282,9 +299,11 @@ db_provider_.get(), temp_dir(), task_environment_.GetMainThreadTaskRunner()); + tab_url_provider_ = std::make_unique<FakeTabUrlProvider>(); + hints_manager_ = std::make_unique<OptimizationGuideHintsManager>( &testing_profile_, pref_service_.get(), hint_store_.get(), - top_host_provider, url_loader_factory_); + top_host_provider, tab_url_provider_.get(), url_loader_factory_); hints_manager_->SetClockForTesting(task_environment_.GetMockClock()); // Run until hint cache is initialized and the OptimizationGuideHintsManager @@ -295,6 +314,7 @@ void ResetHintsManager() { hints_manager_->Shutdown(); hints_manager_.reset(); + tab_url_provider_.reset(); hint_store_.reset(); pref_service_.reset(); RunUntilIdle(); @@ -399,6 +419,10 @@ TestingPrefServiceSimple* pref_service() const { return pref_service_.get(); } + FakeTabUrlProvider* tab_url_provider() const { + return tab_url_provider_.get(); + } + void RunUntilIdle() { task_environment_.RunUntilIdle(); base::RunLoop().RunUntilIdle(); @@ -421,6 +445,7 @@ TestingProfile testing_profile_; std::unique_ptr<content::TestWebContentsFactory> web_contents_factory_; std::unique_ptr<optimization_guide::OptimizationGuideStore> hint_store_; + std::unique_ptr<FakeTabUrlProvider> tab_url_provider_; std::unique_ptr<OptimizationGuideHintsManager> hints_manager_; std::unique_ptr<TestingPrefServiceSimple> pref_service_; scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; @@ -1869,7 +1894,7 @@ InitializeWithDefaultConfig("1.0.0"); // Force timer to expire and schedule a hints fetch. - MoveClockForwardBy(base::TimeDelta::FromSeconds(kTestFetchRetryDelaySecs)); + MoveClockForwardBy(base::TimeDelta::FromSeconds(kUpdateFetchHintsTimeSecs)); EXPECT_EQ(0, top_host_provider->get_num_top_hosts_called()); // Hints fetcher should not even be created. EXPECT_FALSE(batch_update_hints_fetcher()); @@ -1963,25 +1988,7 @@ InitializeWithDefaultConfig("1.0.0"); // Force timer to expire and schedule a hints fetch. - MoveClockForwardBy(base::TimeDelta::FromSeconds(kTestFetchRetryDelaySecs)); - // Hints fetcher should not even be created. - EXPECT_FALSE(batch_update_hints_fetcher()); -} - -TEST_F(OptimizationGuideHintsManagerFetchingTest, - HintsFetchNotAllowedIfFeatureIsEnabledButTopHostProviderIsNotProvided) { - base::CommandLine::ForCurrentProcess()->AppendSwitch( - optimization_guide::switches::kDisableCheckingUserPermissionsForTesting); - CreateHintsManager(/*top_host_provider=*/nullptr); - hints_manager()->RegisterOptimizationTypes( - {optimization_guide::proto::DEFER_ALL_SCRIPT}); - hints_manager()->SetHintsFetcherFactoryForTesting( - BuildTestHintsFetcherFactory( - {HintsFetcherEndState::kFetchSuccessWithHostHints})); - InitializeWithDefaultConfig("1.0.0"); - - // Force timer to expire and schedule a hints fetch. - MoveClockForwardBy(base::TimeDelta::FromSeconds(kTestFetchRetryDelaySecs)); + MoveClockForwardBy(base::TimeDelta::FromSeconds(kUpdateFetchHintsTimeSecs)); // Hints fetcher should not even be created. EXPECT_FALSE(batch_update_hints_fetcher()); } @@ -2002,7 +2009,7 @@ InitializeWithDefaultConfig("1.0.0"); // Force timer to expire and schedule a hints fetch but the fetch is not made. - MoveClockForwardBy(base::TimeDelta::FromSeconds(kTestFetchRetryDelaySecs)); + MoveClockForwardBy(base::TimeDelta::FromSeconds(kUpdateFetchHintsTimeSecs)); EXPECT_EQ(0, top_host_provider->get_num_top_hosts_called()); // Hints fetcher should not be created. EXPECT_FALSE(batch_update_hints_fetcher()); @@ -2034,15 +2041,15 @@ BuildTestHintsFetcherFactory( {HintsFetcherEndState::kFetchSuccessWithHostHints})); - // Force timer to expire and schedule a hints fetch but the fetch is not made. - MoveClockForwardBy(base::TimeDelta::FromSeconds(kTestFetchRetryDelaySecs)); + // Force timer to expire after random delay and schedule a hints fetch. + MoveClockForwardBy(base::TimeDelta::FromSeconds(60 * 2)); EXPECT_EQ(0, top_host_provider->get_num_top_hosts_called()); // Hints fetcher should not be created. EXPECT_FALSE(batch_update_hints_fetcher()); } TEST_F(OptimizationGuideHintsManagerFetchingTest, - HintsFetcherEnabledNoHostsToFetch) { + HintsFetcherEnabledNoHostsOrUrlsToFetch) { base::CommandLine::ForCurrentProcess()->AppendSwitch( optimization_guide::switches::kDisableCheckingUserPermissionsForTesting); std::unique_ptr<FakeTopHostProvider> top_host_provider = @@ -2056,43 +2063,54 @@ {HintsFetcherEndState::kFetchSuccessWithHostHints})); InitializeWithDefaultConfig("1.0.0"); - // Force timer to expire and schedule a hints fetch. - MoveClockForwardBy(base::TimeDelta::FromSeconds(kTestFetchRetryDelaySecs)); + // Force timer to expire after random delay and schedule a hints fetch. + MoveClockForwardBy(base::TimeDelta::FromSeconds(60 * 2)); EXPECT_EQ(1, top_host_provider->get_num_top_hosts_called()); + EXPECT_EQ(1, tab_url_provider()->get_num_urls_called()); // Hints fetcher should not be even created. EXPECT_FALSE(batch_update_hints_fetcher()); + + // Move it forward again to make sure timer is scheduled. + MoveClockForwardBy(base::TimeDelta::FromSeconds(kUpdateFetchHintsTimeSecs)); + EXPECT_EQ(2, top_host_provider->get_num_top_hosts_called()); + EXPECT_EQ(2, tab_url_provider()->get_num_urls_called()); + // Still no hosts or URLs, so hints fetcher should still not be even created. + EXPECT_FALSE(batch_update_hints_fetcher()); } TEST_F(OptimizationGuideHintsManagerFetchingTest, - HintsFetcherEnabledWithHostsNoHintsInResponse) { + HintsFetcherEnabledNoHostsButHasUrlsToFetch) { base::CommandLine::ForCurrentProcess()->AppendSwitch( optimization_guide::switches::kDisableCheckingUserPermissionsForTesting); std::unique_ptr<FakeTopHostProvider> top_host_provider = - std::make_unique<FakeTopHostProvider>( - std::vector<std::string>({"example1.com", "example2.com"})); + std::make_unique<FakeTopHostProvider>(std::vector<std::string>({})); CreateHintsManager(top_host_provider.get()); + hints_manager()->RegisterOptimizationTypes( {optimization_guide::proto::DEFER_ALL_SCRIPT}); hints_manager()->SetHintsFetcherFactoryForTesting( BuildTestHintsFetcherFactory( - {HintsFetcherEndState::kFetchSuccessWithNoHints})); + {HintsFetcherEndState::kFetchSuccessWithHostHints})); InitializeWithDefaultConfig("1.0.0"); - // Force timer to expire and schedule a hints fetch. - MoveClockForwardBy(base::TimeDelta::FromSeconds(kTestFetchRetryDelaySecs)); + tab_url_provider()->SetUrls({GURL("https://a.com"), GURL("https://b.com")}); + + // Force timer to expire after random delay and schedule a hints fetch that + // succeeds. + MoveClockForwardBy(base::TimeDelta::FromSeconds(60 * 2)); EXPECT_EQ(1, top_host_provider->get_num_top_hosts_called()); + EXPECT_EQ(1, tab_url_provider()->get_num_urls_called()); EXPECT_EQ(1, batch_update_hints_fetcher()->num_fetches_requested()); - // Check that hints should not be fetched again after the delay for a hints - // fetch attempt with no hints. - MoveClockForwardBy(base::TimeDelta::FromSeconds(kTestFetchRetryDelaySecs)); - // This should be called exactly once, confirming that hints are not fetched - // again after |kTestFetchRetryDelaySecs|. - EXPECT_EQ(1, top_host_provider->get_num_top_hosts_called()); + // Move it forward again to make sure timer is scheduled. + MoveClockForwardBy(base::TimeDelta::FromSeconds(kUpdateFetchHintsTimeSecs)); + EXPECT_EQ(2, top_host_provider->get_num_top_hosts_called()); + EXPECT_EQ(2, tab_url_provider()->get_num_urls_called()); + // Urls didn't change and we have all URLs cached in store. EXPECT_EQ(1, batch_update_hints_fetcher()->num_fetches_requested()); } -TEST_F(OptimizationGuideHintsManagerFetchingTest, HintsFetcherTimerRetryDelay) { +TEST_F(OptimizationGuideHintsManagerFetchingTest, HintsFetcherTimerFetch) { base::CommandLine::ForCurrentProcess()->AppendSwitch( optimization_guide::switches::kDisableCheckingUserPermissionsForTesting); std::unique_ptr<FakeTopHostProvider> top_host_provider = @@ -2103,46 +2121,16 @@ hints_manager()->RegisterOptimizationTypes( {optimization_guide::proto::DEFER_ALL_SCRIPT}); hints_manager()->SetHintsFetcherFactoryForTesting( - BuildTestHintsFetcherFactory({HintsFetcherEndState::kFetchFailed})); - InitializeWithDefaultConfig("1.0.0"); - - // Force timer to expire and schedule a hints fetch - first time. - MoveClockForwardBy(base::TimeDelta::FromSeconds(kTestFetchRetryDelaySecs)); - EXPECT_EQ(1, top_host_provider->get_num_top_hosts_called()); - EXPECT_EQ(1, batch_update_hints_fetcher()->num_fetches_requested()); - - // Force speculative timer to expire after fetch fails. - MoveClockForwardBy(base::TimeDelta::FromSeconds(kTestFetchRetryDelaySecs)); - EXPECT_EQ(1, top_host_provider->get_num_top_hosts_called()); - EXPECT_EQ(1, batch_update_hints_fetcher()->num_fetches_requested()); -} - -TEST_F(OptimizationGuideHintsManagerFetchingTest, - HintsFetcherTimerFetchSucceeds) { - base::CommandLine::ForCurrentProcess()->AppendSwitch( - optimization_guide::switches::kDisableCheckingUserPermissionsForTesting); - std::unique_ptr<FakeTopHostProvider> top_host_provider = - std::make_unique<FakeTopHostProvider>( - std::vector<std::string>({"example1.com", "example2.com"})); - - // Force hints fetch scheduling. - CreateHintsManager(top_host_provider.get()); - hints_manager()->RegisterOptimizationTypes( - {optimization_guide::proto::DEFER_ALL_SCRIPT}); - hints_manager()->SetHintsFetcherFactoryForTesting( BuildTestHintsFetcherFactory( {HintsFetcherEndState::kFetchSuccessWithHostHints})); InitializeWithDefaultConfig("1.0.0"); - // Force timer to expire and schedule a hints fetch that succeeds. - MoveClockForwardBy(base::TimeDelta::FromSeconds(kTestFetchRetryDelaySecs)); + // Force timer to expire after random delay and schedule a hints fetch that + // succeeds. + MoveClockForwardBy(base::TimeDelta::FromSeconds(60 * 2)); EXPECT_EQ(1, batch_update_hints_fetcher()->num_fetches_requested()); - // TODO(mcrouse): Make sure timer is triggered by metadata entry, - // |hint_cache| control needed. - MoveClockForwardBy(base::TimeDelta::FromSeconds(kTestFetchRetryDelaySecs)); - EXPECT_EQ(1, batch_update_hints_fetcher()->num_fetches_requested()); - + // Move it forward again to make sure timer is scheduled. MoveClockForwardBy(base::TimeDelta::FromSeconds(kUpdateFetchHintsTimeSecs)); EXPECT_EQ(2, batch_update_hints_fetcher()->num_fetches_requested()); } @@ -3690,39 +3678,3 @@ EXPECT_EQ(optimization_guide::OptimizationTypeDecision::kNoHintAvailable, optimization_type_decision); } - -class OptimizationGuideHintsManagerFetchingNoBatchUpdateTest - : public OptimizationGuideHintsManagerTest { - public: - OptimizationGuideHintsManagerFetchingNoBatchUpdateTest() { - scoped_list_.InitAndEnableFeatureWithParameters( - optimization_guide::features::kRemoteOptimizationGuideFetching, - {{"batch_update_hints_for_top_hosts", "false"}}); - } - - private: - base::test::ScopedFeatureList scoped_list_; -}; - -TEST_F(OptimizationGuideHintsManagerFetchingNoBatchUpdateTest, - BatchUpdateHintsFetchNotScheduledIfNotAllowed) { - base::CommandLine::ForCurrentProcess()->AppendSwitch( - optimization_guide::switches::kDisableCheckingUserPermissionsForTesting); - std::unique_ptr<FakeTopHostProvider> top_host_provider = - std::make_unique<FakeTopHostProvider>( - std::vector<std::string>({"example1.com", "example2.com"})); - - // Force hints fetch scheduling. - CreateHintsManager(top_host_provider.get()); - hints_manager()->RegisterOptimizationTypes( - {optimization_guide::proto::DEFER_ALL_SCRIPT}); - hints_manager()->SetHintsFetcherFactoryForTesting( - BuildTestHintsFetcherFactory( - {HintsFetcherEndState::kFetchSuccessWithHostHints})); - InitializeWithDefaultConfig("1.0.0"); - - // Force timer to expire and schedule a hints fetch. - MoveClockForwardBy(base::TimeDelta::FromSeconds(kTestFetchRetryDelaySecs)); - // Hints fetcher should not even be created. - EXPECT_FALSE(batch_update_hints_fetcher()); -}
diff --git a/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc b/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc index ee74ba8..ba06325 100644 --- a/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc +++ b/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc
@@ -12,6 +12,7 @@ #include "base/optional.h" #include "base/sequenced_task_runner.h" #include "base/task/task_traits.h" +#include "build/build_config.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/metrics/chrome_metrics_service_accessor.h" #include "chrome/browser/optimization_guide/optimization_guide_hints_manager.h" @@ -27,6 +28,7 @@ #include "components/optimization_guide/core/optimization_guide_features.h" #include "components/optimization_guide/core/optimization_guide_store.h" #include "components/optimization_guide/core/optimization_guide_util.h" +#include "components/optimization_guide/core/tab_url_provider.h" #include "components/optimization_guide/core/top_host_provider.h" #include "components/optimization_guide/proto/models.pb.h" #include "content/public/browser/browser_context.h" @@ -35,6 +37,12 @@ #include "content/public/browser/storage_partition.h" #include "url/gurl.h" +#if defined(OS_ANDROID) +#include "chrome/browser/optimization_guide/android/optimization_guide_tab_url_provider_android.h" +#else +#include "chrome/browser/optimization_guide/optimization_guide_tab_url_provider.h" +#endif + namespace { // Returns the top host provider to be used with this keyed service. Can return @@ -147,6 +155,15 @@ "SyntheticOptimizationGuideRemoteFetching", optimization_guide_fetching_enabled ? "Enabled" : "Disabled"); +#if defined(OS_ANDROID) + tab_url_provider_ = std::make_unique< + optimization_guide::android::OptimizationGuideTabUrlProviderAndroid>( + profile); +#else + tab_url_provider_ = + std::make_unique<OptimizationGuideTabUrlProvider>(profile); +#endif + hint_store_ = optimization_guide::features::ShouldPersistHintsToDisk() ? std::make_unique<optimization_guide::OptimizationGuideStore>( @@ -172,7 +189,7 @@ hints_manager_ = std::make_unique<OptimizationGuideHintsManager>( profile, profile->GetPrefs(), hint_store, top_host_provider_.get(), - url_loader_factory); + tab_url_provider_.get(), url_loader_factory); prediction_manager_ = std::make_unique<optimization_guide::PredictionManager>( prediction_model_and_features_store, top_host_provider_.get(), url_loader_factory, profile->GetPrefs(), profile);
diff --git a/chrome/browser/optimization_guide/optimization_guide_keyed_service.h b/chrome/browser/optimization_guide/optimization_guide_keyed_service.h index 9fb5ad0c..1f10045 100644 --- a/chrome/browser/optimization_guide/optimization_guide_keyed_service.h +++ b/chrome/browser/optimization_guide/optimization_guide_keyed_service.h
@@ -33,6 +33,7 @@ class PredictionManager; class PredictionManagerBrowserTestBase; class PredictionModelDownloadClient; +class TabUrlProvider; class TopHostProvider; } // namespace optimization_guide @@ -169,6 +170,10 @@ // behavior. std::unique_ptr<optimization_guide::TopHostProvider> top_host_provider_; + // The tab URL provider to use for fetching information for the user's active + // tabs. Will be null if the user is off the record. + std::unique_ptr<optimization_guide::TabUrlProvider> tab_url_provider_; + DISALLOW_COPY_AND_ASSIGN(OptimizationGuideKeyedService); };
diff --git a/chrome/browser/optimization_guide/optimization_guide_tab_url_provider.cc b/chrome/browser/optimization_guide/optimization_guide_tab_url_provider.cc new file mode 100644 index 0000000..9bf5d46 --- /dev/null +++ b/chrome/browser/optimization_guide/optimization_guide_tab_url_provider.cc
@@ -0,0 +1,85 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/optimization_guide/optimization_guide_tab_url_provider.h" + +#include "build/build_config.h" +#include "chrome/browser/profiles/profile.h" +#include "content/public/browser/web_contents.h" +#include "url/gurl.h" + +#if !defined(OS_ANDROID) +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" +#endif + +namespace { + +// Returns whether the web contents has been shown in the last 90 days. +bool IsWebContentsCandidateForRefresh( + content::WebContents* web_contents, + const base::TimeDelta& duration_since_last_shown) { + return web_contents && + (base::TimeTicks::Now() - web_contents->GetLastActiveTime()) < + duration_since_last_shown; +} + +} // namespace + +OptimizationGuideTabUrlProvider::OptimizationGuideTabUrlProvider( + Profile* profile) + : profile_(profile) {} +OptimizationGuideTabUrlProvider::~OptimizationGuideTabUrlProvider() = default; + +const std::vector<GURL> OptimizationGuideTabUrlProvider::GetUrlsOfActiveTabs( + const base::TimeDelta& duration_since_last_shown) { + const std::vector<content::WebContents*> web_contents_list = + GetAllWebContentsForProfile(profile_); + std::vector<std::pair<GURL, base::TimeTicks>> urls_and_active_time; + urls_and_active_time.reserve(web_contents_list.size()); + for (content::WebContents* web_contents : web_contents_list) { + if (IsWebContentsCandidateForRefresh(web_contents, + duration_since_last_shown)) { + urls_and_active_time.emplace_back( + std::make_pair(web_contents->GetLastCommittedURL(), + web_contents->GetLastActiveTime())); + } + } + std::sort(urls_and_active_time.begin(), urls_and_active_time.end(), + [](const std::pair<GURL, base::TimeTicks>& a, + const std::pair<GURL, base::TimeTicks>& b) { + return a.second > b.second; + }); + + std::vector<GURL> urls; + urls.reserve(urls_and_active_time.size()); + for (const auto& url_and_active_time : urls_and_active_time) { + urls.emplace_back(url_and_active_time.first); + } + return urls; +} + +const std::vector<content::WebContents*> +OptimizationGuideTabUrlProvider::GetAllWebContentsForProfile(Profile* profile) { +#if defined(OS_ANDROID) + NOTREACHED(); + return {}; +#else + std::vector<content::WebContents*> web_contents_list; + for (Browser* browser : *BrowserList::GetInstance()) { + if (!browser || browser->profile() != profile) + continue; + + TabStripModel* tab_strip_model = browser->tab_strip_model(); + int tab_count = tab_strip_model->count(); + for (int i = 0; i < tab_count; i++) { + content::WebContents* web_contents = tab_strip_model->GetWebContentsAt(i); + if (web_contents) + web_contents_list.push_back(web_contents); + } + } + return web_contents_list; +#endif +}
diff --git a/chrome/browser/optimization_guide/optimization_guide_tab_url_provider.h b/chrome/browser/optimization_guide/optimization_guide_tab_url_provider.h new file mode 100644 index 0000000..4fe322b --- /dev/null +++ b/chrome/browser/optimization_guide/optimization_guide_tab_url_provider.h
@@ -0,0 +1,41 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_OPTIMIZATION_GUIDE_OPTIMIZATION_GUIDE_TAB_URL_PROVIDER_H_ +#define CHROME_BROWSER_OPTIMIZATION_GUIDE_OPTIMIZATION_GUIDE_TAB_URL_PROVIDER_H_ + +#include "components/optimization_guide/core/tab_url_provider.h" + +class Profile; + +namespace content { +class WebContents; +} // namespace content + +// An implementation of optimization_guide::TabUrlProvider that provides tab +// URLs that are currently shown for the profile. +class OptimizationGuideTabUrlProvider + : public optimization_guide::TabUrlProvider { + public: + explicit OptimizationGuideTabUrlProvider(Profile* profile); + ~OptimizationGuideTabUrlProvider() override; + + OptimizationGuideTabUrlProvider( + const OptimizationGuideTabUrlProvider& other) = delete; + OptimizationGuideTabUrlProvider& operator=( + const OptimizationGuideTabUrlProvider&) = delete; + + // optimization_guide::TabUrlProvider: + const std::vector<GURL> GetUrlsOfActiveTabs( + const base::TimeDelta& duration_since_last_shown) override; + + private: + // Returns all web contents shown across all browser windows for |profile|. + virtual const std::vector<content::WebContents*> GetAllWebContentsForProfile( + Profile* profile); + + Profile* profile_; +}; + +#endif // CHROME_BROWSER_OPTIMIZATION_GUIDE_OPTIMIZATION_GUIDE_TAB_URL_PROVIDER_H_
diff --git a/chrome/browser/optimization_guide/optimization_guide_tab_url_provider_unittest.cc b/chrome/browser/optimization_guide/optimization_guide_tab_url_provider_unittest.cc new file mode 100644 index 0000000..dff940f --- /dev/null +++ b/chrome/browser/optimization_guide/optimization_guide_tab_url_provider_unittest.cc
@@ -0,0 +1,62 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/optimization_guide/optimization_guide_tab_url_provider.h" + +#include "chrome/test/base/browser_with_test_window_test.h" +#include "testing/gmock/include/gmock/gmock.h" + +using testing::ElementsAre; + +class OptimizationGuideTabUrlProviderTest : public BrowserWithTestWindowTest { + public: + OptimizationGuideTabUrlProviderTest() = default; + ~OptimizationGuideTabUrlProviderTest() override = default; + + void SetUp() override { + BrowserWithTestWindowTest::SetUp(); + otr_browser_window_ = CreateBrowserWindow(); + otr_browser_ = + CreateBrowser(profile()->GetPrimaryOTRProfile(), browser()->type(), + /*hosted_app=*/false, otr_browser_window_.get()); + tab_url_provider_ = + std::make_unique<OptimizationGuideTabUrlProvider>(profile()); + } + + void TearDown() override { + // Also destroy |otr_browser_| before the profile. browser()'s destruction + // is handled in BrowserWithTestWindowTest::TearDown(). + otr_browser_->tab_strip_model()->CloseAllTabs(); + otr_browser_.reset(); + BrowserWithTestWindowTest::TearDown(); + } + + Browser* otr_browser() const { return otr_browser_.get(); } + + OptimizationGuideTabUrlProvider* tab_url_provider() const { + return tab_url_provider_.get(); + } + + private: + std::unique_ptr<BrowserWindow> otr_browser_window_; + std::unique_ptr<Browser> otr_browser_; + std::unique_ptr<OptimizationGuideTabUrlProvider> tab_url_provider_; +}; + +TEST_F(OptimizationGuideTabUrlProviderTest, GetUrlsNoOpenTabs) { + std::vector<GURL> urls = + tab_url_provider()->GetUrlsOfActiveTabs(base::TimeDelta::FromDays(90)); + EXPECT_TRUE(urls.empty()); +} + +TEST_F(OptimizationGuideTabUrlProviderTest, GetUrlsFiltersOutIncognitoTabs) { + AddTab(otr_browser(), GURL("https://otrshouldskip.com")); + AddTab(browser(), GURL("https://example.com")); + AddTab(browser(), GURL("https://example2.com")); + + std::vector<GURL> urls = + tab_url_provider()->GetUrlsOfActiveTabs(base::TimeDelta::FromDays(90)); + EXPECT_THAT(urls, ElementsAre(GURL("https://example2.com"), + GURL("https://example.com"))); +}
diff --git a/chrome/browser/optimization_guide/page_text_observer_browsertest.cc b/chrome/browser/optimization_guide/page_text_observer_browsertest.cc index d534efbf..3a55928 100644 --- a/chrome/browser/optimization_guide/page_text_observer_browsertest.cc +++ b/chrome/browser/optimization_guide/page_text_observer_browsertest.cc
@@ -9,6 +9,8 @@ #include "base/bind.h" #include "base/callback.h" #include "base/optional.h" +#include "base/strings/strcat.h" +#include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" @@ -25,9 +27,20 @@ #include "net/test/embedded_test_server/embedded_test_server.h" #include "net/test/embedded_test_server/http_request.h" #include "net/test/embedded_test_server/http_response.h" +#include "testing/gmock/include/gmock/gmock.h" namespace optimization_guide { +namespace { + +FrameTextDumpResult MakeFrameDump(mojom::TextDumpEvent event, + content::GlobalFrameRoutingId rfh_id, + bool amp_frame, + const std::u16string& contents) { + return FrameTextDumpResult::Initialize(event, rfh_id, amp_frame) + .CompleteWithContents(contents); +} + class TestConsumer : public PageTextObserver::Consumer { public: TestConsumer() = default; @@ -36,16 +49,18 @@ void Reset() { was_called_ = false; } void PopulateRequest(uint32_t max_size, - const std::set<mojom::TextDumpEvent>& events) { + const std::set<mojom::TextDumpEvent>& events, + bool request_amp = false) { request_ = std::make_unique<PageTextObserver::ConsumerTextDumpRequest>(); request_->max_size = max_size; request_->events = events; - request_->callback = base::BindRepeating(&TestConsumer::OnGotTextDump, - base::Unretained(this)); + request_->callback = + base::BindOnce(&TestConsumer::OnGotTextDump, base::Unretained(this)); + request_->dump_amp_subframes = request_amp; } void WaitForPageText() { - if (text_) { + if (result_) { return; } @@ -56,7 +71,9 @@ bool was_called() const { return was_called_; } - const base::Optional<std::u16string>& text() const { return text_; } + base::Optional<PageTextDumpResult> result() { + return base::OptionalFromPtr(result_.get()); + } // PageTextObserver::Consumer: std::unique_ptr<PageTextObserver::ConsumerTextDumpRequest> @@ -66,22 +83,22 @@ } private: - void OnGotTextDump(const std::u16string& text) { - text_ = text; + void OnGotTextDump(const PageTextDumpResult& result) { + result_ = std::make_unique<PageTextDumpResult>(result); if (on_page_text_closure_) { std::move(on_page_text_closure_).Run(); } } bool was_called_ = false; - std::unique_ptr<PageTextObserver::ConsumerTextDumpRequest> request_; base::OnceClosure on_page_text_closure_; - - base::Optional<std::u16string> text_; + std::unique_ptr<PageTextDumpResult> result_; }; +} // namespace + // This tests code in // //components/optimization_guide/content/browser/page_text_observer.h, but // this test is in //chrome because the components browsertests do not fully @@ -133,6 +150,21 @@ return resp; } + // This script is onLoad-blocking in the HTML, but is intentionally slow. + // This provides important time between first layout and finish load for + // tests that need it. + if (request.GetURL().path() == "/slow-add-world-text.js") { + std::unique_ptr<net::test_server::DelayedHttpResponse> resp = + std::make_unique<net::test_server::DelayedHttpResponse>( + base::TimeDelta::FromMilliseconds(500)); + resp->set_code(net::HTTP_OK); + resp->set_content_type("application/javascript"); + resp->set_content( + "var p = document.createElement('p'); p.innerHTML = 'world'; " + "document.body.appendChild(p); "); + return resp; + } + if (request.GetURL().path() == "/dynamic.html") { std::unique_ptr<net::test_server::BasicHttpResponse> resp = std::make_unique<net::test_server::BasicHttpResponse>(); @@ -146,7 +178,7 @@ } }; -IN_PROC_BROWSER_TEST_F(PageTextObserverBrowserTest, SimpleCase) { +IN_PROC_BROWSER_TEST_F(PageTextObserverBrowserTest, SimpleCaseNoSubframes) { PageTextObserver::CreateForWebContents(web_contents()); ASSERT_TRUE(observer()); @@ -160,8 +192,14 @@ ASSERT_TRUE(consumer.was_called()); consumer.WaitForPageText(); - ASSERT_TRUE(consumer.text()); - EXPECT_EQ(base::ASCIIToUTF16("hello"), *consumer.text()); + ASSERT_TRUE(consumer.result()); + EXPECT_THAT(consumer.result()->frame_results(), + ::testing::UnorderedElementsAreArray({ + MakeFrameDump( + mojom::TextDumpEvent::kFirstLayout, + web_contents()->GetMainFrame()->GetGlobalFrameRoutingId(), + /*amp_frame=*/false, base::ASCIIToUTF16("hello")), + })); } IN_PROC_BROWSER_TEST_F(PageTextObserverBrowserTest, FirstLayoutAndOnLoad) { @@ -189,14 +227,99 @@ first_layout_consumer.WaitForPageText(); on_load_consumer.WaitForPageText(); - ASSERT_TRUE(first_layout_consumer.text()); - // This check can be a bit flaky on some platforms. Check that "hello" is - // present, since the text captured may already be "hello world". - EXPECT_TRUE(base::Contains(*first_layout_consumer.text(), - base::ASCIIToUTF16("hello"))); + ASSERT_TRUE(first_layout_consumer.result()); + EXPECT_THAT( + first_layout_consumer.result()->frame_results(), + ::testing::UnorderedElementsAreArray({ + MakeFrameDump( + mojom::TextDumpEvent::kFirstLayout, + web_contents()->GetMainFrame()->GetGlobalFrameRoutingId(), + /*amp_frame=*/false, base::ASCIIToUTF16("hello")), + MakeFrameDump( + mojom::TextDumpEvent::kFinishedLoad, + web_contents()->GetMainFrame()->GetGlobalFrameRoutingId(), + /*amp_frame=*/false, base::ASCIIToUTF16("hello\n\nworld")), + })); - ASSERT_TRUE(on_load_consumer.text()); - EXPECT_EQ(base::ASCIIToUTF16("hello\n\nworld"), *on_load_consumer.text()); + EXPECT_EQ(first_layout_consumer.result(), on_load_consumer.result()); +} + +IN_PROC_BROWSER_TEST_F(PageTextObserverBrowserTest, OOPIFAMPSubframe) { + PageTextObserver::CreateForWebContents(web_contents()); + ASSERT_TRUE(observer()); + + TestConsumer consumer; + observer()->AddConsumer(&consumer); + consumer.PopulateRequest( + /*max_size=*/1024, + /*events=*/{mojom::TextDumpEvent::kFirstLayout}, + /*request_amp=*/true); + + GURL url(embedded_test_server()->GetURL("a.com", "/dynamic.html")); + dynamic_response_body_ = base::StringPrintf( + "<html><body>" + "<script type=\"text/javascript\" src=\"/slow-first-layout.js\"></script>" + "<p>mainframe</p>" + "<iframe name=\"amp\" src=\"%s\"></iframe>" + "</body></html>", + embedded_test_server()->GetURL("b.com", "/amp.html").spec().c_str()); + ui_test_utils::NavigateToURL(browser(), url); + ASSERT_TRUE(consumer.was_called()); + + consumer.WaitForPageText(); + + content::GlobalFrameRoutingId amp_frame_id; + for (auto* rfh : web_contents()->GetMainFrame()->GetFramesInSubtree()) { + if (rfh->GetFrameName() == "amp") { + amp_frame_id = rfh->GetGlobalFrameRoutingId(); + break; + } + } + + ASSERT_TRUE(consumer.result()); + EXPECT_THAT( + consumer.result()->frame_results(), + ::testing::UnorderedElementsAreArray({ + MakeFrameDump( + mojom::TextDumpEvent::kFirstLayout, + web_contents()->GetMainFrame()->GetGlobalFrameRoutingId(), + /*amp_frame=*/false, base::ASCIIToUTF16("mainframe")), + MakeFrameDump(mojom::TextDumpEvent::kFinishedLoad, amp_frame_id, + /*amp_frame=*/true, base::ASCIIToUTF16("AMP")), + })); +} + +IN_PROC_BROWSER_TEST_F(PageTextObserverBrowserTest, OOPIFNotAmpSubframe) { + PageTextObserver::CreateForWebContents(web_contents()); + ASSERT_TRUE(observer()); + + TestConsumer consumer; + observer()->AddConsumer(&consumer); + consumer.PopulateRequest( + /*max_size=*/1024, + /*events=*/{mojom::TextDumpEvent::kFirstLayout}, + /*request_amp=*/true); + + GURL url(embedded_test_server()->GetURL("a.com", "/dynamic.html")); + dynamic_response_body_ = base::StringPrintf( + "<html><body>" + "<script type=\"text/javascript\" src=\"/slow-first-layout.js\"></script>" + "<p>mainframe</p>" + "<iframe src=\"%s\"></iframe>" + "</body></html>", + embedded_test_server()->GetURL("b.com", "/hello.html").spec().c_str()); + ui_test_utils::NavigateToURL(browser(), url); + ASSERT_TRUE(consumer.was_called()); + + consumer.WaitForPageText(); + ASSERT_TRUE(consumer.result()); + EXPECT_THAT(consumer.result()->frame_results(), + ::testing::UnorderedElementsAreArray({ + MakeFrameDump( + mojom::TextDumpEvent::kFirstLayout, + web_contents()->GetMainFrame()->GetGlobalFrameRoutingId(), + /*amp_frame=*/false, base::ASCIIToUTF16("mainframe")), + })); } class PageTextObserverSingleProcessBrowserTest @@ -224,17 +347,58 @@ GURL url(embedded_test_server()->GetURL("a.com", "/dynamic.html")); dynamic_response_body_ = base::StringPrintf( "<html><body>" - "<p>foo</p>" + "<script type=\"text/javascript\" src=\"/slow-first-layout.js\"></script>" + "<p>mainframe</p>" "<iframe src=\"%s\"></iframe>" "</body></html>", embedded_test_server()->GetURL("a.com", "/hello.html").spec().c_str()); - ui_test_utils::NavigateToURL(browser(), url); ASSERT_TRUE(consumer.was_called()); consumer.WaitForPageText(); - ASSERT_TRUE(consumer.text()); - EXPECT_EQ(base::ASCIIToUTF16("foo\n\nhello"), *consumer.text()); + ASSERT_TRUE(consumer.result()); + EXPECT_THAT( + consumer.result()->frame_results(), + ::testing::UnorderedElementsAreArray({ + MakeFrameDump( + mojom::TextDumpEvent::kFinishedLoad, + web_contents()->GetMainFrame()->GetGlobalFrameRoutingId(), + /*amp_frame=*/false, base::ASCIIToUTF16("mainframe\n\nhello")), + })); +} + +IN_PROC_BROWSER_TEST_F(PageTextObserverSingleProcessBrowserTest, + SameProcessAMPSubframe) { + PageTextObserver::CreateForWebContents(web_contents()); + ASSERT_TRUE(observer()); + + TestConsumer consumer; + observer()->AddConsumer(&consumer); + consumer.PopulateRequest( + /*max_size=*/1024, + /*events=*/{mojom::TextDumpEvent::kFirstLayout}, + /*request_amp=*/true); + + GURL url(embedded_test_server()->GetURL("a.com", "/dynamic.html")); + dynamic_response_body_ = base::StringPrintf( + "<html><body>" + "<script type=\"text/javascript\" src=\"/slow-first-layout.js\"></script>" + "<p>mainframe</p>" + "<iframe src=\"%s\"></iframe>" + "</body></html>", + embedded_test_server()->GetURL("a.com", "/amp.html").spec().c_str()); + ui_test_utils::NavigateToURL(browser(), url); + ASSERT_TRUE(consumer.was_called()); + + consumer.WaitForPageText(); + ASSERT_TRUE(consumer.result()); + EXPECT_THAT(consumer.result()->frame_results(), + ::testing::UnorderedElementsAreArray({ + MakeFrameDump( + mojom::TextDumpEvent::kFirstLayout, + web_contents()->GetMainFrame()->GetGlobalFrameRoutingId(), + /*amp_frame=*/false, base::ASCIIToUTF16("mainframe")), + })); } } // namespace optimization_guide
diff --git a/chrome/browser/policy/extension_policy_browsertest.cc b/chrome/browser/policy/extension_policy_browsertest.cc index f84930c..cfee4aa9 100644 --- a/chrome/browser/policy/extension_policy_browsertest.cc +++ b/chrome/browser/policy/extension_policy_browsertest.cc
@@ -5,10 +5,12 @@ #include <memory> #include "base/files/file_util.h" +#include "base/files/scoped_temp_dir.h" #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" #include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h" +#include "base/threading/thread_restrictions.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" #include "chrome/browser/background/background_contents_service.h" @@ -17,6 +19,7 @@ #include "chrome/browser/extensions/chrome_extension_test_notification_observer.h" #include "chrome/browser/extensions/component_loader.h" #include "chrome/browser/extensions/crx_installer.h" +#include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/extensions/extension_management_constants.h" #include "chrome/browser/extensions/extension_management_test_util.h" #include "chrome/browser/extensions/extension_service.h" @@ -40,6 +43,7 @@ #include "chrome/common/extensions/extension_test_util.h" #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" #include "chrome/test/base/ui_test_utils.h" +#include "components/policy/core/browser/browser_policy_connector.h" #include "components/policy/policy_constants.h" #include "components/version_info/channel.h" #include "components/webapps/browser/installable/installable_metrics.h" @@ -108,6 +112,9 @@ const char kGoodCrxId[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf"; const char kSimpleWithIconCrxId[] = "dehdlahnlebladnfleagmjdapdjdcnlp"; const char kHostedAppCrxId[] = "kbmnembihfiondgfjekmnmcbddelicoi"; +// Different versions of this extension Id at +// {DIR_TEST_DATA}/extensions/pinning/ are used in extension pinning tests. +const char kPinnedExtensionCrxId[] = "fdlpamochgodkfemfnickdlkabcfmbln"; const char kGoodCrxVersion[] = "1.0.0.1"; @@ -921,6 +928,9 @@ MOCK_METHOD1(ExtensionStageChanged, void(extensions::InstallStageTracker::Stage)); + MOCK_METHOD2(OnExtensionInstallationFailed, + void(const extensions::ExtensionId&, + extensions::InstallStageTracker::FailureReason)); void OnExtensionDataChangedForTesting( const extensions::ExtensionId& id, @@ -1347,6 +1357,410 @@ EXPECT_EQ(installed_version.CompareTo(base::Version("1.0.0.1")), 0); } +class ExtensionPinningTest : public extensions::ExtensionBrowserTest { + public: + ExtensionPinningTest() = default; + ~ExtensionPinningTest() override = default; + + protected: + // Sets the ExtensionSettings policy so that extension |id| will be + // force-installed from update URL pointing to test server's file + // |update_url_suffix|. It also sets |override_update_url| flag as true for + // the |id|. + void SetExtensionSettingsPolicy(const std::string& update_url_suffix, + const std::string& id) { +#if defined(OS_WIN) + // Unless enterprise managed, policy handler only allows extensions from the + // Chrome Webstore to be force installed. Mark enterprise managed for + // windows. + base::win::ScopedDomainStateForTesting scoped_domain(true); +#endif + + ASSERT_TRUE(embedded_test_server()->Started()); + GURL update_url = embedded_test_server()->GetURL(update_url_suffix); + + PolicyMap policies; + base::Value dict(base::Value::Type::DICTIONARY), + key_dict(base::Value::Type::DICTIONARY); + key_dict.SetStringKey(extensions::schema_constants::kInstallationMode, + extensions::schema_constants::kForceInstalled); + key_dict.SetStringKey(extensions::schema_constants::kUpdateUrl, + update_url.spec()); + key_dict.SetBoolKey(extensions::schema_constants::kOverrideUpdateUrl, true); + dict.SetKey(id, std::move(key_dict)); + policies.Set(key::kExtensionSettings, POLICY_LEVEL_MANDATORY, + POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, std::move(dict), + nullptr); + provider_.UpdateChromePolicy(policies); + } + + // Triggers extension update process and waits for either extension + // installation success if |expected_install_success| is true or else + // extension installation failure. + const extensions::Extension* TriggerExtensionUpdate( + const std::string& id, + bool expected_install_success) { + extensions::ExtensionRegistry* registry = extension_registry(); + if (registry->GetExtensionById( + id, extensions::ExtensionRegistry::EVERYTHING) == nullptr) { + return nullptr; + } + + extensions::ExtensionService* service = extension_service(); + extensions::ExtensionUpdater* updater = service->updater(); + extensions::ExtensionUpdater::CheckParams params; + params.install_immediately = true; + + if (expected_install_success) { + extensions::TestExtensionRegistryObserver update_observer( + extension_registry()); + updater->CheckNow(std::move(params)); + update_observer.WaitForExtensionWillBeInstalled(); + } else { + base::RunLoop run_loop; + MockedInstallationCollectorObserver collector_observer( + browser()->profile()); + extensions::InstallStageTracker* install_stage_tracker = + extensions::InstallStageTracker::Get(browser()->profile()); + install_stage_tracker->AddObserver(&collector_observer); + + // We expect install failure only due to no update for the extension. + EXPECT_CALL( + collector_observer, + OnExtensionInstallationFailed( + testing::_, + extensions::InstallStageTracker::FailureReason::NO_UPDATE)) + .WillOnce(testing::Invoke([&]() { run_loop.Quit(); })); + updater->CheckNow(std::move(params)); + run_loop.Run(); + } + + return registry->enabled_extensions().GetByID(id); + } + + void SetUpInProcessBrowserTestFixture() override { + ExtensionBrowserTest::SetUpInProcessBrowserTestFixture(); + + EXPECT_CALL(provider_, IsInitializationComplete(testing::_)) + .WillRepeatedly(testing::Return(true)); + EXPECT_CALL(provider_, IsFirstPolicyLoadComplete(testing::_)) + .WillRepeatedly(testing::Return(true)); + BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_); + } + + std::string GetUpdateManifestBody(const std::string& id, + const std::string& crx_name, + const std::string& version) { + // "example.com" is a placeholder that gets substituted with the test + // server address at runtime. + std::string crx_path = "http://example.com/" + crx_name; + return "<?xml version='1.0' encoding='UTF-8'?>" + "<gupdate xmlns='http://www.google.com/update2/response' " + "protocol='2.0'>" + " <app appid='" + + id + + "'>" + " <updatecheck status='ok' codebase='" + + crx_path + "' version='" + version + + "' />" + " </app>" + "</gupdate>"; + } + + std::string GetUpdateManifestHeader() { + return "HTTP/1.1 200 OK\nContent-Type: application/json; " + "charset=utf-8\n"; + } + + base::FilePath PackLocalExtension(const std::string& relative_dir_path, + const std::string& relative_pem_path, + const base::FilePath& crx_path) { + base::FilePath base_path; + GetTestDataDirectory(&base_path); + auto extension_path = + base_path.Append(kTestExtensionsDir).AppendASCII(relative_dir_path); + base::FilePath pem_path = + base_path.Append(kTestExtensionsDir).AppendASCII(relative_pem_path); + return PackExtensionWithOptions(extension_path, crx_path, pem_path, + base::FilePath()); + } + + private: + MockConfigurationPolicyProvider provider_; +}; + +// Extension without update_url in manifest gets updated through update_url in +// policy. +IN_PROC_BROWSER_TEST_F(ExtensionPinningTest, + UpdateExtensionWithNoUrlInManifest) { + base::ScopedAllowBlockingForTesting allow_blocking; + base::ScopedTempDir scoped_temp_dir; + EXPECT_TRUE(scoped_temp_dir.CreateUniqueTempDir()); + + base::FilePath install_crx_path = + scoped_temp_dir.GetPath().AppendASCII("v1.crx"); + ASSERT_EQ( + PackLocalExtension("pinning/no_update_url/v1", + "pinning/no_update_url/key.pem", install_crx_path), + install_crx_path); + + // Intercept requests to install the extension and return false for any + // unexpected request. + ExtensionRequestInterceptor interceptor; + ASSERT_TRUE(embedded_test_server()->Start()); + // TODO(b/172205862): Find a way to move these requests out of the test. + interceptor.set_interceptor_hook(base::BindLambdaForTesting( + [&](content::URLLoaderInterceptor::RequestParams* params) { + if (params->url_request.url.path() == "/update_manifest_v1.xml") { + content::URLLoaderInterceptor::WriteResponse( + GetUpdateManifestHeader(), + GetUpdateManifestBody(kPinnedExtensionCrxId, "v1.crx", + /*version=*/"1"), + params->client.get()); + return true; + } + + if (params->url_request.url.path() == "/v1.crx") { + content::URLLoaderInterceptor::WriteResponse(install_crx_path, + params->client.get()); + return true; + } + return false; + })); + + extensions::TestExtensionRegistryObserver observer(extension_registry(), + kPinnedExtensionCrxId); + SetExtensionSettingsPolicy("/update_manifest_v1.xml", kPinnedExtensionCrxId); + auto installed_extension = observer.WaitForExtensionWillBeInstalled(); + ASSERT_TRUE(installed_extension); + EXPECT_EQ(installed_extension->version().CompareTo(base::Version("1")), 0); + + base::FilePath updated_crx_path = + scoped_temp_dir.GetPath().AppendASCII("v2.crx"); + ASSERT_EQ( + PackLocalExtension("pinning/no_update_url/v2", + "pinning/no_update_url/key.pem", updated_crx_path), + updated_crx_path); + + // Override the interceptor hook to only accept new requests for updated + // extension. + interceptor.set_interceptor_hook(base::BindLambdaForTesting( + [&](content::URLLoaderInterceptor::RequestParams* params) { + if (params->url_request.url.path() == "/update_manifest_v2.xml") { + content::URLLoaderInterceptor::WriteResponse( + GetUpdateManifestHeader(), + GetUpdateManifestBody(kPinnedExtensionCrxId, "v2.crx", + /*version=*/"2"), + params->client.get()); + return true; + } + + if (params->url_request.url.path() == "/v2.crx") { + content::URLLoaderInterceptor::WriteResponse(updated_crx_path, + params->client.get()); + return true; + } + return false; + })); + // Change |update_url| to point to version 2 of the extension. + SetExtensionSettingsPolicy("/update_manifest_v2.xml", kPinnedExtensionCrxId); + + // Extension is updated from |update_url| in the policy. + const extensions::Extension* updated_extension = TriggerExtensionUpdate( + kPinnedExtensionCrxId, /*expected_install_success=*/true); + ASSERT_TRUE(updated_extension); + EXPECT_EQ(updated_extension->version().CompareTo(base::Version("2")), 0); +} + +// Extension with one update_url in manifest gets updated through another +// update_url in policy. +IN_PROC_BROWSER_TEST_F(ExtensionPinningTest, UpdateExtensionWithUrlInManifest) { + base::ScopedAllowBlockingForTesting allow_blocking; + base::ScopedTempDir scoped_temp_dir; + EXPECT_TRUE(scoped_temp_dir.CreateUniqueTempDir()); + + base::FilePath install_crx_path = + scoped_temp_dir.GetPath().AppendASCII("v1.crx"); + ASSERT_EQ(PackLocalExtension("pinning/update_url/v1", + "pinning/update_url/key.pem", install_crx_path), + install_crx_path); + + // Intercept requests to update the extension and return false for any + // unexpected request. + ExtensionRequestInterceptor interceptor; + ASSERT_TRUE(embedded_test_server()->Start()); + // TODO(b/172205862): Find a way to move these requests out of the test. + interceptor.set_interceptor_hook(base::BindLambdaForTesting( + [&](content::URLLoaderInterceptor::RequestParams* params) { + if (params->url_request.url.path() == "/update_manifest_v1.xml") { + content::URLLoaderInterceptor::WriteResponse( + GetUpdateManifestHeader(), + GetUpdateManifestBody(kPinnedExtensionCrxId, "v1.crx", + /*version=*/"1"), + params->client.get()); + return true; + } + + if (params->url_request.url.path() == "/v1.crx") { + content::URLLoaderInterceptor::WriteResponse(install_crx_path, + params->client.get()); + return true; + } + return false; + })); + + extensions::TestExtensionRegistryObserver observer(extension_registry(), + kPinnedExtensionCrxId); + SetExtensionSettingsPolicy("/update_manifest_v1.xml", kPinnedExtensionCrxId); + auto installed_extension = observer.WaitForExtensionWillBeInstalled(); + ASSERT_TRUE(installed_extension); + EXPECT_EQ(installed_extension->version().CompareTo(base::Version("1")), 0); + + base::FilePath updated_crx_path = + scoped_temp_dir.GetPath().AppendASCII("v2.crx"); + ASSERT_EQ(PackLocalExtension("pinning/update_url/v2", + "pinning/update_url/key.pem", updated_crx_path), + updated_crx_path); + + // Override the interceptor hook to only accept new requests for updated + // extension. + interceptor.set_interceptor_hook(base::BindLambdaForTesting( + [&](content::URLLoaderInterceptor::RequestParams* params) { + if (params->url_request.url.path() == "/update_manifest_v2.xml") { + content::URLLoaderInterceptor::WriteResponse( + GetUpdateManifestHeader(), + GetUpdateManifestBody(kPinnedExtensionCrxId, "v2.crx", + /*version=*/"2"), + params->client.get()); + return true; + } + + if (params->url_request.url.path() == "/v2.crx") { + content::URLLoaderInterceptor::WriteResponse(updated_crx_path, + params->client.get()); + return true; + } + return false; + })); + // Change |update_url| to point to version 2 of the extension. + SetExtensionSettingsPolicy("/update_manifest_v2.xml", kPinnedExtensionCrxId); + + // Extension is updated from |update_url| in the policy. + const extensions::Extension* updated_extension = TriggerExtensionUpdate( + kPinnedExtensionCrxId, /*expected_install_success=*/true); + ASSERT_TRUE(updated_extension); + EXPECT_EQ(updated_extension->version().CompareTo(base::Version("2")), 0); +} + +// Extension with one update_url in manifest is not updated through it. +IN_PROC_BROWSER_TEST_F(ExtensionPinningTest, IgnoreUpdateUrlInManifest) { + base::ScopedAllowBlockingForTesting allow_blocking; + base::ScopedTempDir scoped_temp_dir; + EXPECT_TRUE(scoped_temp_dir.CreateUniqueTempDir()); + + base::FilePath install_crx_path = + scoped_temp_dir.GetPath().AppendASCII("v1.crx"); + ASSERT_EQ(PackLocalExtension("pinning/update_url/v1", + "pinning/update_url/key.pem", install_crx_path), + install_crx_path); + + // Intercept requests to update the extension and return false for any + // unexpected request. + ExtensionRequestInterceptor interceptor; + ASSERT_TRUE(embedded_test_server()->Start()); + // TODO(b/172205862): Find a way to move these requests out of the test. + interceptor.set_interceptor_hook(base::BindLambdaForTesting( + [&](content::URLLoaderInterceptor::RequestParams* params) { + if (params->url_request.url.path() == "/update_manifest_v1.xml") { + content::URLLoaderInterceptor::WriteResponse( + GetUpdateManifestHeader(), + GetUpdateManifestBody(kPinnedExtensionCrxId, "v1.crx", + /*version=*/"1"), + params->client.get()); + return true; + } + + if (params->url_request.url.path() == "/v1.crx") { + content::URLLoaderInterceptor::WriteResponse(install_crx_path, + params->client.get()); + return true; + } + return false; + })); + + extensions::TestExtensionRegistryObserver observer(extension_registry(), + kPinnedExtensionCrxId); + SetExtensionSettingsPolicy("/update_manifest_v1.xml", kPinnedExtensionCrxId); + auto installed_extension = observer.WaitForExtensionWillBeInstalled(); + ASSERT_TRUE(installed_extension); + EXPECT_EQ(installed_extension->version().CompareTo(base::Version("1")), 0); + + // Extension is not updated from |update_url| in extension manifest. The + // installation fails due to no updates as |update_url| in the + // ExtensionSettings policy is used for updates which points to the installed + // version. + const extensions::Extension* updated_extension = TriggerExtensionUpdate( + kPinnedExtensionCrxId, /*expected_install_success=*/false); + ASSERT_TRUE(updated_extension); + EXPECT_EQ(updated_extension->version().CompareTo(base::Version("1")), 0); +} + +// Self hosted extension from the Chrome Web Store is not updated through the +// update_url in it's manifest even though a new version is available on the +// Store. +IN_PROC_BROWSER_TEST_F(ExtensionPinningTest, + SelfHostedCWSExtensionNotUpdatedFromStore) { + // Sample Google calendar extension from Chrome Web Store, for which we have + // an old CRX. + const char kGoogleCalendarCrxId[] = "gmbgaklkmjakoegficnlkhebmhkjfich"; + extensions::ExtensionRegistry* registry = extension_registry(); + ASSERT_FALSE(registry->GetExtensionById( + kGoogleCalendarCrxId, extensions::ExtensionRegistry::EVERYTHING)); + + // Intercept requests to update the extension and return false for any + // unexpected request. + ExtensionRequestInterceptor interceptor; + ASSERT_TRUE(embedded_test_server()->Start()); + // TODO(b/172205862): Find a way to move these requests out of the test. + interceptor.set_interceptor_hook(base::BindLambdaForTesting( + [&](content::URLLoaderInterceptor::RequestParams* params) { + if (params->url_request.url.path() == "/update_manifest.xml") { + content::URLLoaderInterceptor::WriteResponse( + GetUpdateManifestHeader(), + GetUpdateManifestBody(kGoogleCalendarCrxId, "calendar.crx", + "3.1.0"), + params->client.get()); + return true; + } + + if (params->url_request.url.path() == "/calendar.crx") { + content::URLLoaderInterceptor::WriteResponse( + "chrome/test/data/extensions/pinning/calendar/" + "gmbgaklkmjakoegficnlkhebmhkjfich-google-calendar-3.1.0.crx", + params->client.get()); + return true; + } + return false; + })); + + extensions::TestExtensionRegistryObserver observer(extension_registry(), + kGoogleCalendarCrxId); + SetExtensionSettingsPolicy("/update_manifest.xml", kGoogleCalendarCrxId); + auto installed_extension = observer.WaitForExtensionWillBeInstalled(); + ASSERT_TRUE(installed_extension); + EXPECT_EQ(installed_extension->version().CompareTo(base::Version("3.1.0")), + 0); + + // Extension is not updated from |update_url| in extension manifest. The + // installation fails due to no updates as |update_url| in the + // ExtensionSettings policy is used for updates which points to the installed + // version. + const extensions::Extension* updated_extension = TriggerExtensionUpdate( + kGoogleCalendarCrxId, /*expected_install_success=*/false); + ASSERT_TRUE(updated_extension); + EXPECT_EQ(updated_extension->version().CompareTo(base::Version("3.1.0")), 0); +} + // Verifies that if multiple <app> tags for an extension are specified in the // update manifest, the first valid tag is selected for crx download. This // test helps to notify of any change in this behaviour as there might be
diff --git a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java index 54e15d5..fc79582ff4 100644 --- a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java +++ b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java
@@ -486,6 +486,14 @@ public static final String LAST_SESSION_BROWSER_PID = "Chrome.CrashReporting.LastSessionBrowserPid"; + /** + * The application state last recorded by browser in previous session, updated when crash + * reporting is initialized and when current application state changes henceforth. If read after + * crash reporting is initialized, then the value would hold current session state. + */ + public static final String LAST_SESSION_APPLICATION_STATE = + "Chrome.CrashReporting.LastSessionApplicationState"; + public static final String LOCALE_MANAGER_AUTO_SWITCH = "LocaleManager_PREF_AUTO_SWITCH"; public static final String LOCALE_MANAGER_PROMO_SHOWN = "LocaleManager_PREF_PROMO_SHOWN"; public static final String LOCALE_MANAGER_SEARCH_ENGINE_PROMO_SHOW_STATE = @@ -911,6 +919,7 @@ IMAGE_DESCRIPTIONS_DONT_ASK_AGAIN, ISOLATED_SPLITS_DEX_COMPILE_VERSION, LAST_SESSION_BROWSER_PID, + LAST_SESSION_APPLICATION_STATE, OFFLINE_INDICATOR_V2_WALL_TIME_SHOWN_MS, OFFLINE_INDICATOR_V2_LAST_UPDATE_WALL_TIME_MS, OFFLINE_INDICATOR_V2_TIME_IN_FOREGROUND_MS,
diff --git a/chrome/browser/renderer_context_menu/mock_render_view_context_menu.cc b/chrome/browser/renderer_context_menu/mock_render_view_context_menu.cc index 9a6802b..36584ea 100644 --- a/chrome/browser/renderer_context_menu/mock_render_view_context_menu.cc +++ b/chrome/browser/renderer_context_menu/mock_render_view_context_menu.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/renderer_context_menu/mock_render_view_context_menu.h" +#include <algorithm> + #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/profiles/profile.h" #include "chrome/grit/generated_resources.h" @@ -156,9 +158,6 @@ return; } } - - FAIL() << "Menu observer is trying to change a menu item it doesn't own." - << " command_id: " << command_id; } void MockRenderViewContextMenu::UpdateMenuIcon(int command_id, @@ -174,10 +173,45 @@ << " command_id: " << command_id; } -void MockRenderViewContextMenu::RemoveMenuItem(int command_id) {} +void MockRenderViewContextMenu::RemoveMenuItem(int command_id) { + auto old_end = items_.end(); + auto new_end = std::remove_if( + items_.begin(), old_end, + [command_id](const auto& item) { return item.command_id == command_id; }); + + if (new_end == old_end) { + FAIL() << "Menu observer is trying to remove a menu item it doesn't own." + << " command_id: " << command_id; + return; + } + + items_.erase(new_end, old_end); +} void MockRenderViewContextMenu::RemoveAdjacentSeparators() {} +void MockRenderViewContextMenu::RemoveSeparatorBeforeMenuItem(int command_id) { + auto iter = std::find_if( + items_.begin(), items_.end(), + [command_id](const auto& item) { return item.command_id == command_id; }); + + if (iter == items_.end()) { + FAIL() << "Menu observer is trying to remove a separator before a " + "non-existent item." + << " command_id: " << command_id; + return; + } + + if (iter == items_.begin()) { + FAIL() << "Menu observer is trying to remove a separator before a " + "the first menu item." + << " command_id: " << command_id; + return; + } + + items_.erase(iter - 1); +} + void MockRenderViewContextMenu::AddSpellCheckServiceItem(bool is_checked) { AddCheckItem( IDC_CONTENT_CONTEXT_SPELLING_TOGGLE,
diff --git a/chrome/browser/renderer_context_menu/mock_render_view_context_menu.h b/chrome/browser/renderer_context_menu/mock_render_view_context_menu.h index 31ea3c1..c3019fd1 100644 --- a/chrome/browser/renderer_context_menu/mock_render_view_context_menu.h +++ b/chrome/browser/renderer_context_menu/mock_render_view_context_menu.h
@@ -71,6 +71,7 @@ void UpdateMenuIcon(int command_id, const ui::ImageModel& icon) override; void RemoveMenuItem(int command_id) override; void RemoveAdjacentSeparators() override; + void RemoveSeparatorBeforeMenuItem(int command_id) override; void AddSpellCheckServiceItem(bool is_checked) override; void AddAccessibilityLabelsServiceItem(bool is_checked) override; content::RenderViewHost* GetRenderViewHost() const override;
diff --git a/chrome/browser/renderer_context_menu/spelling_menu_observer.cc b/chrome/browser/renderer_context_menu/spelling_menu_observer.cc index 0c26cba..5e17490 100644 --- a/chrome/browser/renderer_context_menu/spelling_menu_observer.cc +++ b/chrome/browser/renderer_context_menu/spelling_menu_observer.cc
@@ -6,6 +6,7 @@ #include <utility> +#include "base/barrier_closure.h" #include "base/bind.h" #include "base/command_line.h" #include "base/i18n/case_conversion.h" @@ -62,7 +63,7 @@ void SpellingMenuObserver::InitMenu(const content::ContextMenuParams& params) { DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(!params.misspelled_word.empty() || - params.dictionary_suggestions.empty()); + params.dictionary_suggestions.empty()); // Exit if we are not in an editable element because we add a menu item only // for editable elements. @@ -74,100 +75,141 @@ if (params.misspelled_word.empty()) return; + // Note that for Windows, suggestions_ will initially only contain those + // suggestions obtained using Hunspell. suggestions_ = params.dictionary_suggestions; misspelled_word_ = params.misspelled_word; - bool use_suggestions = SpellingServiceClient::IsAvailable( + use_remote_suggestions_ = SpellingServiceClient::IsAvailable( browser_context, SpellingServiceClient::SUGGEST); - if (!suggestions_.empty() || use_suggestions) - proxy_->AddSeparator(); - - // Append Dictionary spell check suggestions. - int length = std::min(kMaxSpellingSuggestions, - static_cast<int>(params.dictionary_suggestions.size())); - for (int i = 0; i < length && - IDC_SPELLCHECK_SUGGESTION_0 + i <= IDC_SPELLCHECK_SUGGESTION_LAST; - ++i) { - proxy_->AddMenuItem(IDC_SPELLCHECK_SUGGESTION_0 + static_cast<int>(i), - params.dictionary_suggestions[i]); - } - - // The service types |SpellingServiceClient::SPELLCHECK| and - // |SpellingServiceClient::SUGGEST| are mutually exclusive. Only one is - // available at at time. - // - // When |SpellingServiceClient::SPELLCHECK| is available, the contextual - // suggestions from |SpellingServiceClient| are already stored in - // |params.dictionary_suggestions|. |SpellingMenuObserver| places these - // suggestions in the slots |IDC_SPELLCHECK_SUGGESTION_[0-LAST]|. If - // |SpellingMenuObserver| queried |SpellingServiceClient| again, then quality - // of suggestions would be reduced by lack of context around the misspelled - // word. - // - // When |SpellingServiceClient::SUGGEST| is available, - // |params.dictionary_suggestions| contains suggestions only from Hunspell - // dictionary. |SpellingMenuObserver| queries |SpellingServiceClient| with the - // misspelled word without the surrounding context. Spellcheck suggestions - // from |SpellingServiceClient::SUGGEST| are not available until - // |SpellingServiceClient| responds to the query. While |SpellingMenuObserver| - // waits for |SpellingServiceClient|, it shows a placeholder text "Loading - // suggestion..." in the |IDC_CONTENT_CONTEXT_SPELLING_SUGGESTION| slot. After - // |SpellingServiceClient| responds to the query, |SpellingMenuObserver| - // replaces the placeholder text with either the spelling suggestion or the - // message "No more suggestions from Google." The "No more suggestions" - // message is there when |SpellingServiceClient| returned the same suggestion - // as Hunspell. - if (use_suggestions) { - // Append a placeholder item for the suggestion from the Spelling service - // and send a request to the service if we can retrieve suggestions from it. - // Also, see if we can use the spelling service to get an ideal suggestion. - // Otherwise, we'll fall back to the set of suggestions. Initialize - // variables used in OnTextCheckComplete(). We copy the input text to the - // result text so we can replace its misspelled regions with suggestions. - succeeded_ = false; - result_ = params.misspelled_word; - - // Add a placeholder item. This item will be updated when we receive a - // response from the Spelling service. (We do not have to disable this - // item now since Chrome will call IsCommandIdEnabled() and disable it.) - loading_message_ = - l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_SPELLING_CHECKING); - proxy_->AddMenuItem(IDC_CONTENT_CONTEXT_SPELLING_SUGGESTION, - loading_message_); - // Invoke a JSON-RPC call to the Spelling service in the background so we - // can update the placeholder item when we receive its response. It also - // starts the animation timer so we can show animation until we receive - // it. - bool result = client_->RequestTextCheck( - browser_context, SpellingServiceClient::SUGGEST, params.misspelled_word, - base::BindOnce(&SpellingMenuObserver::OnTextCheckComplete, - base::Unretained(this), SpellingServiceClient::SUGGEST)); - if (result) { - loading_frame_ = 0; - animation_timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(1), - this, &SpellingMenuObserver::OnAnimationTimerExpired); - } - } - - if (!params.dictionary_suggestions.empty()) { - // |spellcheck_service| can be null when the suggested word is - // provided by Web SpellCheck API. +#if defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) + use_platform_suggestions_ = spellcheck::UseBrowserSpellChecker(); + if (use_platform_suggestions_) { + // Need to asynchronously retrieve suggestions from the platform + // spellchecker, which requires the SpellcheckService. SpellcheckService* spellcheck_service = SpellcheckServiceFactory::GetForContext(browser_context); - if (spellcheck_service && spellcheck_service->GetMetrics()) - spellcheck_service->GetMetrics()->RecordSuggestionStats(1); + if (!spellcheck_service) + return; + + // If there are no local suggestions or the spellcheck cloud service isn't + // used, this separator will be removed later. proxy_->AddSeparator(); + + // Append placeholders for maximum number of suggestions. Note that all but + // the first placeholder will be made hidden in OnContextMenuShown override. + // It can't be done here because UpdateMenuItem can only be called after + // ToolkitDelegateViews is initialized, which happens after + // RenderViewContextMenu::InitMenu. + for (int i = 0; + i < kMaxSpellingSuggestions && + IDC_SPELLCHECK_SUGGESTION_0 + i <= IDC_SPELLCHECK_SUGGESTION_LAST; + ++i) { + proxy_->AddMenuItem(IDC_SPELLCHECK_SUGGESTION_0 + i, + /*title=*/std::u16string()); + } + + // Completion barrier for local (and possibly remote) retrieval of + // suggestions. Remote suggestion cannot be displayed until local + // suggestions have been retrieved, so that duplicates can be accounted for. + completion_barrier_ = base::BarrierClosure( + use_remote_suggestions_ ? 2 : 1, + base::BindOnce(&SpellingMenuObserver::OnGetSuggestionsComplete, + weak_ptr_factory_.GetWeakPtr())); + + // Asynchronously retrieve suggestions from the platform spellchecker. + spellcheck_platform::GetPerLanguageSuggestions( + spellcheck_service->platform_spell_checker(), misspelled_word_, + base::BindOnce(&SpellingMenuObserver::OnGetPlatformSuggestionsComplete, + weak_ptr_factory_.GetWeakPtr())); + + if (use_remote_suggestions_) { + // Asynchronously retrieve remote suggestions in parallel. + GetRemoteSuggestions(); + } else { + // Animate first suggestion placeholder while retrieving suggestions. + loading_message_ = + l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_SPELLING_CHECKING); + loading_frame_ = 0; + animation_timer_.Start( + FROM_HERE, base::TimeDelta::FromSeconds(1), + base::BindRepeating(&SpellingMenuObserver::OnAnimationTimerExpired, + weak_ptr_factory_.GetWeakPtr(), + IDC_SPELLCHECK_SUGGESTION_0)); + } + + // If there are no suggestions, this separator between suggestions and "Add + // to dictionary" will be removed later. + proxy_->AddSeparator(); + } else { +#endif // defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) + if (!suggestions_.empty() || use_remote_suggestions_) + proxy_->AddSeparator(); + + // Append Dictionary spell check suggestions. + int length = + std::min(kMaxSpellingSuggestions, + static_cast<int>(params.dictionary_suggestions.size())); + for (int i = 0; i < length && IDC_SPELLCHECK_SUGGESTION_0 + i <= + IDC_SPELLCHECK_SUGGESTION_LAST; + ++i) { + proxy_->AddMenuItem(IDC_SPELLCHECK_SUGGESTION_0 + i, + params.dictionary_suggestions[i]); + } + + if (use_remote_suggestions_) + GetRemoteSuggestions(); + + if (!params.dictionary_suggestions.empty()) { + // |spellcheck_service| can be null when the suggested word is + // provided by Web SpellCheck API. + SpellcheckService* spellcheck_service = + SpellcheckServiceFactory::GetForContext(browser_context); + if (spellcheck_service && spellcheck_service->GetMetrics()) + spellcheck_service->GetMetrics()->RecordSuggestionStats(1); + proxy_->AddSeparator(); + } +#if defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) } +#endif // defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) // If word is misspelled, give option for "Add to dictionary" and, if // multilingual spellchecking is not enabled, a check item "Ask Google for // suggestions". - proxy_->AddMenuItem(IDC_SPELLCHECK_ADD_TO_DICTIONARY, + proxy_->AddMenuItem( + IDC_SPELLCHECK_ADD_TO_DICTIONARY, l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_ADD_TO_DICTIONARY)); proxy_->AddSpellCheckServiceItem(integrate_spelling_service_.GetValue()); } +#if defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) +void SpellingMenuObserver::OnContextMenuShown( + const content::ContextMenuParams& /*params*/, + const gfx::Rect& /*bounds_in_screen*/) { + if (!use_platform_suggestions_) + return; + + // Disable the first place holder but keep it visible for animation if not + // retrieving remote suggestions. Note that UpdateMenuItem does nothing if the + // command_id is not found, e.g. if there is an early exit from InitMenu. + proxy_->UpdateMenuItem(IDC_SPELLCHECK_SUGGESTION_0, + /*enabled=*/false, + /*hidden=*/(use_remote_suggestions_ ? true : false), + loading_message_); + + // Disable and hide the rest of the placeholders until suggestions obtained. + for (int i = 1; + i < kMaxSpellingSuggestions && + IDC_SPELLCHECK_SUGGESTION_0 + i <= IDC_SPELLCHECK_SUGGESTION_LAST; + ++i) { + proxy_->UpdateMenuItem(IDC_SPELLCHECK_SUGGESTION_0 + i, + /*enabled=*/false, /*hidden=*/true, + /*title=*/std::u16string()); + } +} +#endif // defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) + bool SpellingMenuObserver::IsCommandIdSupported(int command_id) { if (command_id >= IDC_SPELLCHECK_SUGGESTION_0 && command_id <= IDC_SPELLCHECK_SUGGESTION_LAST) @@ -313,13 +355,172 @@ } } -void SpellingMenuObserver::OnTextCheckComplete( - SpellingServiceClient::ServiceType type, - bool success, - const std::u16string& text, - const std::vector<SpellCheckResult>& results) { +#if defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) +void SpellingMenuObserver::OnGetPlatformSuggestionsComplete( + const spellcheck::PerLanguageSuggestions& + platform_per_language_suggestions) { + // Prioritize the platform results, since presumably the first user language + // will have a Windows language pack installed. Treat the Hunspell suggestions + // as if a single language. + spellcheck::PerLanguageSuggestions per_language_suggestions = + platform_per_language_suggestions; + per_language_suggestions.push_back(suggestions_); + + std::vector<std::u16string> combined_suggestions; + spellcheck::FillSuggestions(per_language_suggestions, &combined_suggestions); + // suggestions_ will now include those from both the platform spellchecker and + // Hunspell. + suggestions_ = combined_suggestions; + + // The menu can be updated with local suggestions without waiting for the + // request for remote suggestions to complete. + if (suggestions_.empty() && !use_remote_suggestions_) + proxy_->RemoveSeparatorBeforeMenuItem(IDC_SPELLCHECK_SUGGESTION_0); + + // Update spell check suggestions displayed on the menu. + int length = + std::min(kMaxSpellingSuggestions, static_cast<int>(suggestions_.size())); + + for (int i = 0; i < length && IDC_SPELLCHECK_SUGGESTION_0 + i <= + IDC_SPELLCHECK_SUGGESTION_LAST; + ++i) { + proxy_->UpdateMenuItem(IDC_SPELLCHECK_SUGGESTION_0 + i, + /*enabled=*/true, /*hidden=*/false, suggestions_[i]); + } + + for (int i = suggestions_.size(); i < kMaxSpellingSuggestions; ++i) { + // There were fewer suggestions returned than placeholder slots, remove the + // empty menu items. + proxy_->RemoveMenuItem(IDC_SPELLCHECK_SUGGESTION_0 + i); + } + + if (suggestions_.empty()) { + proxy_->RemoveSeparatorBeforeMenuItem(IDC_SPELLCHECK_ADD_TO_DICTIONARY); + } else { + // |spellcheck_service| can be null when the suggested word is + // provided by Web SpellCheck API. + SpellcheckService* spellcheck_service = + SpellcheckServiceFactory::GetForContext(proxy_->GetBrowserContext()); + if (spellcheck_service && spellcheck_service->GetMetrics()) + spellcheck_service->GetMetrics()->RecordSuggestionStats(1); + } + + completion_barrier_.Run(); +} + +void SpellingMenuObserver::OnGetSuggestionsComplete() { animation_timer_.Stop(); + if (use_remote_suggestions_) { + // Update remote suggestion too using cached values from + // OnGetRemoteSuggestionsComplete. + UpdateRemoteSuggestion(remote_service_type_, succeeded_, remote_results_); + } + + FireSuggestionsCompleteCallbackIfNeededForTesting(); +} + +void SpellingMenuObserver::RegisterSuggestionsCompleteCallbackForTesting( + base::OnceClosure callback) { + suggestions_complete_callback_for_testing_ = std::move(callback); +} +#endif // defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) + +void SpellingMenuObserver::GetRemoteSuggestions() { + // The service types |SpellingServiceClient::SPELLCHECK| and + // |SpellingServiceClient::SUGGEST| are mutually exclusive. Only one is + // available at a time. + // + // When |SpellingServiceClient::SPELLCHECK| is available, the contextual + // suggestions from |SpellingServiceClient| are already stored in + // |params.dictionary_suggestions|. |SpellingMenuObserver| places these + // suggestions in the slots |IDC_SPELLCHECK_SUGGESTION_[0-LAST]|. If + // |SpellingMenuObserver| queried |SpellingServiceClient| again, then + // quality of suggestions would be reduced by lack of context around the + // misspelled word. + // + // When |SpellingServiceClient::SUGGEST| is available, + // |params.dictionary_suggestions| contains suggestions only from Hunspell + // dictionary. |SpellingMenuObserver| queries |SpellingServiceClient| with + // the misspelled word without the surrounding context. Spellcheck + // suggestions from |SpellingServiceClient::SUGGEST| are not available until + // |SpellingServiceClient| responds to the query. While + // |SpellingMenuObserver| waits for |SpellingServiceClient|, it shows a + // placeholder text "Loading suggestion..." in the + // |IDC_CONTENT_CONTEXT_SPELLING_SUGGESTION| slot. After + // |SpellingServiceClient| responds to the query, |SpellingMenuObserver| + // replaces the placeholder text with either the spelling suggestion or the + // message "No more suggestions from Google." The "No more suggestions" + // message is there when |SpellingServiceClient| returned the same + // suggestion as Hunspell. + // + // Append a placeholder item for the suggestion from the Spelling service + // and send a request to the service if we can retrieve suggestions from it. + // Also, see if we can use the spelling service to get an ideal suggestion. + // Otherwise, we'll fall back to the set of suggestions. Initialize + // variables used in OnTextCheckComplete(). We copy the input text to the + // result text so we can replace its misspelled regions with suggestions. + succeeded_ = false; + result_ = misspelled_word_; + + // Add a placeholder item. This item will be updated when we receive a + // response from the Spelling service. (We do not have to disable this + // item now since Chrome will call IsCommandIdEnabled() and disable it.) + loading_message_ = + l10n_util::GetStringUTF16(IDS_CONTENT_CONTEXT_SPELLING_CHECKING); + proxy_->AddMenuItem(IDC_CONTENT_CONTEXT_SPELLING_SUGGESTION, + loading_message_); + + // Invoke a JSON-RPC call to the Spelling service in the background so we + // can update the placeholder item when we receive its response. It also + // starts the animation timer so we can show animation until we receive + // it. + content::BrowserContext* browser_context = proxy_->GetBrowserContext(); + if (!browser_context) + return; + bool result = client_->RequestTextCheck( + browser_context, SpellingServiceClient::SUGGEST, misspelled_word_, + base::BindOnce(&SpellingMenuObserver::OnGetRemoteSuggestionsComplete, + weak_ptr_factory_.GetWeakPtr(), + SpellingServiceClient::SUGGEST)); + if (result) { + loading_frame_ = 0; + animation_timer_.Start( + FROM_HERE, base::TimeDelta::FromSeconds(1), + base::BindRepeating(&SpellingMenuObserver::OnAnimationTimerExpired, + weak_ptr_factory_.GetWeakPtr(), + IDC_CONTENT_CONTEXT_SPELLING_SUGGESTION)); + } +} + +void SpellingMenuObserver::OnGetRemoteSuggestionsComplete( + SpellingServiceClient::ServiceType type, + bool success, + const std::u16string& /*text*/, + const std::vector<SpellCheckResult>& results) { +#if defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) + if (use_platform_suggestions_) { + // Cache results since we need the parallel retrieval of local suggestions + // to also complete in order to proceed. + remote_service_type_ = type; + succeeded_ = success; + // Parameter |text| is unused. + remote_results_ = results; + + completion_barrier_.Run(); + } else { +#endif // defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) + animation_timer_.Stop(); + UpdateRemoteSuggestion(type, success, results); +#if defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) + } +#endif // defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) +} + +void SpellingMenuObserver::UpdateRemoteSuggestion( + SpellingServiceClient::ServiceType type, + bool success, + const std::vector<SpellCheckResult>& results) { // Scan the text-check results and replace the misspelled regions with // suggested words. If the replaced text is included in the suggestion list // provided by the local spellchecker, we show a "No suggestions from Google" @@ -355,7 +556,14 @@ } } -void SpellingMenuObserver::OnAnimationTimerExpired() { +#if defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) +void SpellingMenuObserver::FireSuggestionsCompleteCallbackIfNeededForTesting() { + if (suggestions_complete_callback_for_testing_) + std::move(suggestions_complete_callback_for_testing_).Run(); +} +#endif // defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) + +void SpellingMenuObserver::OnAnimationTimerExpired(int command_id) { // Append '.' characters to the end of "Checking". loading_frame_ = (loading_frame_ + 1) & 3; std::u16string loading_message = @@ -363,6 +571,6 @@ // Update the menu item with the text. We disable this item to prevent users // from selecting it. - proxy_->UpdateMenuItem(IDC_CONTENT_CONTEXT_SPELLING_SUGGESTION, false, false, - loading_message); + proxy_->UpdateMenuItem(command_id, + /*enabled=*/false, /*hidden=*/false, loading_message); }
diff --git a/chrome/browser/renderer_context_menu/spelling_menu_observer.h b/chrome/browser/renderer_context_menu/spelling_menu_observer.h index af62f242..471ab4b 100644 --- a/chrome/browser/renderer_context_menu/spelling_menu_observer.h +++ b/chrome/browser/renderer_context_menu/spelling_menu_observer.h
@@ -14,10 +14,14 @@ #include "base/compiler_specific.h" #include "base/macros.h" +#include "base/memory/weak_ptr.h" #include "base/timer/timer.h" +#include "build/build_config.h" #include "components/prefs/pref_member.h" #include "components/renderer_context_menu/render_view_context_menu_observer.h" #include "components/spellcheck/browser/spelling_service_client.h" +#include "components/spellcheck/common/spellcheck_common.h" +#include "components/spellcheck/spellcheck_buildflags.h" class RenderViewContextMenuProxy; struct SpellCheckResult; @@ -48,22 +52,61 @@ // RenderViewContextMenuObserver implementation. void InitMenu(const content::ContextMenuParams& params) override; +#if defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) + void OnContextMenuShown(const content::ContextMenuParams& params, + const gfx::Rect& bounds_in_screen) override; +#endif // defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) bool IsCommandIdSupported(int command_id) override; bool IsCommandIdChecked(int command_id) override; bool IsCommandIdEnabled(int command_id) override; void ExecuteCommand(int command_id) override; +#if defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) + // A callback function called when the platform spellchecker finishes getting + // suggestions for a misspelled word. + void OnGetPlatformSuggestionsComplete( + const spellcheck::PerLanguageSuggestions& + platform_per_language_suggestions); + + // A callback for the BarrierClosure, fired when the platform (and possibly + // remote) retrieval of suggestions completes. + void OnGetSuggestionsComplete(); + + // Registers a callback for testing when local (and possibly remote) retrieval + // of suggestions has completed. This allows tests to wait in a run loop + // before confirming the presence of expected menu items. + void RegisterSuggestionsCompleteCallbackForTesting( + base::OnceClosure callback); +#endif // defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) + // A callback function called when the Spelling service finishes checking a // misspelled word. - void OnTextCheckComplete(SpellingServiceClient::ServiceType type, - bool success, - const std::u16string& text, - const std::vector<SpellCheckResult>& results); + void OnGetRemoteSuggestionsComplete( + SpellingServiceClient::ServiceType type, + bool success, + const std::u16string& text, + const std::vector<SpellCheckResult>& results); private: + // Method that starts the asynchronous retrieval of suggestions from the + // remote enhanced spellcheck service. + void GetRemoteSuggestions(); + + // Updates the presented suggestion from the Spelling service. + void UpdateRemoteSuggestion(SpellingServiceClient::ServiceType type, + bool success, + const std::vector<SpellCheckResult>& results); + +#if defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) + // Fires a callback for testing when local (and possibly remote) retrieval of + // suggestions has completed. This allows tests to wait in a run loop before + // confirming the presence of expected menu items. + void FireSuggestionsCompleteCallbackIfNeededForTesting(); +#endif // defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) + // The callback function for base::RepeatingTimer. This function updates the - // "loading..." animation in the context-menu item. - void OnAnimationTimerExpired(); + // "loading..." animation in the context-menu item for the given command_id. + void OnAnimationTimerExpired(int command_id); // The interface to add a context-menu item and update it. This class uses // this interface to avoid accesing context-menu items directly. @@ -112,6 +155,30 @@ // Flag indicating whether automatic spelling correction is enabled. BooleanPrefMember autocorrect_spelling_; + // Flag indicating that suggestions from the remote spelling service may be + // available. + bool use_remote_suggestions_ = false; + +#if defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) + // Flag indicating that suggestions should be retrieved asynchronously from + // the platform spellchecker (effectively just Windows versions > Win7). + bool use_platform_suggestions_ = false; + + // Barrier closure for completion of both remote and local check. + base::RepeatingClosure completion_barrier_; + + // Used for caching remote results in case async platform suggestion retrieval + // has not completed. + SpellingServiceClient::ServiceType remote_service_type_ = + SpellingServiceClient::SUGGEST; + std::vector<SpellCheckResult> remote_results_; + + // Callback registered using RegisterSuggestionsCompleteCallbackForTesting. + base::OnceClosure suggestions_complete_callback_for_testing_; +#endif // defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) + + base::WeakPtrFactory<SpellingMenuObserver> weak_ptr_factory_{this}; + DISALLOW_COPY_AND_ASSIGN(SpellingMenuObserver); };
diff --git a/chrome/browser/renderer_context_menu/spelling_menu_observer_browsertest.cc b/chrome/browser/renderer_context_menu/spelling_menu_observer_browsertest.cc index 6d9c0ba8..9fcf05b 100644 --- a/chrome/browser/renderer_context_menu/spelling_menu_observer_browsertest.cc +++ b/chrome/browser/renderer_context_menu/spelling_menu_observer_browsertest.cc
@@ -6,13 +6,19 @@ #include "base/macros.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_feature_list.h" #include "base/values.h" +#include "build/build_config.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/renderer_context_menu/mock_render_view_context_menu.h" +#include "chrome/browser/spellchecker/spellcheck_factory.h" +#include "chrome/browser/spellchecker/spellcheck_service.h" #include "chrome/test/base/in_process_browser_test.h" #include "components/prefs/pref_service.h" #include "components/spellcheck/browser/pref_names.h" #include "components/spellcheck/browser/spelling_service_client.h" +#include "components/spellcheck/common/spellcheck_features.h" +#include "components/spellcheck/spellcheck_buildflags.h" #include "content/public/browser/context_menu_params.h" #include "content/public/test/browser_test.h" #include "testing/gtest/include/gtest/gtest.h" @@ -25,7 +31,68 @@ public: SpellingMenuObserverTest(); - void SetUpOnMainThread() override { Reset(false); } + void SetUpOnMainThread() override { + Reset(false); + +#if defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) + // Windows versions that don't support platform + // spellchecker fallback to Hunspell. + if (!spellcheck::WindowsVersionSupportsSpellchecker()) + return; + + base::ListValue dictionary; + dictionary.AppendString("en-US"); + menu()->GetPrefs()->Set(spellcheck::prefs::kSpellCheckDictionaries, + dictionary); + // Use SetTestingFactoryAndUse to force creation and initialization of + // SpellcheckService using the TestingProfile browser context. + SpellcheckServiceFactory::GetInstance()->SetTestingFactoryAndUse( + menu()->GetBrowserContext(), + base::BindRepeating(&SpellingMenuObserverTest::BuildSpellcheckService, + base::Unretained(this))); +#endif // defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) + } + +#if defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) + std::unique_ptr<KeyedService> BuildSpellcheckService( + content::BrowserContext* context) { + auto spellcheck_service = std::make_unique<SpellcheckService>(context); + + // Call SetLanguage to assure that the platform spellchecker is initialized. + spellcheck_platform::SetLanguage( + spellcheck_service->platform_spell_checker(), "en-US", + base::BindOnce(&SpellingMenuObserverTest::OnSetLanguageComplete, + base::Unretained(this))); + + RunUntilCallbackReceived(); + + return spellcheck_service; + } + + void OnSetLanguageComplete(bool result) { + ASSERT_TRUE(result); + callback_received_ = true; + if (quit_) + std::move(quit_).Run(); + } + + void OnSuggestionsComplete() { + callback_received_ = true; + if (quit_) + std::move(quit_).Run(); + } + + void RunUntilCallbackReceived() { + if (callback_received_) + return; + base::RunLoop run_loop; + quit_ = run_loop.QuitClosure(); + run_loop.Run(); + + // Reset status. + callback_received_ = false; + } +#endif // defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) void TearDownOnMainThread() override { observer_.reset(); @@ -46,7 +113,29 @@ params.dictionary_suggestions.clear(); if (suggestion) params.dictionary_suggestions.push_back(base::ASCIIToUTF16(suggestion)); + +#if defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) + // Expect early return if word is spelled correctly. + if (params.misspelled_word.empty()) + callback_received_ = true; + + if (spellcheck::WindowsVersionSupportsSpellchecker()) { + observer_->RegisterSuggestionsCompleteCallbackForTesting( + base::BindOnce(&SpellingMenuObserverTest::OnSuggestionsComplete, + base::Unretained(this))); + } +#endif // defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) + observer_->InitMenu(params); + + // Windows behavior needs this to be called as well to update placeholder + // menu items. Doesn't hurt for non-Windows platforms either. + observer_->OnContextMenuShown(params, gfx::Rect()); + +#if defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) + if (spellcheck::WindowsVersionSupportsSpellchecker()) + RunUntilCallbackReceived(); +#endif // defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) } void ForceSuggestMode() { @@ -70,14 +159,32 @@ private: std::unique_ptr<SpellingMenuObserver> observer_; std::unique_ptr<MockRenderViewContextMenu> menu_; + +#if defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) + // Quits the RunLoop on receiving callbacks. + base::OnceClosure quit_; + + // Flag used for early exit from RunLoop if callback already received. + bool callback_received_ = false; + + base::test::ScopedFeatureList feature_list_; +#endif // defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) + DISALLOW_COPY_AND_ASSIGN(SpellingMenuObserverTest); }; +#if defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) SpellingMenuObserverTest::SpellingMenuObserverTest() { + feature_list_.InitWithFeatures( + /*enabled_features=*/{spellcheck::kWinUseBrowserSpellChecker, + spellcheck::kWinRetrieveSuggestionsOnlyOnDemand}, + /*disabled_features=*/{spellcheck::kWinDelaySpellcheckServiceInit}); } +#else +SpellingMenuObserverTest::SpellingMenuObserverTest() = default; +#endif // defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) -SpellingMenuObserverTest::~SpellingMenuObserverTest() { -} +SpellingMenuObserverTest::~SpellingMenuObserverTest() = default; } // namespace @@ -90,7 +197,8 @@ // Tests that right-clicking a misspelled word adds two items: // "Add to dictionary", "Use enhanced spell check". IN_PROC_BROWSER_TEST_F(SpellingMenuObserverTest, InitMenuWithMisspelledWord) { - InitMenu("wiimode", nullptr); + // Pick word that Windows platform spellcheck has no suggestions for. + InitMenu("missssspelling", nullptr); EXPECT_EQ(2U, menu()->GetMenuSize()); // Read all the context-menu items added by this test and verify they are @@ -110,9 +218,160 @@ menu()->GetMenuItem(2, &item); } +#if defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) +// Tests that right-clicking a misspelled word that is identified as misspelled +// by both Hunspell and Windows platform combines their suggestions. +IN_PROC_BROWSER_TEST_F(SpellingMenuObserverTest, + WinInitMenuWithMisspelledWordCombined) { + // Test invalid for Windows versions that don't support platform spellchecker. + if (!spellcheck::WindowsVersionSupportsSpellchecker()) + return; + + InitMenu("mispelled", "misspelling"); + EXPECT_EQ(6U, menu()->GetMenuSize()); + + // Read all the context-menu items added by this test and verify they are + // expected ones. + MockRenderViewContextMenu::MockMenuItem item; + // First separator. + menu()->GetMenuItem(0, &item); + EXPECT_EQ(-1, item.command_id); + EXPECT_FALSE(item.enabled); + EXPECT_FALSE(item.hidden); + // First suggestion. + menu()->GetMenuItem(1, &item); + EXPECT_EQ(IDC_SPELLCHECK_SUGGESTION_0, item.command_id); + EXPECT_TRUE(item.enabled); + EXPECT_FALSE(item.hidden); + EXPECT_EQ(base::ASCIIToUTF16("misspelled"), item.title); + // Second suggestion. + menu()->GetMenuItem(2, &item); + EXPECT_EQ(IDC_SPELLCHECK_SUGGESTION_0 + 1, item.command_id); + EXPECT_TRUE(item.enabled); + EXPECT_FALSE(item.hidden); + EXPECT_EQ(base::ASCIIToUTF16("misspelling"), item.title); + // Second separator. + menu()->GetMenuItem(3, &item); + EXPECT_EQ(-1, item.command_id); + EXPECT_FALSE(item.enabled); + EXPECT_FALSE(item.hidden); + // Add to dictionary. + menu()->GetMenuItem(4, &item); + EXPECT_EQ(IDC_SPELLCHECK_ADD_TO_DICTIONARY, item.command_id); + EXPECT_TRUE(item.enabled); + EXPECT_FALSE(item.hidden); + // Enhanced spellcheck toggle. + menu()->GetMenuItem(5, &item); + EXPECT_EQ(IDC_CONTENT_CONTEXT_SPELLING_TOGGLE, item.command_id); + EXPECT_TRUE(item.enabled); + EXPECT_FALSE(item.checked); + EXPECT_FALSE(item.hidden); +} + +// Tests that right-clicking a misspelled word that is identified as misspelled +// by both Hunspell and Windows platform with the same suggestion leads to a +// single suggestion. +IN_PROC_BROWSER_TEST_F(SpellingMenuObserverTest, + WinInitMenuWithMisspelledWordNoDuplicateSuggestions) { + // Test invalid for Windows versions that don't support platform spellchecker. + if (!spellcheck::WindowsVersionSupportsSpellchecker()) + return; + + InitMenu("mispelled", "misspelled"); + EXPECT_EQ(5U, menu()->GetMenuSize()); + + // Read all the context-menu items added by this test and verify they are + // expected ones. + MockRenderViewContextMenu::MockMenuItem item; + // First separator. + menu()->GetMenuItem(0, &item); + EXPECT_EQ(-1, item.command_id); + EXPECT_FALSE(item.enabled); + EXPECT_FALSE(item.hidden); + // First and only suggestion. + menu()->GetMenuItem(1, &item); + EXPECT_EQ(IDC_SPELLCHECK_SUGGESTION_0, item.command_id); + EXPECT_TRUE(item.enabled); + EXPECT_FALSE(item.hidden); + EXPECT_EQ(base::ASCIIToUTF16("misspelled"), item.title); + // Second separator. + menu()->GetMenuItem(2, &item); + EXPECT_EQ(-1, item.command_id); + EXPECT_FALSE(item.enabled); + EXPECT_FALSE(item.hidden); + // Add to dictionary. + menu()->GetMenuItem(3, &item); + EXPECT_EQ(IDC_SPELLCHECK_ADD_TO_DICTIONARY, item.command_id); + EXPECT_TRUE(item.enabled); + EXPECT_FALSE(item.hidden); + // Enhanced spellcheck toggle. + menu()->GetMenuItem(4, &item); + EXPECT_EQ(IDC_CONTENT_CONTEXT_SPELLING_TOGGLE, item.command_id); + EXPECT_TRUE(item.enabled); + EXPECT_FALSE(item.checked); + EXPECT_FALSE(item.hidden); +} + +// Tests that right-clicking a misspelled word that is identified as misspelled +// by both Hunspell and Windows platform that has > 3 suggestions only displays +// 3 suggestions. +IN_PROC_BROWSER_TEST_F(SpellingMenuObserverTest, + WinInitMenuWithMisspelledWordMaxSuggestions) { + // Test invalid for Windows versions that don't support platform spellchecker. + if (!spellcheck::WindowsVersionSupportsSpellchecker()) + return; + + InitMenu("wtree", "wee"); + EXPECT_EQ(7U, menu()->GetMenuSize()); + + // Read all the context-menu items added by this test and verify they are + // expected ones. + MockRenderViewContextMenu::MockMenuItem item; + // First separator. + menu()->GetMenuItem(0, &item); + EXPECT_EQ(-1, item.command_id); + EXPECT_FALSE(item.enabled); + EXPECT_FALSE(item.hidden); + // First suggestion. + menu()->GetMenuItem(1, &item); + EXPECT_EQ(IDC_SPELLCHECK_SUGGESTION_0, item.command_id); + EXPECT_TRUE(item.enabled); + EXPECT_FALSE(item.hidden); + EXPECT_EQ(base::ASCIIToUTF16("tree"), item.title); + // Second suggestion. + menu()->GetMenuItem(2, &item); + EXPECT_EQ(IDC_SPELLCHECK_SUGGESTION_0 + 1, item.command_id); + EXPECT_TRUE(item.enabled); + EXPECT_FALSE(item.hidden); + EXPECT_EQ(base::ASCIIToUTF16("wee"), item.title); + // Third suggestion. + menu()->GetMenuItem(3, &item); + EXPECT_EQ(IDC_SPELLCHECK_SUGGESTION_0 + 2, item.command_id); + EXPECT_TRUE(item.enabled); + EXPECT_FALSE(item.hidden); + EXPECT_EQ(base::ASCIIToUTF16("were"), item.title); + // Second separator. + menu()->GetMenuItem(4, &item); + EXPECT_EQ(-1, item.command_id); + EXPECT_FALSE(item.enabled); + EXPECT_FALSE(item.hidden); + // Add to dictionary. + menu()->GetMenuItem(5, &item); + EXPECT_EQ(IDC_SPELLCHECK_ADD_TO_DICTIONARY, item.command_id); + EXPECT_TRUE(item.enabled); + EXPECT_FALSE(item.hidden); + // Enhanced spellcheck toggle. + menu()->GetMenuItem(6, &item); + EXPECT_EQ(IDC_CONTENT_CONTEXT_SPELLING_TOGGLE, item.command_id); + EXPECT_TRUE(item.enabled); + EXPECT_FALSE(item.checked); + EXPECT_FALSE(item.hidden); +} +#endif // defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) + // Tests that right-clicking a correct word when we enable spelling-service // integration to verify an item "Use enhanced spell check" is checked. Even -// though this meanu itself does not add this item, its sub-menu adds the item +// though this menu itself does not add this item, its sub-menu adds the item // and calls SpellingMenuObserver::IsChecked() to check it. IN_PROC_BROWSER_TEST_F(SpellingMenuObserverTest, EnableSpellingServiceWithCorrectWord) { @@ -135,7 +394,8 @@ menu()->GetPrefs()->Set(spellcheck::prefs::kSpellCheckDictionaries, dictionary); - InitMenu("wiimode", nullptr); + // Pick word that Windows platform spellcheck has no suggestions for. + InitMenu("missssspelling", nullptr); EXPECT_EQ(2U, menu()->GetMenuSize()); // To avoid duplicates, this test reads only the "Use enhanced spell check"
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/options/options.css b/chrome/browser/resources/chromeos/accessibility/chromevox/options/options.css index 7638100..30f0ce4 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/options/options.css +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/options/options.css
@@ -65,6 +65,11 @@ width: 40px; } +#developerLog { + padding: 0; + width: 686px; +} + .option .developerLog { height: 60px; padding-inline-end: 0; @@ -78,6 +83,7 @@ .option .developer-option-icon-button { height: 60px; + padding: 0 20px; } .option input[type='checkbox']:checked {
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/select_to_speak/BUILD.gn index f3ba67a97..4e7d0010 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/BUILD.gn +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/BUILD.gn
@@ -108,7 +108,7 @@ "pipe.jpg", ] extra_js_files = [ - "//chrome/test/data/webui/settings/fake_settings_private.js", + "fake_settings_private.js", "//chrome/test/data/webui/fake_chrome_event.js", ]
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/fake_settings_private.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/fake_settings_private.js new file mode 100644 index 0000000..9000116 --- /dev/null +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/fake_settings_private.js
@@ -0,0 +1,154 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview Fake implementation of chrome.settingsPrivate for testing. + * Note: This file is deprecated and is no longer maintained by the browser + * settings/WebUI team. For the updated version (JS modules only), see + * chrome/test/data/webui/settings/fake_settings_private.js. + */ +cr.define('settings', function() { + /** + * @typedef {Array<{key: string, + * type: chrome.settingsPrivate.PrefType, + * values: !Array<*>}>} + */ + let FakeSettingsPrivatePref; + + /** + * Creates a deep copy of the object. + * @param {*} obj + * @return {*} + */ + function deepCopy(obj) { + return JSON.parse(JSON.stringify(obj)); + } + + /** + * Fake of chrome.settingsPrivate API. Use by setting + * CrSettingsPrefs.deferInitialization to true, then passing a + * FakeSettingsPrivate to settings-prefs#initialize(). + * @implements {SettingsPrivate} + */ + class FakeSettingsPrivate { + /** @param {Array<!settings.FakeSettingsPrivatePref>=} opt_initialPrefs */ + constructor(opt_initialPrefs) { + this.disallowSetPref_ = false; + this.failNextSetPref_ = false; + + this.prefs = {}; + + if (!opt_initialPrefs) { + return; + } + for (const pref of opt_initialPrefs) { + this.addPref_(pref.type, pref.key, pref.value); + } + + // chrome.settingsPrivate override. + this.onPrefsChanged = /** @type {!ChromeEvent} */ (new FakeChromeEvent()); + } + + // chrome.settingsPrivate overrides. + getAllPrefs(callback) { + // Send a copy of prefs to keep our internal state private. + const prefs = []; + for (const key in this.prefs) { + prefs.push(deepCopy(this.prefs[key])); + } + + // Run the callback asynchronously to test that the prefs aren't actually + // used before they become available. + setTimeout(callback.bind(null, prefs)); + } + + setPref(key, value, pageId, callback) { + const pref = this.prefs[key]; + assertNotEquals(undefined, pref); + assertEquals(typeof value, typeof pref.value); + assertEquals(Array.isArray(value), Array.isArray(pref.value)); + + if (this.failNextSetPref_) { + callback(false); + this.failNextSetPref_ = false; + return; + } + assertNotEquals(true, this.disallowSetPref_); + + const changed = JSON.stringify(pref.value) !== JSON.stringify(value); + pref.value = deepCopy(value); + callback(true); + + // Like chrome.settingsPrivate, send a notification when prefs change. + if (changed) { + this.sendPrefChanges([{key, value}]); + } + } + + getPref(key, callback) { + const pref = this.prefs[key]; + assertNotEquals(undefined, pref); + callback( + /** @type {!chrome.settingsPrivate.PrefObject} */ (deepCopy(pref))); + } + + // Functions used by tests. + + /** Instructs the API to return a failure when setPref is next called. */ + failNextSetPref() { + this.failNextSetPref_ = true; + } + + /** Instructs the API to assert (fail the test) if setPref is called. */ + disallowSetPref() { + this.disallowSetPref_ = true; + } + + allowSetPref() { + this.disallowSetPref_ = false; + } + + /** + * Notifies the listeners of pref changes. + * @param {!Array<{key: string, value: *}>} changes + */ + sendPrefChanges(changes) { + const prefs = []; + for (const change of changes) { + const pref = this.prefs[change.key]; + assertNotEquals(undefined, pref); + pref.value = change.value; + prefs.push(deepCopy(pref)); + } + /** @type {FakeChromeEvent} */ (this.onPrefsChanged).callListeners(prefs); + } + + /** @override */ + getDefaultZoom() {} + + /** @override */ + setDefaultZoom() {} + + // Private methods for use by the fake API. + + /** + * @param {!chrome.settingsPrivate.PrefType} type + * @param {string} key + * @param {*} value + * @private + */ + addPref_(type, key, value) { + this.prefs[key] = { + type, + key, + value, + }; + } + } + + return { + FakeSettingsPrivate, + FakeSettingsPrivatePref, + }; +});
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_prefs_test.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_prefs_test.js index cbe3ad9..ef75ddd1 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_prefs_test.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_prefs_test.js
@@ -5,8 +5,7 @@ GEN_INCLUDE(['select_to_speak_e2e_test_base.js']); GEN_INCLUDE(['../../../../../../ui/webui/resources/js/cr.js']); GEN_INCLUDE(['../../../../../test/data/webui/fake_chrome_event.js']); -GEN_INCLUDE( - ['../../../../../test/data/webui/settings/fake_settings_private.js']); +GEN_INCLUDE(['fake_settings_private.js']); GEN_INCLUDE(['mock_storage.js']); /**
diff --git a/chrome/browser/resources/chromeos/login/debug/debug.js b/chrome/browser/resources/chromeos/login/debug/debug.js index 13e799f..f3eb319 100644 --- a/chrome/browser/resources/chromeos/login/debug/debug.js +++ b/chrome/browser/resources/chromeos/login/debug/debug.js
@@ -943,6 +943,9 @@ optInDefaultState: true, legalFooterVisibility: false, }, + trigger: (screen) => { + screen.updateA11ySettingsButtonVisibility(false); + }, }, { id: 'NoOptionToSubscribe', @@ -951,6 +954,9 @@ optInDefaultState: false, legalFooterVisibility: false, }, + trigger: (screen) => { + screen.updateA11ySettingsButtonVisibility(false); + }, }, { id: 'WithLegalFooter', @@ -959,6 +965,20 @@ optInDefaultState: true, legalFooterVisibility: true, }, + trigger: (screen) => { + screen.updateA11ySettingsButtonVisibility(false); + }, + }, + { + id: 'WithAceessibilityButton', + data: { + optInVisibility: true, + optInDefaultState: true, + legalFooterVisibility: true, + }, + trigger: (screen) => { + screen.updateA11ySettingsButtonVisibility(true); + }, }, ], },
diff --git a/chrome/browser/resources/chromeos/login/enterprise_enrollment.html b/chrome/browser/resources/chromeos/login/enterprise_enrollment.html index 92415ea..2ed45c93 100644 --- a/chrome/browser/resources/chromeos/login/enterprise_enrollment.html +++ b/chrome/browser/resources/chromeos/login/enterprise_enrollment.html
@@ -9,7 +9,7 @@ <link rel="import" href="/components/common_styles.html"> <link rel="import" href="/components/hd_iron_icon.html"> -<link rel="import" href="/components/oobe_dialog.html"> +<link rel="import" href="/components/oobe_adaptive_dialog.html"> <link rel="import" href="/components/oobe_i18n_behavior.html"> <link rel="import" href="/components/login_screen_behavior.html"> <link rel="import" href="/components/multi_step_behavior.html"> @@ -32,9 +32,24 @@ vertical-align: top; } + :host-context(html[new-layout]) #contentEnrolling { + display: none; + } + + :host-context(html:not([new-layout])) #subtitleEnrolling { + display: none; + } + #attributePromptMessage { color: black; } + + :host-context(html:not(html[new-layout])) .illustration { + display: none; + } + :host-context(html[new-layout]) .illustration-old { + display: none; + } </style> <!-- OAUTH GAIA DIALOG --> <gaia-dialog id="step-signin" class="flex" for-step="signin" @@ -47,19 +62,24 @@ </gaia-dialog> <!-- ENROLLMENT IN PROGRESS (SPINNER) DIALOG --> - <oobe-dialog id="step-working" for-step="working" - title-key="oauthEnrollScreenTitle"> - <hd-iron-icon slot="oobe-icon" + <oobe-adaptive-dialog id="step-working" for-step="working"> + <hd-iron-icon slot="icon" icon1x="oobe-32:enterprise" icon2x="oobe-64:enterprise"> </hd-iron-icon> + <h1 slot="title"> + [[i18nDynamic(locale, 'oauthEnrollScreenTitle')]] + </h1> + <p slot="subtitle" id="subtitleEnrolling"> + [[i18nDynamic(locale, 'oauthEnrollWorking')]] + </p> <paper-progress slot="progress" indeterminate> </paper-progress> - <div slot="footer" class="flex layout vertical" role="alert"> - <div class="step-message"> + <div slot="content" class="flex layout vertical" role="alert"> + <div class="step-message" id="contentEnrolling"> [[i18nDynamic(locale, 'oauthEnrollWorking')]] </div> </div> - </oobe-dialog> + </oobe-adaptive-dialog> <offline-ad-login-element id="step-ad-join" is-domain-join for-step="ad-join" @@ -78,14 +98,14 @@ AttributePrompt: [ 'Done' ] ActiveDirectoryJoin: [ 'Try Again' ] --> - <oobe-dialog id="step-error" has-buttons role="alert" + <oobe-adaptive-dialog id="step-error" role="alert" for-step="error, attribute-prompt-error, active-directory-join-error"> - <hd-iron-icon slot="oobe-icon" + <hd-iron-icon slot="icon" icon1x="oobe-32:warning" icon2x="oobe-64:warning"></hd-iron-icon> <h1 slot="title">[[i18nDynamic(locale, 'oauthEnrollErrorTitle')]]</h1> <div id="errorMsg" slot="subtitle">[[errorText_]]</div> - <div slot="footer" + <div slot="content" class="flex layout vertical center center-justified"> <img srcset="images/1x/error.svg 1x, images/2x/error.svg 2x" @@ -135,41 +155,53 @@ </div> </div> - </oobe-dialog> + </oobe-adaptive-dialog> <!-- SUCCESS DIALOG --> - <oobe-dialog has-buttons id="step-success" for-step="success" role="alert" - title-key="oauthEnrollSuccessTitle" footer-shrinkable> - <hd-iron-icon slot="oobe-icon" + <oobe-adaptive-dialog id="step-success" for-step="success" role="alert" + footer-shrinkable> + <hd-iron-icon slot="icon" icon1x="oobe-32:enterprise" icon2x="oobe-64:enterprise"> </hd-iron-icon> + <h1 slot="title"> + [[i18nDynamic(locale, 'oauthEnrollSuccessTitle')]] + </h1> <!-- Hide the subtitle if the domain could not be determined. --> <div hidden="[[isEmpty_(domainManager_)]]" class="self-start" slot="subtitle"> <div>[[successText_(locale, deviceName_, domainManager_)]]</div> </div> - <div slot="footer" class="flex layout vertical center end-justified"> + <div slot="content" class="flex layout vertical center center-justified"> <img srcset="images/enrollment_success_illustration_1x.png 1x, - images/enrollment_success_illustration_2x.png 2x" + images/enrollment_success_illustration_2x.png 2x" alt$="[[i18nDynamic(locale, 'enrollmentSuccessIllustrationTitle')]]" - class="oobe-illustration"> + class="oobe-illustration illustration-old"> + <img src="images/enrollment_complete.svg" + alt$="[[i18nDynamic(locale, + 'enrollmentSuccessIllustrationTitle')]]" + class="oobe-illustration illustration"> </div> - <div slot="bottom-buttons" class="layout horizontal end-justified"> + <div slot="bottom-buttons"> <oobe-text-button inverse id="successDoneButton" text-key="oauthEnrollDone" on-click="onEnrollmentFinished_" class="focus-on-show"></oobe-text-button> </div> - </oobe-dialog> + </oobe-adaptive-dialog> <!-- ATTRIBUTE PROMPT DIALOG --> - <oobe-dialog id="step-attribute-prompt" for-step="attribute-prompt" - has-buttons title-key="oauthEnrollScreenTitle" - subtitle-key="oauthEnrollDeviceInformation"> - <hd-iron-icon slot="oobe-icon" + <oobe-adaptive-dialog id="step-attribute-prompt" + for-step="attribute-prompt"> + <hd-iron-icon slot="icon" icon1x="oobe-32:enterprise" icon2x="oobe-64:enterprise"> </hd-iron-icon> - <div slot="footer" class="flex layout vertical"> + <h1 slot="title"> + [[i18nDynamic(locale, 'oauthEnrollScreenTitle')]] + </h1> + <p slot="subtitle"> + [[i18nDynamic(locale, 'oauthEnrollDeviceInformation')]] + </p> + <div slot="content" class="flex layout vertical"> <div class="step-message"> <span id="attributePromptMessage"> [[i18nDynamic(locale, 'oauthEnrollAttributeExplanation')]] @@ -189,7 +221,7 @@ </cr-input> </div> </div> - <div slot="bottom-buttons" class="layout horizontal end-justified"> + <div slot="bottom-buttons"> <oobe-text-button id="attributesSkip" text-key="oauthEnrollSkip" on-click="skipAttributes_"> </oobe-text-button> @@ -197,6 +229,6 @@ <oobe-next-button id="attributesSubmit" on-click="submitAttributes_"></oobe-next-button> </div> - </oobe-dialog> + </oobe-adaptive-dialog> </template> </dom-module>
diff --git a/chrome/browser/resources/chromeos/login/images/enrollment_complete.svg b/chrome/browser/resources/chromeos/login/images/enrollment_complete.svg new file mode 100644 index 0000000..b81833bd --- /dev/null +++ b/chrome/browser/resources/chromeos/login/images/enrollment_complete.svg
@@ -0,0 +1 @@ +<svg width="520" height="320" viewBox="0 0 520 320" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill="#fff" d="M0 0h520v320H0z"/><g clip-path="url(#clip0)"><path fill="#fff" d="M0 31.733h520v256.533H0z"/><path d="M456.855 110.011h-68.519v127.772h68.519V110.011z" stroke="#E6E7EA" stroke-width="1.733" stroke-linejoin="round"/><path d="M399.629 120.887h8.996a3.54 3.54 0 0 1 3.362 2.41 3.555 3.555 0 0 0 3.363 2.409h13.381a3.539 3.539 0 0 0 3.051-1.733l.789-1.344a3.563 3.563 0 0 1 3.059-1.733h9.923a3.552 3.552 0 0 1 3.554 3.545v14.256a3.556 3.556 0 0 1-3.554 3.545H399.62a3.546 3.546 0 0 1-3.545-3.545v-14.23a3.546 3.546 0 0 1 3.554-3.58v0zm0 27.283h8.996a3.546 3.546 0 0 1 3.363 2.418v0a3.548 3.548 0 0 0 3.362 2.409h13.382a3.557 3.557 0 0 0 3.05-1.733l.789-1.343a3.568 3.568 0 0 1 3.059-1.734h9.924a3.567 3.567 0 0 1 3.553 3.554v14.239a3.554 3.554 0 0 1-3.553 3.545H399.62a3.54 3.54 0 0 1-3.282-2.187 3.535 3.535 0 0 1-.271-1.358v-14.257a3.55 3.55 0 0 1 3.562-3.553zm0 27.291h8.996a3.541 3.541 0 0 1 3.362 2.41v0a3.547 3.547 0 0 0 3.363 2.409h13.381a3.555 3.555 0 0 0 3.051-1.733l.789-1.344a3.553 3.553 0 0 1 3.059-1.733h9.923a3.552 3.552 0 0 1 3.554 3.545v14.265a3.558 3.558 0 0 1-3.554 3.545H399.62a3.546 3.546 0 0 1-3.545-3.545v-14.274a3.557 3.557 0 0 1 1.041-2.51 3.547 3.547 0 0 1 2.513-1.035z" stroke="#E6E7EA" stroke-width="1.733" stroke-linejoin="round"/><path d="M193.596 234.906c.216-4.333 1.638-30.741 3.648-44.512 1.864-12.792 8.104-29.571 20.454-35.039 22.334-9.898 46.921 4.558 68.016 12.592" stroke="#4285F4" stroke-width="1.733" stroke-linecap="round" stroke-linejoin="round"/><path d="M399.629 202.753h8.996a3.547 3.547 0 0 1 3.362 2.409v0a3.555 3.555 0 0 0 3.363 2.409h13.381a3.54 3.54 0 0 0 3.051-1.733l.789-1.335a3.553 3.553 0 0 1 3.059-1.733h9.923a3.552 3.552 0 0 1 3.554 3.545v14.256a3.563 3.563 0 0 1-3.554 3.554H399.62a3.556 3.556 0 0 1-3.545-3.554v-14.274a3.535 3.535 0 0 1 1.041-2.509 3.541 3.541 0 0 1 2.513-1.035z" stroke="#E6E7EA" stroke-width="1.733" stroke-linejoin="round"/><path d="M430.95 131.565h-16.718v2.929h16.718v-2.929zm0 27.282h-16.718v2.93h16.718v-2.93zm0 27.292h-16.718v2.929h16.718v-2.929zm0 27.82h-16.718v2.929h16.718v-2.929z" fill="#4285F4"/><path d="M388.336 237.792v21.493h3.467l1.222-21.493m63.83 0v21.493h-3.467l-1.222-21.493" stroke="#E6E7EA" stroke-width="1.733" stroke-linejoin="round"/><path d="M78.789 259.32h386.724" stroke="#D2E3FC" stroke-width="1.733" stroke-linecap="round" stroke-linejoin="round"/><path d="M73.987 94.341L50.84 96.075a1.396 1.396 0 0 0-1.05 2.175l13 19.197a1.401 1.401 0 0 0 1.256.608 1.401 1.401 0 0 0 1.154-.782l10.149-20.938a1.395 1.395 0 0 0-1.36-1.994z" stroke="#00AC47" stroke-width="1.733" stroke-linecap="round" stroke-linejoin="round"/><path d="M82.793 176.519a21.063 21.063 0 0 1 4.61-1.266l4.949-1.352a17.185 17.185 0 0 0 10.4-8.042l2.886-5.044 1.265-2.21.113.069c.363-.492.763-.955 1.196-1.387a14.47 14.47 0 0 1 10.202-4.289 14.465 14.465 0 0 1 10.247 4.181 14.464 14.464 0 0 1 3.218 15.741 14.46 14.46 0 0 1-3.11 4.708c-.434.429-.894.832-1.378 1.205l.061.121-2.193 1.283-5.009 2.929a17.152 17.152 0 0 0-7.93 10.452l-1.309 4.966a20.563 20.563 0 0 1-1.213 4.628 20.657 20.657 0 0 1-14.957 12.645 20.657 20.657 0 0 1-24.012-14.173 20.652 20.652 0 0 1 11.99-25.174l-.026.009z" fill="#4285F4"/><path d="M97.465 130.767a7.055 7.055 0 1 0 0-14.11 7.055 7.055 0 0 0 0 14.11z" fill="#EA4335"/><path d="M123.747 138.519l-2.431 24.31a1.525 1.525 0 0 0 1.366 1.669l24.086 2.409a1.526 1.526 0 0 0 1.669-1.366l2.431-24.311a1.525 1.525 0 0 0-1.366-1.669l-24.086-2.408a1.524 1.524 0 0 0-1.669 1.366z" stroke="#D2E3FC" stroke-width="1.733" stroke-linecap="round" stroke-linejoin="round"/><path d="M327.514 188.193H287.82c-19.825 0-35.897 16.071-35.897 35.897 0 19.826 16.072 35.897 35.897 35.897h39.694c19.825 0 35.897-16.071 35.897-35.897 0-19.826-16.072-35.897-35.897-35.897z" fill="#34A853"/><path d="M299.71 155.944c6.171 13.667 7.956 32.587-8.554 39.312-6.257 2.548-13.372 2.921-20.002 1.846-12.229-1.985-23.253-8.771-34.39-13.815l-3.198 51.619h-39.97m-.035.633s-.624 11.327-.936 13.944a7.006 7.006 0 0 1-.866 2.6 4.624 4.624 0 0 1-2.869 2.011 7.425 7.425 0 0 0-2.964 1.153 7.8 7.8 0 0 0-2.236 4.064h16.319a14.97 14.97 0 0 0 13.148-7.8l1.56-2.851v10.66h7.678s1.075-10.4 2.444-23.721" stroke="#4285F4" stroke-width="1.733" stroke-linecap="round" stroke-linejoin="round"/><path d="M245.822 223.31l6.066 23.053-7.176 2.713-3.77-9.975-.45 3.224a14.996 14.996 0 0 1-3.126 7.288 14.993 14.993 0 0 1-6.408 4.672l-8.389 2.929" stroke="#4285F4" stroke-width="1.733" stroke-linecap="round" stroke-linejoin="round"/><path d="M280.263 88.933c1.846 4.81 7.739 8.164 13.52 8.104l-.72-3.38-1.577-2.748-3.259-2.435-3.406-.97-4.558 1.43z" fill="#4285F4"/><path d="M284.63 105.591a8.953 8.953 0 1 0 0-17.906 8.953 8.953 0 0 0 0 17.906zm-3.535 4.558l.658-4.558m9.152 4.688l-1.135-6.309" stroke="#4285F4" stroke-width="1.733" stroke-linecap="round" stroke-linejoin="round"/><path d="M294.883 89.358a6.678 6.678 0 0 1 6.392-4.257 6.676 6.676 0 0 1 6.166 4.578c.072-.525.203-1.04.39-1.534a6.667 6.667 0 0 1 8.667-3.796 2.402 2.402 0 0 0 3.155-1.482c.06-.174.13-.338.199-.512a6.747 6.747 0 0 1 7.523-3.822 6.642 6.642 0 0 1 1.967.763 2.296 2.296 0 0 0 3.302-1.283l1.612-4.68a5.045 5.045 0 0 1 8.45-1.794 5.032 5.032 0 0 1 1.166 4.821 5.031 5.031 0 0 1-3.532 3.482l-6.067 1.647a2.305 2.305 0 0 0-1.672 2.6 6.673 6.673 0 0 1-9.022 7.202h-.044a2.364 2.364 0 0 0-3.111 1.421l-.121.312a6.676 6.676 0 0 1-12.558-.312 6.495 6.495 0 0 1-.39 1.534 6.688 6.688 0 0 1-6.106 4.436 6.68 6.68 0 0 1-6.34-9.29l-.026-.034z" fill="#4285F4"/><path d="M278.304 164.767c3.597-2.34 5.599-6.388 6.648-10.4a248.581 248.581 0 0 0 5.598-27.491m-32.283 11.917c-6.994-6.292-17.151-14.378-24.041-15.02a18.209 18.209 0 0 0-8.736 1.638 29.729 29.729 0 0 0-12.359 9.915c-.633.867-1.127 2.305-.199 2.877.71.442 1.612-.095 2.27-.615l9.534-7.471a17.323 17.323 0 0 0-4.862 6.067 6.69 6.69 0 0 0-.798 4.455c.382 1.49 1.907 2.764 3.398 2.392" stroke="#4285F4" stroke-width="1.733" stroke-linecap="round" stroke-linejoin="round"/><path d="M299.711 155.944s.641-9.88.866-15.184c.382-9.663 2.158-19.24-4.194-26.598-5.296-6.127-14.3-6.405-20.289-1.014-7.8 7.055-9.161 20.887-10.799 32.301a194.504 194.504 0 0 0-7.02-6.656M236.6 187.031c3.467 13.962 9.429 36.998 9.429 36.998s-7.427 2.496-12.029 4.16m-18.702-77.436c-10.851 0-20.428 8.164-23.002 16.986-1.976 6.76-.979 11.718.408 18.616 1.135 5.625 1.958 10.123 3.085 15.739" stroke="#4285F4" stroke-width="1.733" stroke-linecap="round" stroke-linejoin="round"/><path d="M229.667 114.639c2.4-8.572 1.984-19.604-4.533-25.957-6.933-6.734-16.527-7.8-24.163-6.067-9.377 2.184-16.293 8.615-23.764 14.309-6.517 4.983-14.17 9.62-22.698 9.109" stroke="#D2E3FC" stroke-width="1.733" stroke-linecap="round" stroke-linejoin="round"/><path d="M246.012 150.129l11.44-11.215m-17.082 4.472l10.4-10.582M247 153.578l-10.158-15.626m62.869 17.992H284.44m15.271-5.659h-13.589" stroke="#4285F4" stroke-width="1.733" stroke-linecap="round" stroke-linejoin="round"/><path d="M201.881 115.774l5.72 34.979h33.228" stroke="#053975" stroke-width="3.467" stroke-miterlimit="10"/><mask id="a" maskUnits="userSpaceOnUse" x="251" y="188" width="113" height="72"><path d="M327.513 188.193H287.82c-19.826 0-35.898 16.071-35.898 35.897 0 19.826 16.072 35.897 35.898 35.897h39.693c19.826 0 35.897-16.071 35.897-35.897 0-19.826-16.071-35.897-35.897-35.897z" fill="#34A853"/></mask><g mask="url(#a)"><path d="M299.71 155.944c6.171 13.667 7.956 32.587-8.554 39.312-6.257 2.548-13.372 2.921-20.002 1.846-12.229-1.985-23.253-8.771-34.39-13.815l-3.198 51.619h-39.97" stroke="#fff" stroke-width="1.733" stroke-linecap="round" stroke-linejoin="round"/></g><path d="M227.067 132.379a11.647 11.647 0 0 0-4.273 9.074 3.38 3.38 0 0 0 .52 2.011 3.32 3.32 0 0 0 2.089 1.049h.19c.035 0-.104-.113-.095-.044" stroke="#4285F4" stroke-width="1.733" stroke-linecap="round" stroke-linejoin="round"/><path d="M229.814 134.537a13.428 13.428 0 0 0-3.727 5.495c-.615 1.82-1.222 5.607 1.664 5.789 1.734.113 3.207-1.317 4.212-2.6.633-.797 2.739-3.466 1.309-4.333a.862.862 0 0 0-.503-.121c-1.655 0-3.345 1.733-4.064 3.085m3.64-3.059c2.14-.338 2.764-.13 4.498-.867" stroke="#4285F4" stroke-width="1.733" stroke-linecap="round" stroke-linejoin="round"/><mask id="b" maskUnits="userSpaceOnUse" x="69" y="152" width="64" height="65"><path d="M82.793 176.519a21.063 21.063 0 0 1 4.61-1.266l4.949-1.352a17.185 17.185 0 0 0 10.4-8.042l2.886-5.044 1.265-2.21.113.069c.363-.492.763-.955 1.196-1.387a14.47 14.47 0 0 1 10.202-4.289 14.465 14.465 0 0 1 10.247 4.181 14.464 14.464 0 0 1 3.218 15.741 14.46 14.46 0 0 1-3.11 4.708c-.434.429-.894.832-1.378 1.205l.061.121-2.193 1.283-5.009 2.929a17.152 17.152 0 0 0-7.93 10.452l-1.309 4.966a20.563 20.563 0 0 1-1.213 4.628 20.657 20.657 0 0 1-14.957 12.645 20.657 20.657 0 0 1-24.012-14.173 20.652 20.652 0 0 1 11.99-25.174l-.026.009z" fill="#4285F4"/></mask><g mask="url(#b)"><path d="M123.747 138.519l-2.431 24.31a1.525 1.525 0 0 0 1.366 1.669l24.086 2.409a1.526 1.526 0 0 0 1.669-1.366l2.431-24.311a1.525 1.525 0 0 0-1.366-1.669l-24.086-2.408a1.524 1.524 0 0 0-1.669 1.366z" stroke="#FBBC05" stroke-width="1.733" stroke-linecap="round" stroke-linejoin="round"/></g><path d="M246.012 141.973a4.324 4.324 0 1 0 .001-8.649 4.324 4.324 0 0 0-.001 8.649z" fill="#fff" stroke="#4285F4" stroke-width="1.733" stroke-linecap="round" stroke-linejoin="round"/><path d="M245.761 136.418l.26 1.265 1.256.269m29.095-37.839s3.874 1.006 5.052-1.482" stroke="#4285F4" stroke-width="1.733" stroke-linecap="round" stroke-linejoin="round"/><path d="M138.155 85.233a3.329 3.329 0 0 1-.806 5.26 15.052 15.052 0 0 1-20.158-20.626 3.331 3.331 0 0 1 2.47-1.656 3.325 3.325 0 0 1 2.808.98l15.686 16.042z" fill="#FBBC05"/></g><defs><clipPath id="clip0"><path fill="#fff" transform="translate(0 31.733)" d="M0 0h520v256.533H0z"/></clipPath></defs></svg> \ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/login/marketing_opt_in.html b/chrome/browser/resources/chromeos/login/marketing_opt_in.html index 955147c..d99a281 100644 --- a/chrome/browser/resources/chromeos/login/marketing_opt_in.html +++ b/chrome/browser/resources/chromeos/login/marketing_opt_in.html
@@ -135,22 +135,19 @@ <div id="googleUrl">www.google.com</div> </div> </div> - <div slot="bottom-buttons"> - <div> - <oobe-welcome-secondary-button - hidden="[[!isA11ySettingsButtonVisible_]]" - id="marketing-opt-in-accessibility-button" - on-click="onToggleAccessibilityPage_" - icon1x="marketing-opt-in-32:accessibility" - icon2x="marketing-opt-in-64:accessibility" - text-key="marketingOptInA11yButtonLabel"> - </oobe-welcome-secondary-button> - </div> - <oobe-text-button on-click="onGetStarted_" class="focus-on-show" - inverse text-key="marketingOptInScreenAllSet" - id="marketing-opt-in-next-button"> - </oobe-text-button> - </div> + <oobe-welcome-secondary-button slot="bottom-buttons" + hidden="[[!isA11ySettingsButtonVisible_]]" + id="marketing-opt-in-accessibility-button" + on-click="onToggleAccessibilityPage_" + icon1x="marketing-opt-in-32:accessibility" + icon2x="marketing-opt-in-64:accessibility" + text-key="marketingOptInA11yButtonLabel"> + </oobe-welcome-secondary-button> + <oobe-text-button slot="bottom-buttons" + on-click="onGetStarted_" class="focus-on-show" + inverse text-key="marketingOptInScreenAllSet" + id="marketing-opt-in-next-button"> + </oobe-text-button> </oobe-adaptive-dialog> <oobe-adaptive-dialog id="finalAccessibilityPage" role="dialog"
diff --git a/chrome/browser/resources/feedback_webui/feedback_resources.grd b/chrome/browser/resources/feedback_webui/feedback_resources.grd index 70ca592..208263d8 100644 --- a/chrome/browser/resources/feedback_webui/feedback_resources.grd +++ b/chrome/browser/resources/feedback_webui/feedback_resources.grd
@@ -16,7 +16,6 @@ <include name="IDR_FEEDBACK_FEEDBACK_UTIL_JS" file="js/feedback_util.js" type="BINDATA" /> <include name="IDR_FEEDBACK_FEEDBACK_JS" file="js/feedback.js" preprocess="true" type="BINDATA" /> <include name="IDR_FEEDBACK_TAKE_SCREENSHOT_JS" file="js/take_screenshot.js" type="BINDATA" /> - <include name="IDR_FEEDBACK_TOPBAR_HANDLER_JS" file="js/topbar_handlers.js" type="BINDATA" /> <include name="IDR_FEEDBACK_FEEDBACK_CSS" file="css/feedback.css" type="BINDATA" /> <include name="IDR_FEEDBACK_BUTTON_BUTTER_BAR_CLOSE_PNG" file="images/button_butter_bar_close.png" type="BINDATA" />
diff --git a/chrome/browser/resources/feedback_webui/html/default.html b/chrome/browser/resources/feedback_webui/html/default.html index 78a9bd97..3114c032 100644 --- a/chrome/browser/resources/feedback_webui/html/default.html +++ b/chrome/browser/resources/feedback_webui/html/default.html
@@ -5,24 +5,12 @@ <meta charset="utf-8"> <link rel="stylesheet" href="chrome://resources/css/text_defaults.css"> <link rel="stylesheet" href="chrome://resources/css/apps/common.css"></link> - <link rel="stylesheet" href="chrome://resources/css/apps/topbutton_bar.css"> </link> <link rel="stylesheet" href="../css/feedback.css"> <script type="module" src="../js/feedback.js"></script> </head> <body> - <div id="title-bar" class="title-bar"> - <span id="page-title">$i18n{pageTitle}</span> - <span class="topbutton-bar"> - <button class="minimize-button" id="minimize-button" tabindex="-1" - aria-label="$i18n{minimizeBtnLabel}"> - </button> - <button class="close-button" id="close-button" tabindex="-1" - aria-label="$i18n{closeBtnLabel}"> - </button> - </span> - </div> <div id="content-pane" class="content"> <p id="free-form-text">$i18n{freeFormText}</p> <textarea id="description-text" aria-labelledby="free-form-text"
diff --git a/chrome/browser/resources/feedback_webui/js/BUILD.gn b/chrome/browser/resources/feedback_webui/js/BUILD.gn index 0800056..87599ba5 100644 --- a/chrome/browser/resources/feedback_webui/js/BUILD.gn +++ b/chrome/browser/resources/feedback_webui/js/BUILD.gn
@@ -13,7 +13,6 @@ # TODO(crbug.com/1167223): Fix and enable remaining js_library() targets. #":sys_info", - #":topbar_handlers", ] } @@ -44,7 +43,3 @@ js_library("take_screenshot") { } - -js_library("topbar_handlers") { - deps = [ "//ui/webui/resources/js:util" ] -}
diff --git a/chrome/browser/resources/feedback_webui/js/topbar_handlers.js b/chrome/browser/resources/feedback_webui/js/topbar_handlers.js deleted file mode 100644 index 1715221e..0000000 --- a/chrome/browser/resources/feedback_webui/js/topbar_handlers.js +++ /dev/null
@@ -1,36 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// TODO(crbug.com/1167223): Either port this file to work as a WebUI, or delete. - -/** - * Setup handlers for the minimize and close topbar buttons. - */ -function initializeHandlers() { - // If this dialog is using system window controls, these elements aren't - // needed at all. - if (window.feedbackInfo.useSystemWindowFrame) { - $('minimize-button').hidden = true; - $('close-button').hidden = true; - return; - } - $('minimize-button').addEventListener('click', function(e) { - e.preventDefault(); - chrome.app.window.current().minimize(); - }); - - $('minimize-button').addEventListener('mousedown', function(e) { - e.preventDefault(); - }); - - $('close-button').addEventListener('click', function() { - scheduleWindowClose(); - }); - - $('close-button').addEventListener('mousedown', function(e) { - e.preventDefault(); - }); -} - -window.addEventListener('DOMContentLoaded', initializeHandlers);
diff --git a/chrome/browser/resources/print_preview/ui/more_settings.html b/chrome/browser/resources/print_preview/ui/more_settings.html index d1bda1ab..abfc5c7 100644 --- a/chrome/browser/resources/print_preview/ui/more_settings.html +++ b/chrome/browser/resources/print_preview/ui/more_settings.html
@@ -18,8 +18,9 @@ :host cr-expand-button { flex: 1; - margin-inline-end: calc(var(--print-preview-sidebar-margin) + 6px); - margin-inline-start: var(--print-preview-sidebar-margin); + /* Padding here as cr-expand-button has a background on hover. */ + padding-inline-end: calc(var(--print-preview-sidebar-margin) + 6px); + padding-inline-start: var(--print-preview-sidebar-margin); --cr-expand-button-size: 28px; }
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/network_summary_item.js b/chrome/browser/resources/settings/chromeos/internet_page/network_summary_item.js index a6a35c6f..d2c33ba5 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/network_summary_item.js +++ b/chrome/browser/resources/settings/chromeos/internet_page/network_summary_item.js
@@ -163,9 +163,16 @@ return name ? this.i18n('networkListItemConnectingTo', name) : this.i18n('networkListItemConnecting'); } - if (networkState.type === mojom.NetworkType.kCellular && deviceState && - deviceState.scanning) { - return this.i18n('internetMobileSearching'); + if (networkState.type === mojom.NetworkType.kCellular && deviceState) { + // If there is no cellular SIM and the updated UI flag is disabled, + // simply display 'Off'. See b/162564761 for details. + if (deviceState.simAbsent && + !loadTimeData.getBoolean('updatedCellularActivationUi')) { + return this.i18n('deviceOff'); + } + if (deviceState.scanning) { + return this.i18n('internetMobileSearching'); + } } return this.i18n('networkListItemNotConnected'); },
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.gni b/chrome/browser/resources/settings/chromeos/os_settings.gni index 10f8766..4c50419 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings.gni +++ b/chrome/browser/resources/settings/chromeos/os_settings.gni
@@ -7,6 +7,39 @@ import("//ui/webui/resources/cr_elements/chromeos/os_cr_elements.gni") import("../settings.gni") +# Common namespace rewrites for all polymer_modulizer() or js_modulizer() +# targets in Settings. +settings_namespace_rewrites = [ + "Polymer.DomIf|DomIf", + "Polymer.IronResizableBehavior|IronResizableBehavior", + "settings.AboutPageBrowserProxy|AboutPageBrowserProxy", + "settings.Account|Account", + "settings.AccountManagerBrowserProxy|AccountManagerBrowserProxy", + "settings.ExtensionControlBrowserProxy|ExtensionControlBrowserProxy", + "settings.FontsBrowserProxy|FontsBrowserProxy", + "settings.LanguagesBrowserProxy|LanguagesBrowserProxy", + "settings.LifetimeBrowserProxy|LifetimeBrowserProxy", + "settings.MetricsReporting|MetricsReporting", + "settings.MinimumRoutes|MinimumRoutes", + "settings.PageStatus|PageStatus", + "Settings.PrefUtil.prefToString|prefToString", + "Settings.PrefUtil.stringToPrefValue|stringToPrefValue", + "settings.PrivacyPageBrowserProxy|PrivacyPageBrowserProxy", + "settings.ProfileInfo|ProfileInfo", + "settings.ResolverOption|ResolverOption", + "settings.Route|Route", + "settings.SearchEnginesBrowserProxy|SearchEnginesBrowserProxy", + "settings.SearchRequest|SearchRequest", + "settings.SecureDnsMode|SecureDnsMode", + "settings.SecureDnsSetting|SecureDnsSetting", + "settings.SecureDnsUiManagementMode|SecureDnsUiManagementMode", + "settings.StatusAction|StatusAction", + "settings.StoredAccount|StoredAccount", + "settings.SyncBrowserProxy|SyncBrowserProxy", + "settings.SyncPrefs|SyncPrefs", + "settings.SyncStatus|SyncStatus", +] + os_settings_namespace_rewrites = settings_namespace_rewrites + cr_components_chromeos_namespace_rewrites + cr_elements_chromeos_namespace_rewrites + [
diff --git a/chrome/browser/resources/settings/languages_page/languages.js b/chrome/browser/resources/settings/languages_page/languages.js index e6f967c..604d1f09 100644 --- a/chrome/browser/resources/settings/languages_page/languages.js +++ b/chrome/browser/resources/settings/languages_page/languages.js
@@ -579,14 +579,14 @@ const {on: spellCheckOnLanguages, off: spellCheckOffLanguages} = this.getSpellCheckLanguages_(args.supportedLanguages); - const alwaysTranslateLangauges = + const alwaysTranslateLanguages = args.alwaysTranslateCodes.map(code => this.getLanguage(code)); const model = /** @type {!LanguagesModel} */ ({ supported: args.supportedLanguages, enabled: enabledLanguageStates, translateTarget: args.translateTarget, - alwaysTranslate: alwaysTranslateLangauges, + alwaysTranslate: alwaysTranslateLanguages, spellCheckOnLanguages, spellCheckOffLanguages, });
diff --git a/chrome/browser/resources/settings/settings.gni b/chrome/browser/resources/settings/settings.gni index 001b94566..9dcf9e0 100644 --- a/chrome/browser/resources/settings/settings.gni +++ b/chrome/browser/resources/settings/settings.gni
@@ -9,36 +9,3 @@ "js_module_root=../../chrome/browser/resources/settings/", "js_module_root=./gen/chrome/browser/resources/settings/", ] - -# Common namespace rewrites for all polymer_modulizer() or js_modulizer() -# targets in Settings. -settings_namespace_rewrites = [ - "Polymer.DomIf|DomIf", - "Polymer.IronResizableBehavior|IronResizableBehavior", - "settings.AboutPageBrowserProxy|AboutPageBrowserProxy", - "settings.Account|Account", - "settings.AccountManagerBrowserProxy|AccountManagerBrowserProxy", - "settings.ExtensionControlBrowserProxy|ExtensionControlBrowserProxy", - "settings.FontsBrowserProxy|FontsBrowserProxy", - "settings.LanguagesBrowserProxy|LanguagesBrowserProxy", - "settings.LifetimeBrowserProxy|LifetimeBrowserProxy", - "settings.MetricsReporting|MetricsReporting", - "settings.MinimumRoutes|MinimumRoutes", - "settings.PageStatus|PageStatus", - "Settings.PrefUtil.prefToString|prefToString", - "Settings.PrefUtil.stringToPrefValue|stringToPrefValue", - "settings.PrivacyPageBrowserProxy|PrivacyPageBrowserProxy", - "settings.ProfileInfo|ProfileInfo", - "settings.ResolverOption|ResolverOption", - "settings.Route|Route", - "settings.SearchEnginesBrowserProxy|SearchEnginesBrowserProxy", - "settings.SearchRequest|SearchRequest", - "settings.SecureDnsMode|SecureDnsMode", - "settings.SecureDnsSetting|SecureDnsSetting", - "settings.SecureDnsUiManagementMode|SecureDnsUiManagementMode", - "settings.StatusAction|StatusAction", - "settings.StoredAccount|StoredAccount", - "settings.SyncBrowserProxy|SyncBrowserProxy", - "settings.SyncPrefs|SyncPrefs", - "settings.SyncStatus|SyncStatus", -]
diff --git a/chrome/browser/resources/settings/site_settings/site_data_details_subpage.html b/chrome/browser/resources/settings/site_settings/site_data_details_subpage.html index ed883ff..f4e8961c 100644 --- a/chrome/browser/resources/settings/site_settings/site_data_details_subpage.html +++ b/chrome/browser/resources/settings/site_settings/site_data_details_subpage.html
@@ -1,8 +1,20 @@ <style include="cr-shared-style settings-shared md-select iron-flex"> + .cr-row { + padding-inline-start: 0; + } + [first] { border-top: none; } + cr-expand-button { + padding: 0 var(--cr-section-padding); + } + + .separator { + margin-inline-start: 0; + } + .secondary, .start { max-width: 100%;
diff --git a/chrome/browser/sessions/tab_loader.cc b/chrome/browser/sessions/tab_loader.cc index 56415d6c..8e6247c 100644 --- a/chrome/browser/sessions/tab_loader.cc +++ b/chrome/browser/sessions/tab_loader.cc
@@ -13,6 +13,7 @@ #include "base/system/sys_info.h" #include "base/threading/sequenced_task_runner_handle.h" #include "base/time/default_tick_clock.h" +#include "base/trace_event/memory_pressure_level_proto.h" #include "base/trace_event/typed_macros.h" #include "build/build_config.h" #include "chrome/browser/browser_process.h" @@ -373,7 +374,7 @@ [&](perfetto::EventContext ctx) { auto* event = ctx.event<perfetto::protos::pbzero::ChromeTrackEvent>(); auto* data = event->set_chrome_memory_pressure_notification(); - data->set_level(base::MemoryPressureListener::LevelAsTraceEnum( + data->set_level(base::trace_event::MemoryPressureLevelToTraceEnum( memory_pressure_level)); });
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/long_screenshots/bitmap_generation/EntryManager.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/long_screenshots/bitmap_generation/EntryManager.java index 89c1fbeb..85cc162 100644 --- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/long_screenshots/bitmap_generation/EntryManager.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/long_screenshots/bitmap_generation/EntryManager.java
@@ -22,6 +22,7 @@ * {@link generateInitialEntry}. */ public class EntryManager { + private static final int KB_IN_BYTES = 1024; // List of all entries in correspondence of the webpage. private List<LongScreenshotsEntry> mEntries; // List of entries that are queued to generate the bitmap. Entries should only be queued @@ -30,6 +31,8 @@ private BitmapGenerator mGenerator; private @EntryStatus int mGeneratorStatus; private ScreenshotBoundsManager mBoundsManager; + private int mMemoryUsedInKb; + private int mMaxMemoryUsageInKb; /** * @param context An instance of current Android {@link Context}. @@ -43,6 +46,8 @@ mGenerator = new BitmapGenerator(tab, mBoundsManager, createBitmapGeneratorCallback()); mGenerator.captureTab(); updateGeneratorStatus(EntryStatus.CAPTURE_IN_PROGRESS); + // TODO(cb/1153969): Make this a finch param instead. + mMaxMemoryUsageInKb = 16 * 1024; } /** @@ -51,8 +56,8 @@ * generation and retrieve the bitmap. */ public LongScreenshotsEntry generateInitialEntry() { - LongScreenshotsEntry entry = - new LongScreenshotsEntry(mGenerator, mBoundsManager.getInitialEntryBounds()); + LongScreenshotsEntry entry = new LongScreenshotsEntry( + mGenerator, mBoundsManager.getInitialEntryBounds(), this::updateMemoryUsage); processEntry(entry, false); // Pre-compute these entries so that they are ready to go when the user starts scrolling. getPreviousEntry(entry.getId()); @@ -82,14 +87,19 @@ return mEntries.get(found - 1); } + // Before generating a new bitmap, make sure too much memory has not already been used. + if (mMemoryUsedInKb >= mMaxMemoryUsageInKb) { + return LongScreenshotsEntry.createEntryWithStatus(EntryStatus.INSUFFICIENT_MEMORY); + } + Rect bounds = mBoundsManager.calculateClipBoundsAbove(mEntries.get(0).getId()); if (bounds == null) { - return LongScreenshotsEntry.createEntryWithStatus( - null, bounds, EntryStatus.BOUNDS_ABOVE_CAPTURE); + return LongScreenshotsEntry.createEntryWithStatus(EntryStatus.BOUNDS_ABOVE_CAPTURE); } // found = 0 - LongScreenshotsEntry newEntry = new LongScreenshotsEntry(mGenerator, bounds); + LongScreenshotsEntry newEntry = + new LongScreenshotsEntry(mGenerator, bounds, this::updateMemoryUsage); processEntry(newEntry, true); return newEntry; } @@ -116,16 +126,21 @@ return mEntries.get(found + 1); } + // Before generating a new bitmap, make sure too much memory has not already been used. + if (mMemoryUsedInKb >= mMaxMemoryUsageInKb) { + return LongScreenshotsEntry.createEntryWithStatus(EntryStatus.INSUFFICIENT_MEMORY); + } + // found = last entry in the arraylist int newStartY = mEntries.get(mEntries.size() - 1).getEndYAxis() + 1; Rect bounds = mBoundsManager.calculateClipBoundsBelow(newStartY); if (bounds == null) { - return LongScreenshotsEntry.createEntryWithStatus( - null, bounds, EntryStatus.BOUNDS_BELOW_CAPTURE); + return LongScreenshotsEntry.createEntryWithStatus(EntryStatus.BOUNDS_BELOW_CAPTURE); } - LongScreenshotsEntry newEntry = new LongScreenshotsEntry(mGenerator, bounds); + LongScreenshotsEntry newEntry = + new LongScreenshotsEntry(mGenerator, bounds, this::updateMemoryUsage); processEntry(newEntry, false); return newEntry; } @@ -167,6 +182,10 @@ } } + private void updateMemoryUsage(int bytedUsed) { + mMemoryUsedInKb += (bytedUsed / KB_IN_BYTES); + } + /** * Creates the default BitmapGenerator to be used to retrieve the state of the generation. This * is the default implementation and should only be overridden for tests.
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/long_screenshots/bitmap_generation/LongScreenshotsEntry.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/long_screenshots/bitmap_generation/LongScreenshotsEntry.java index ea5bd61..519552c9 100644 --- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/long_screenshots/bitmap_generation/LongScreenshotsEntry.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/long_screenshots/bitmap_generation/LongScreenshotsEntry.java
@@ -10,6 +10,8 @@ import androidx.annotation.IntDef; import androidx.annotation.VisibleForTesting; +import org.chromium.base.Callback; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -33,6 +35,7 @@ // Generated bitmap private Bitmap mGeneratedBitmap; private EntryListener mEntryListener; + private Callback<Integer> mMemoryTracker; @IntDef({EntryStatus.UNKNOWN, EntryStatus.INSUFFICIENT_MEMORY, EntryStatus.GENERATION_ERROR, EntryStatus.BITMAP_GENERATED, EntryStatus.CAPTURE_COMPLETE, @@ -67,14 +70,15 @@ * @param generator BitmapGenerator to be used to capture and composite the website. * @param bounds The bounds of the entry. */ - public LongScreenshotsEntry(BitmapGenerator generator, Rect bounds) { + public LongScreenshotsEntry( + BitmapGenerator generator, Rect bounds, Callback<Integer> memoryTracker) { mRect = bounds; mGenerator = generator; + mMemoryTracker = memoryTracker; } - public static LongScreenshotsEntry createEntryWithStatus( - BitmapGenerator generator, Rect bounds, @EntryStatus int status) { - LongScreenshotsEntry entry = new LongScreenshotsEntry(generator, bounds); + static LongScreenshotsEntry createEntryWithStatus(@EntryStatus int status) { + LongScreenshotsEntry entry = new LongScreenshotsEntry(null, null, null); entry.updateStatus(status); return entry; } @@ -99,11 +103,11 @@ return mRect == null ? -1 : mRect.top; } - public int getEndYAxis() { + int getEndYAxis() { return mRect == null ? -1 : mRect.bottom; } - public void generateBitmap() { + void generateBitmap() { if (mGenerator == null) { updateStatus(EntryStatus.GENERATION_ERROR); return; @@ -136,6 +140,10 @@ private void onBitmapGenerated(Bitmap bitmap) { // TODO(tgupta): Add metrics logging here. mGeneratedBitmap = bitmap; + + if (mMemoryTracker != null && mGeneratedBitmap != null) { + mMemoryTracker.onResult(mGeneratedBitmap.getAllocationByteCount()); + } updateStatus(EntryStatus.BITMAP_GENERATED); } @@ -143,14 +151,14 @@ updateStatus(EntryStatus.GENERATION_ERROR); } - public void updateStatus(@EntryStatus int status) { + void updateStatus(@EntryStatus int status) { mCurrentStatus = status; if (mEntryListener != null) { mEntryListener.onResult(mCurrentStatus); } } - public void destroy() { + void destroy() { if (mGenerator != null) { mGenerator.destroy(); mGenerator = null;
diff --git a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/long_screenshots/bitmap_generation/LongScreenshotsEntryTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/long_screenshots/bitmap_generation/LongScreenshotsEntryTest.java index 199c5c9..23f460b 100644 --- a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/long_screenshots/bitmap_generation/LongScreenshotsEntryTest.java +++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/long_screenshots/bitmap_generation/LongScreenshotsEntryTest.java
@@ -6,6 +6,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; +import static org.junit.Assert.fail; import static org.mockito.Mockito.any; import static org.mockito.Mockito.when; @@ -109,8 +110,13 @@ public void testSuccessfulEntry() { TestBitmapGenerator testGenerator = new TestBitmapGenerator(new Rect(0, 0, 200, 1000)); - LongScreenshotsEntry entry = - new LongScreenshotsEntry(testGenerator, new Rect(0, 1000, 0, 2000)); + LongScreenshotsEntry entry = new LongScreenshotsEntry( + testGenerator, new Rect(0, 1000, 0, 2000), new Callback<Integer>() { + @Override + public void onResult(Integer result) { + assertEquals((int) result, 2097152); + } + }); TestEntryListener entryListener = new TestEntryListener(); entry.setListener(entryListener); entry.generateBitmap(); @@ -124,8 +130,13 @@ TestBitmapGenerator testGenerator = new TestBitmapGenerator(new Rect(0, 0, 200, 1000)); testGenerator.throwErrorOnComposite(); - LongScreenshotsEntry entry = - new LongScreenshotsEntry(testGenerator, new Rect(0, 1000, 0, 2000)); + LongScreenshotsEntry entry = new LongScreenshotsEntry( + testGenerator, new Rect(0, 1000, 0, 2000), new Callback<Integer>() { + @Override + public void onResult(Integer result) { + fail("MemoryUsage should not be called"); + } + }); TestEntryListener entryListener = new TestEntryListener(); entry.setListener(entryListener); entry.generateBitmap();
diff --git a/chrome/browser/sharing/click_to_call/click_to_call_context_menu_observer.cc b/chrome/browser/sharing/click_to_call/click_to_call_context_menu_observer.cc index 3189c612..4205cee 100644 --- a/chrome/browser/sharing/click_to_call/click_to_call_context_menu_observer.cc +++ b/chrome/browser/sharing/click_to_call/click_to_call_context_menu_observer.cc
@@ -11,7 +11,6 @@ #include "chrome/browser/renderer_context_menu/render_view_context_menu.h" #include "chrome/browser/sharing/click_to_call/click_to_call_metrics.h" #include "chrome/browser/sharing/click_to_call/click_to_call_ui_controller.h" -#include "chrome/browser/sharing/click_to_call/feature.h" #include "chrome/browser/sharing/sharing_constants.h" #include "chrome/grit/generated_resources.h" #include "components/sync_device_info/device_info.h"
diff --git a/chrome/browser/sharing/click_to_call/click_to_call_context_menu_observer_unittest.cc b/chrome/browser/sharing/click_to_call/click_to_call_context_menu_observer_unittest.cc index 9e91209..b71441aa 100644 --- a/chrome/browser/sharing/click_to_call/click_to_call_context_menu_observer_unittest.cc +++ b/chrome/browser/sharing/click_to_call/click_to_call_context_menu_observer_unittest.cc
@@ -16,7 +16,6 @@ #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/renderer_context_menu/mock_render_view_context_menu.h" #include "chrome/browser/sharing/click_to_call/click_to_call_utils.h" -#include "chrome/browser/sharing/click_to_call/feature.h" #include "chrome/browser/sharing/fake_device_info.h" #include "chrome/browser/sharing/features.h" #include "chrome/browser/sharing/mock_sharing_service.h"
diff --git a/chrome/browser/sharing/click_to_call/click_to_call_utils.cc b/chrome/browser/sharing/click_to_call/click_to_call_utils.cc index d805e36..f9709ab 100644 --- a/chrome/browser/sharing/click_to_call/click_to_call_utils.cc +++ b/chrome/browser/sharing/click_to_call/click_to_call_utils.cc
@@ -11,7 +11,6 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/sharing/click_to_call/feature.h" #include "chrome/browser/sharing/click_to_call/phone_number_regex.h" #include "chrome/browser/sharing/sharing_service.h" #include "chrome/browser/sharing/sharing_service_factory.h" @@ -42,7 +41,7 @@ SharingService* sharing_service = SharingServiceFactory::GetForBrowserContext(browser_context); - return sharing_service && base::FeatureList::IsEnabled(kClickToCallUI); + return sharing_service != nullptr; } } // namespace
diff --git a/chrome/browser/sharing/click_to_call/click_to_call_utils_unittest.cc b/chrome/browser/sharing/click_to_call/click_to_call_utils_unittest.cc index 88a575c..0231e3e 100644 --- a/chrome/browser/sharing/click_to_call/click_to_call_utils_unittest.cc +++ b/chrome/browser/sharing/click_to_call/click_to_call_utils_unittest.cc
@@ -7,9 +7,7 @@ #include <memory> #include "base/macros.h" -#include "base/test/scoped_feature_list.h" #include "chrome/browser/sharing/click_to_call/click_to_call_utils.h" -#include "chrome/browser/sharing/click_to_call/feature.h" #include "chrome/browser/sharing/mock_sharing_service.h" #include "chrome/browser/sharing/sharing_fcm_handler.h" #include "chrome/browser/sharing/sharing_fcm_sender.h" @@ -72,7 +70,6 @@ return create_service_ ? std::make_unique<MockSharingService>() : nullptr; } - base::test::ScopedFeatureList scoped_feature_list_; content::BrowserTaskEnvironment task_environment_; TestingProfile profile_; bool create_service_ = true; @@ -83,27 +80,18 @@ } // namespace TEST_F(ClickToCallUtilsTest, NoSharingService_DoNotOfferAnyMenu) { - scoped_feature_list_.InitAndEnableFeature(kClickToCallUI); create_service_ = false; EXPECT_FALSE(ShouldOfferClickToCallForURL(&profile_, GURL(kTelUrl))); ExpectClickToCallDisabledForSelectionText(kSelectionTextWithNumber); } -TEST_F(ClickToCallUtilsTest, UIFlagDisabled_DoNotOfferAnyMenu) { - scoped_feature_list_.InitAndDisableFeature(kClickToCallUI); - EXPECT_FALSE(ShouldOfferClickToCallForURL(&profile_, GURL(kTelUrl))); - ExpectClickToCallDisabledForSelectionText(kSelectionTextWithNumber); -} - TEST_F(ClickToCallUtilsTest, PolicyDisabled_DoNotOfferAnyMenu) { - scoped_feature_list_.InitAndEnableFeature(kClickToCallUI); profile_.GetPrefs()->SetBoolean(prefs::kClickToCallEnabled, false); EXPECT_FALSE(ShouldOfferClickToCallForURL(&profile_, GURL(kTelUrl))); ExpectClickToCallDisabledForSelectionText(kSelectionTextWithNumber); } TEST_F(ClickToCallUtilsTest, IncognitoProfile_DoNotOfferAnyMenu) { - scoped_feature_list_.InitAndEnableFeature(kClickToCallUI); EXPECT_FALSE(ShouldOfferClickToCallForURL(profile_.GetPrimaryOTRProfile(), GURL(kTelUrl))); ExpectClickToCallDisabledForSelectionText(kSelectionTextWithNumber, @@ -111,24 +99,19 @@ } TEST_F(ClickToCallUtilsTest, EmptyTelLink_DoNotOfferForLink) { - scoped_feature_list_.InitAndEnableFeature(kClickToCallUI); EXPECT_FALSE(ShouldOfferClickToCallForURL(&profile_, GURL(kEmptyTelUrl))); } TEST_F(ClickToCallUtilsTest, TelLink_OfferForLink) { - scoped_feature_list_.InitAndEnableFeature(kClickToCallUI); EXPECT_TRUE(ShouldOfferClickToCallForURL(&profile_, GURL(kTelUrl))); } TEST_F(ClickToCallUtilsTest, NonTelLink_DoNotOfferForLink) { - scoped_feature_list_.InitAndEnableFeature(kClickToCallUI); EXPECT_FALSE(ShouldOfferClickToCallForURL(&profile_, GURL(kNonTelUrl))); } TEST_F(ClickToCallUtilsTest, SelectionText_ValidPhoneNumberRegex_OfferForSelection) { - scoped_feature_list_.InitAndEnableFeature(kClickToCallUI); - // Stores a mapping of selected text to expected phone number parsed. std::map<std::string, std::string> expectations; // Selection text only consists of the phone number. @@ -164,7 +147,6 @@ TEST_F(ClickToCallUtilsTest, SelectionText_InvalidPhoneNumberRegex_DoNotOfferForSelection) { - scoped_feature_list_.InitAndEnableFeature(kClickToCallUI); std::vector<std::string> invalid_selection_texts; // Does not contain any number. @@ -187,7 +169,6 @@ } TEST_F(ClickToCallUtilsTest, SelectionText_Length) { - scoped_feature_list_.InitAndEnableFeature(kClickToCallUI); // Expect text length of 30 to pass. EXPECT_NE(base::nullopt, ExtractPhoneNumberForClickToCall( &profile_, " +1 2 3 4 5 6 7 8 9 0 1 2 3 45")); @@ -197,7 +178,6 @@ } TEST_F(ClickToCallUtilsTest, SelectionText_Digits) { - scoped_feature_list_.InitAndEnableFeature(kClickToCallUI); // Expect text with 15 digits to pass. EXPECT_NE(base::nullopt, ExtractPhoneNumberForClickToCall(&profile_, "+123456789012345"));
diff --git a/chrome/browser/sharing/click_to_call/feature.cc b/chrome/browser/sharing/click_to_call/feature.cc deleted file mode 100644 index 09bfc55..0000000 --- a/chrome/browser/sharing/click_to_call/feature.cc +++ /dev/null
@@ -1,15 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/sharing/click_to_call/feature.h" - -#if defined(OS_ANDROID) -const base::Feature kClickToCallReceiver{"ClickToCallReceiver", - base::FEATURE_ENABLED_BY_DEFAULT}; -#endif // defined(OS_ANDROID) - -#if BUILDFLAG(ENABLE_CLICK_TO_CALL) -const base::Feature kClickToCallUI{"ClickToCallUI", - base::FEATURE_ENABLED_BY_DEFAULT}; -#endif // BUILDFLAG(ENABLE_CLICK_TO_CALL)
diff --git a/chrome/browser/sharing/click_to_call/feature.h b/chrome/browser/sharing/click_to_call/feature.h deleted file mode 100644 index b9000a4..0000000 --- a/chrome/browser/sharing/click_to_call/feature.h +++ /dev/null
@@ -1,22 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_SHARING_CLICK_TO_CALL_FEATURE_H_ -#define CHROME_BROWSER_SHARING_CLICK_TO_CALL_FEATURE_H_ - -#include "base/feature_list.h" -#include "build/build_config.h" -#include "chrome/common/buildflags.h" - -#if defined(OS_ANDROID) -// Feature to allow devices to receive the click to call message. -extern const base::Feature kClickToCallReceiver; -#endif // defined(OS_ANDROID) - -#if BUILDFLAG(ENABLE_CLICK_TO_CALL) -// Feature to allow click to call gets processed on desktop. -extern const base::Feature kClickToCallUI; -#endif // BUILDFLAG(ENABLE_CLICK_TO_CALL) - -#endif // CHROME_BROWSER_SHARING_CLICK_TO_CALL_FEATURE_H_
diff --git a/chrome/browser/sharing/click_to_call/phone_number_regex.cc b/chrome/browser/sharing/click_to_call/phone_number_regex.cc index a3e8dbb..c2b06750 100644 --- a/chrome/browser/sharing/click_to_call/phone_number_regex.cc +++ b/chrome/browser/sharing/click_to_call/phone_number_regex.cc
@@ -11,7 +11,6 @@ #include "base/task/post_task.h" #include "base/task/thread_pool.h" #include "base/time/time.h" -#include "chrome/browser/sharing/click_to_call/feature.h" #include "third_party/re2/src/re2/re2.h" namespace { @@ -40,8 +39,6 @@ } void PrecompilePhoneNumberRegexesAsync() { - if (!base::FeatureList::IsEnabled(kClickToCallUI)) - return; constexpr auto kParseDelay = base::TimeDelta::FromSeconds(15); base::ThreadPool::PostDelayedTask( FROM_HERE,
diff --git a/chrome/browser/sharing/sharing_device_registration.cc b/chrome/browser/sharing/sharing_device_registration.cc index b997d47..0d13994b 100644 --- a/chrome/browser/sharing/sharing_device_registration.cc +++ b/chrome/browser/sharing/sharing_device_registration.cc
@@ -13,7 +13,6 @@ #include "base/time/time.h" #include "build/build_config.h" #include "chrome/browser/sharing/buildflags.h" -#include "chrome/browser/sharing/click_to_call/feature.h" #include "chrome/browser/sharing/shared_clipboard/feature_flags.h" #include "chrome/browser/sharing/sharing_constants.h" #include "chrome/browser/sharing/sharing_device_registration_result.h" @@ -297,8 +296,6 @@ bool SharingDeviceRegistration::IsClickToCallSupported() const { #if defined(OS_ANDROID) - if (!base::FeatureList::IsEnabled(kClickToCallReceiver)) - return false; JNIEnv* env = base::android::AttachCurrentThread(); return Java_SharingJNIBridge_isTelephonySupported(env); #endif
diff --git a/chrome/browser/sharing/sharing_handler_registry_impl.cc b/chrome/browser/sharing/sharing_handler_registry_impl.cc index 7a81cdd..4beaccb 100644 --- a/chrome/browser/sharing/sharing_handler_registry_impl.cc +++ b/chrome/browser/sharing/sharing_handler_registry_impl.cc
@@ -14,9 +14,7 @@ #include "chrome/browser/sharing/sharing_message_sender.h" #if defined(OS_ANDROID) -#include "base/feature_list.h" #include "chrome/browser/sharing/click_to_call/click_to_call_message_handler_android.h" -#include "chrome/browser/sharing/click_to_call/feature.h" #include "chrome/browser/sharing/shared_clipboard/shared_clipboard_message_handler_android.h" #include "chrome/browser/sharing/sms/sms_fetch_request_handler.h" #else @@ -43,11 +41,9 @@ #if defined(OS_ANDROID) // Note: IsClickToCallSupported() is not used as it requires JNI call. - if (base::FeatureList::IsEnabled(kClickToCallReceiver)) { - AddSharingHandler( - std::make_unique<ClickToCallMessageHandler>(), - {chrome_browser_sharing::SharingMessage::kClickToCallMessage}); - } + AddSharingHandler( + std::make_unique<ClickToCallMessageHandler>(), + {chrome_browser_sharing::SharingMessage::kClickToCallMessage}); if (sharing_device_registration->IsSmsFetcherSupported()) { AddSharingHandler(
diff --git a/chrome/browser/site_isolation/spellcheck_per_process_browsertest.cc b/chrome/browser/site_isolation/spellcheck_per_process_browsertest.cc index ea585365..b0be309 100644 --- a/chrome/browser/site_isolation/spellcheck_per_process_browsertest.cc +++ b/chrome/browser/site_isolation/spellcheck_per_process_browsertest.cc
@@ -128,13 +128,6 @@ FillSuggestionListCallback) override {} #if defined(OS_WIN) - void GetPerLanguageSuggestions( - const std::u16string& word, - GetPerLanguageSuggestionsCallback callback) override { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - std::move(callback).Run(std::vector<std::vector<std::u16string>>()); - } - void InitializeDictionaries( InitializeDictionariesCallback callback) override { if (base::FeatureList::IsEnabled(
diff --git a/chrome/browser/spellchecker/spell_check_host_chrome_impl.cc b/chrome/browser/spellchecker/spell_check_host_chrome_impl.cc index cbd20a3..8d18a702 100644 --- a/chrome/browser/spellchecker/spell_check_host_chrome_impl.cc +++ b/chrome/browser/spellchecker/spell_check_host_chrome_impl.cc
@@ -233,20 +233,6 @@ } #if defined(OS_WIN) -void SpellCheckHostChromeImpl::GetPerLanguageSuggestions( - const std::u16string& word, - GetPerLanguageSuggestionsCallback callback) { - SpellcheckService* spellcheck = GetSpellcheckService(); - - if (!spellcheck) { // Teardown. - std::move(callback).Run({}); - return; - } - - spellcheck_platform::GetPerLanguageSuggestions( - spellcheck->platform_spell_checker(), word, std::move(callback)); -} - void SpellCheckHostChromeImpl::InitializeDictionaries( InitializeDictionariesCallback callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
diff --git a/chrome/browser/spellchecker/spell_check_host_chrome_impl.h b/chrome/browser/spellchecker/spell_check_host_chrome_impl.h index 8e8e394..e2bca28 100644 --- a/chrome/browser/spellchecker/spell_check_host_chrome_impl.h +++ b/chrome/browser/spellchecker/spell_check_host_chrome_impl.h
@@ -85,10 +85,6 @@ RequestTextCheckCallback callback) override; #if defined(OS_WIN) - void GetPerLanguageSuggestions( - const std::u16string& word, - GetPerLanguageSuggestionsCallback callback) override; - void InitializeDictionaries(InitializeDictionariesCallback callback) override; #endif // defined(OS_WIN)
diff --git a/chrome/browser/spellchecker/spell_check_host_chrome_impl_win_browsertest.cc b/chrome/browser/spellchecker/spell_check_host_chrome_impl_win_browsertest.cc index fa60a93b..917c4161 100644 --- a/chrome/browser/spellchecker/spell_check_host_chrome_impl_win_browsertest.cc +++ b/chrome/browser/spellchecker/spell_check_host_chrome_impl_win_browsertest.cc
@@ -87,7 +87,6 @@ } void RunSpellCheckReturnMessageTest(); - void RunGetPerLanguageSuggestionsTest(); protected: PlatformSpellChecker* platform_spell_checker_; @@ -133,36 +132,6 @@ EXPECT_EQ(result_[0].decoration, SpellCheckResult::SPELLING); } -IN_PROC_BROWSER_TEST_F(SpellCheckHostChromeImplWinBrowserTest, - GetPerLanguageSuggestions) { - RunGetPerLanguageSuggestionsTest(); -} - -void SpellCheckHostChromeImplWinBrowserTest:: - RunGetPerLanguageSuggestionsTest() { - if (!spellcheck::WindowsVersionSupportsSpellchecker()) { - return; - } - - spellcheck_platform::SetLanguage( - platform_spell_checker_, "en-US", - base::BindOnce(&SpellCheckHostChromeImplWinBrowserTest:: - SetLanguageCompletionCallback, - base::Unretained(this))); - RunUntilResultReceived(); - - spell_check_host_->GetPerLanguageSuggestions( - base::UTF8ToUTF16("tihs"), - base::BindOnce( - &SpellCheckHostChromeImplWinBrowserTest::OnSuggestionResult, - base::Unretained(this))); - RunUntilResultReceived(); - - // Should have 1 vector of results, which should contain at least 1 suggestion - ASSERT_EQ(1U, suggestion_result_.size()); - EXPECT_GT(suggestion_result_[0].size(), 0U); -} - class SpellCheckHostChromeImplWinBrowserTestDelayInit : public SpellCheckHostChromeImplWinBrowserTest { public: @@ -202,8 +171,3 @@ SpellCheckReturnMessage) { RunSpellCheckReturnMessageTest(); } - -IN_PROC_BROWSER_TEST_F(SpellCheckHostChromeImplWinBrowserTestDelayInit, - GetPerLanguageSuggestions) { - RunGetPerLanguageSuggestionsTest(); -}
diff --git a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelFilter.java b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelFilter.java index c8e460d..62f3a13 100644 --- a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelFilter.java +++ b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelFilter.java
@@ -218,6 +218,13 @@ } @Override + public void didCloseTab(Tab tab) { + for (TabModelObserver observer : mFilteredObservers) { + observer.didCloseTab(tab); + } + } + + @Override public void didCloseTab(int tabId, boolean incognito) { for (TabModelObserver observer : mFilteredObservers) { observer.didCloseTab(tabId, incognito);
diff --git a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelObserver.java b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelObserver.java index 5cc47f8..6209a9f 100644 --- a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelObserver.java +++ b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelObserver.java
@@ -38,10 +38,20 @@ * * @param tabId The ID of the tab that was destroyed. * @param incognito True if the closed tab was incognito. + * + * @deprecated Use {@link #didCloseTab(Tab)} instead */ + @Deprecated default void didCloseTab(int tabId, boolean incognito) {} /** + * Called right after {@code tab} has been destroyed. + * + * @param tab The tab that was closed. + */ + default void didCloseTab(Tab tab) {} + + /** * Called before a tab will be added to the {@link TabModel}. * * @param tab The tab about to be added. @@ -99,6 +109,11 @@ default void multipleTabsPendingClosure(List<Tab> tabs, boolean isAllTabs) {} /** + * Called when an "all tabs" closure will happen. + */ + default void willCloseAllTabs(boolean incognito) {} + + /** * Called when an "all tabs" closure has been committed and can't be undone anymore. */ default void allTabsClosureCommitted() {}
diff --git a/chrome/browser/themes/theme_service_unittest.cc b/chrome/browser/themes/theme_service_unittest.cc index 24ad914..40ac26db 100644 --- a/chrome/browser/themes/theme_service_unittest.cc +++ b/chrome/browser/themes/theme_service_unittest.cc
@@ -29,6 +29,7 @@ #include "chrome/test/base/testing_profile_manager.h" #include "content/public/test/test_utils.h" #include "extensions/browser/extension_registry.h" +#include "extensions/browser/extension_util.h" #include "extensions/browser/test_extension_registry_observer.h" #include "extensions/browser/uninstall_reason.h" #include "extensions/common/extension.h" @@ -118,10 +119,17 @@ extensions::UnpackedInstaller::Create(service_)); extensions::TestExtensionRegistryObserver observer(registry_); installer->Load(temp_dir); - scoper.set_extension_id(observer.WaitForExtensionLoaded()->id()); + std::string extenson_id = observer.WaitForExtensionLoaded()->id(); + scoper.set_extension_id(extenson_id); waiter.WaitForThemeChanged(); + // Make sure RegisterClient calls for storage are finished to avoid flaky + // crashes in QuotaManagerImpl::RegisterClient on test shutdown. + // TODO(crbug.com/1182630) : Remove this when 1182630 is fixed. + extensions::util::GetStoragePartitionForExtensionId(extenson_id, profile()); + task_environment()->RunUntilIdle(); + return scoper; }
diff --git a/chrome/browser/translate/translate_manager_render_view_host_unittest.cc b/chrome/browser/translate/translate_manager_render_view_host_unittest.cc index 3b3b3c6..6ecc439 100644 --- a/chrome/browser/translate/translate_manager_render_view_host_unittest.cc +++ b/chrome/browser/translate/translate_manager_render_view_host_unittest.cc
@@ -493,7 +493,7 @@ }; // A list of languages to fake being returned by the translate server. -// Use only langauges for which Chrome's copy of ICU has +// Use only languages for which Chrome's copy of ICU has // display names in English locale. To save space, Chrome's copy of ICU // does not have the display name for a language unless it's in the // Accept-Language list.
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd index 28ca4bcd..771e53b 100644 --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -2304,9 +2304,6 @@ </message> <!-- Download UI --> - <message name="IDS_DOWNLOAD_NOTIFICATION_COMPLETED" desc="Download notification to be displayed when a download completes."> - Download complete - </message> <message name="IDS_DOWNLOAD_NOTIFICATION_PENDING" desc="Download notification to be displayed when a download has been scheduled but has not started being fetched from the network."> Download pending… </message>
diff --git a/chrome/browser/ui/color/tools/dump_colors.cc b/chrome/browser/ui/color/tools/dump_colors.cc index 3240d5f4..1300a93 100644 --- a/chrome/browser/ui/color/tools/dump_colors.cc +++ b/chrome/browser/ui/color/tools/dump_colors.cc
@@ -53,7 +53,7 @@ // TODO(pkasting): Use standard provider setup functions once those exist. ui::AddCoreDefaultColorMixer(provider, dark_window, high_contrast); ui::AddNativeCoreColorMixer(provider, dark_window, high_contrast); - ui::AddUiColorMixer(provider); + ui::AddUiColorMixer(provider, dark_window, high_contrast); ui::AddNativeUiColorMixer(provider, dark_window, high_contrast); #if defined(OS_MAC) // Always keep this mixer after all non-embedder ui mixers.
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc index 1334e42..5deeab8 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view.cc +++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -27,7 +27,6 @@ #include "chrome/browser/search_engines/template_url_service_factory.h" #include "chrome/browser/send_tab_to_self/send_tab_to_self_desktop_util.h" #include "chrome/browser/send_tab_to_self/send_tab_to_self_util.h" -#include "chrome/browser/sharing/click_to_call/feature.h" #include "chrome/browser/sharing/features.h" #include "chrome/browser/sharing/shared_clipboard/feature_flags.h" #include "chrome/browser/ssl/security_state_tab_helper.h" @@ -263,8 +262,7 @@ // The send tab to self icon is intentionally the first one added so it is // the left most icon. params.types_enabled.push_back(PageActionIconType::kSendTabToSelf); - if (base::FeatureList::IsEnabled(kClickToCallUI)) - params.types_enabled.push_back(PageActionIconType::kClickToCall); + params.types_enabled.push_back(PageActionIconType::kClickToCall); if (base::FeatureList::IsEnabled(kSharingQRCodeGenerator)) params.types_enabled.push_back(PageActionIconType::kQRCodeGenerator); if (base::FeatureList::IsEnabled(kSharedClipboardUI))
diff --git a/chrome/browser/ui/views/sharing/click_to_call_browsertest.cc b/chrome/browser/ui/views/sharing/click_to_call_browsertest.cc index e6fc025c..e2e4838e 100644 --- a/chrome/browser/ui/views/sharing/click_to_call_browsertest.cc +++ b/chrome/browser/ui/views/sharing/click_to_call_browsertest.cc
@@ -12,7 +12,6 @@ #include "base/strings/utf_string_conversions.h" #include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h" -#include "base/test/scoped_feature_list.h" #include "build/chromeos_buildflags.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/policy/policy_test_utils.h" @@ -20,7 +19,6 @@ #include "chrome/browser/sharing/click_to_call/click_to_call_metrics.h" #include "chrome/browser/sharing/click_to_call/click_to_call_ui_controller.h" #include "chrome/browser/sharing/click_to_call/click_to_call_utils.h" -#include "chrome/browser/sharing/click_to_call/feature.h" #include "chrome/browser/sharing/features.h" #include "chrome/browser/sharing/sharing_constants.h" #include "chrome/browser/sharing/sharing_sync_preference.h" @@ -61,10 +59,10 @@ } // namespace -// Base browser tests for the Click To Call feature. -class BaseClickToCallBrowserTest : public SharingBrowserTest { +// Browser tests for the Click To Call feature. +class ClickToCallBrowserTest : public SharingBrowserTest { public: - ~BaseClickToCallBrowserTest() override {} + ~ClickToCallBrowserTest() override = default; std::string GetTestPageURL() const override { return std::string(kTestPageURL); @@ -80,8 +78,6 @@ } protected: - base::test::ScopedFeatureList feature_list_; - std::string HistogramName(const char* suffix) { return base::StrCat({"Sharing.ClickToCall", suffix}); } @@ -92,17 +88,6 @@ } }; -// Browser tests for the Click To Call feature. -class ClickToCallBrowserTest : public BaseClickToCallBrowserTest { - public: - ClickToCallBrowserTest() { - feature_list_.InitAndEnableFeature(kClickToCallUI); - } - - protected: - base::test::ScopedFeatureList feature_list_; -}; - // TODO(himanshujaju): Add UI checks. IN_PROC_BROWSER_TEST_F(ClickToCallBrowserTest, ContextMenu_TelLink_SingleDeviceAvailable) { @@ -486,9 +471,7 @@ : public policy::PolicyTest, public testing::WithParamInterface<ClickToCallPolicy> { public: - ClickToCallPolicyTest() { - scoped_feature_list_.InitAndEnableFeature(kClickToCallUI); - } + ClickToCallPolicyTest() = default; ~ClickToCallPolicyTest() override = default; void SetUpInProcessBrowserTestFixture() override { @@ -507,9 +490,6 @@ provider_.UpdateChromePolicy(policies); } - - private: - base::test::ScopedFeatureList scoped_feature_list_; }; IN_PROC_BROWSER_TEST_P(ClickToCallPolicyTest, RunTest) {
diff --git a/chrome/browser/ui/webui/feedback/feedback_dialog.cc b/chrome/browser/ui/webui/feedback/feedback_dialog.cc index 8e7e396c8..7c9903b 100644 --- a/chrome/browser/ui/webui/feedback/feedback_dialog.cc +++ b/chrome/browser/ui/webui/feedback/feedback_dialog.cc
@@ -105,11 +105,11 @@ } bool FeedbackDialog::ShouldShowDialogTitle() const { - return false; + return true; } bool FeedbackDialog::ShouldShowCloseButton() const { - return false; + return true; } ui::WebDialogDelegate::FrameKind FeedbackDialog::GetWebDialogFrameKind() const {
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index 35453a8..3d3511e 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-master-1615982238-6d28cc0efb64698424ab4787b59036e1ccdfa770.profdata +chrome-linux-master-1616003779-9d74256b5a2600ba4439134b7ce065bd2ac4a75c.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index 8d8f31d..0e5e9432 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-master-1615982238-186e2d53eaa4069708ca74b9e7517362982e38f2.profdata +chrome-mac-master-1616003779-c43fade97bfa9228555ce027ef6b650a0ec5e85a.profdata
diff --git a/chrome/renderer/cart/commerce_hint_agent_browsertest.cc b/chrome/renderer/cart/commerce_hint_agent_browsertest.cc index 2d0dbafc..3fd8b41 100644 --- a/chrome/renderer/cart/commerce_hint_agent_browsertest.cc +++ b/chrome/renderer/cart/commerce_hint_agent_browsertest.cc
@@ -470,7 +470,8 @@ base::test::ScopedFeatureList scoped_feature_list_; }; -IN_PROC_BROWSER_TEST_F(CommerceHintCacaoTest, Rejected) { +// Flaky. crbug.com/1183852 +IN_PROC_BROWSER_TEST_F(CommerceHintCacaoTest, DISABLED_Rejected) { NavigateToURL("https://www.walmart.com/"); SendXHR("/add-to-cart", "product: 123"); WaitForCartCount(kEmptyExpected);
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index cb2cc07..b1155c7 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -3952,6 +3952,7 @@ "../browser/download/android/download_manager_service_unittest.cc", "../browser/metrics/thread_watcher_android_unittest.cc", "../browser/notifications/notification_channels_provider_android_unittest.cc", + "../browser/optimization_guide/android/optimization_guide_tab_url_provider_android_unittest.cc", "../browser/password_manager/android/password_ui_view_android_unittest.cc", "../browser/search/contextual_search_policy_handler_android_unittest.cc", "../browser/translate/android/translate_bridge_unittest.cc", @@ -4821,6 +4822,9 @@ "../browser/search/drive/drive_service_unittest.cc", "../browser/search/ntp_features_unittest.cc", "../browser/search/task_module/task_module_service_unittest.cc", + + # Android uses a different way of showing browser windows. + "../browser/optimization_guide/optimization_guide_tab_url_provider_unittest.cc", ] if (is_posix || is_fuchsia) { sources += [ "../browser/process_singleton_posix_unittest.cc" ]
diff --git a/chrome/test/base/chrome_test_launcher.cc b/chrome/test/base/chrome_test_launcher.cc index 4a3d533..c7b3a0ff 100644 --- a/chrome/test/base/chrome_test_launcher.cc +++ b/chrome/test/base/chrome_test_launcher.cc
@@ -70,10 +70,10 @@ #include "testing/gtest/include/gtest/gtest.h" #endif -int ChromeTestSuiteRunner::RunTestSuite(int argc, char** argv) { - ChromeTestSuite test_suite(argc, argv); +// static +int ChromeTestSuiteRunner::RunTestSuiteInternal(ChromeTestSuite* test_suite) { // Browser tests are expected not to tear-down various globals. - test_suite.DisableCheckForLeakedGlobals(); + test_suite->DisableCheckForLeakedGlobals(); #if defined(OS_ANDROID) // Android browser tests run child processes as threads instead. content::ContentTestSuiteBase::RegisterInProcessThreads(); @@ -85,7 +85,12 @@ InstalledVersionPoller::ScopedDisableForTesting disable_polling( InstalledVersionPoller::MakeScopedDisableForTesting()); #endif - return test_suite.Run(); + return test_suite->Run(); +} + +int ChromeTestSuiteRunner::RunTestSuite(int argc, char** argv) { + ChromeTestSuite test_suite(argc, argv); + return RunTestSuiteInternal(&test_suite); } #if defined(OS_WIN)
diff --git a/chrome/test/base/chrome_test_launcher.h b/chrome/test/base/chrome_test_launcher.h index dc62c8f..b590ada 100644 --- a/chrome/test/base/chrome_test_launcher.h +++ b/chrome/test/base/chrome_test_launcher.h
@@ -17,6 +17,8 @@ #include "chrome/app/chrome_main_delegate.h" #endif +class ChromeTestSuite; + // Allows a test suite to override the TestSuite class used. By default it is an // instance of ChromeTestSuite. class ChromeTestSuiteRunner { @@ -27,6 +29,9 @@ virtual ~ChromeTestSuiteRunner() = default; virtual int RunTestSuite(int argc, char** argv); + + protected: + static int RunTestSuiteInternal(ChromeTestSuite* test_suite); }; // Acts like normal ChromeMainDelegate but injects behaviour for browser tests.
diff --git a/chrome/test/base/interactive_ui_tests_main.cc b/chrome/test/base/interactive_ui_tests_main.cc index 35ac201..1baf140 100644 --- a/chrome/test/base/interactive_ui_tests_main.cc +++ b/chrome/test/base/interactive_ui_tests_main.cc
@@ -44,9 +44,6 @@ protected: // ChromeTestSuite overrides: void Initialize() override { - // Browser tests are expected not to tear-down various globals. - base::TestSuite::DisableCheckForLeakedGlobals(); - ChromeTestSuite::Initialize(); #if BUILDFLAG(IS_CHROMEOS_ASH) @@ -148,7 +145,8 @@ class InteractiveUITestSuiteRunner : public ChromeTestSuiteRunner { public: int RunTestSuite(int argc, char** argv) override { - return InteractiveUITestSuite(argc, argv).Run(); + InteractiveUITestSuite test_suite(argc, argv); + return RunTestSuiteInternal(&test_suite); } };
diff --git a/chrome/test/data/extensions/pinning/calendar/gmbgaklkmjakoegficnlkhebmhkjfich-google-calendar-3.1.0.crx b/chrome/test/data/extensions/pinning/calendar/gmbgaklkmjakoegficnlkhebmhkjfich-google-calendar-3.1.0.crx new file mode 100644 index 0000000..8cda685 --- /dev/null +++ b/chrome/test/data/extensions/pinning/calendar/gmbgaklkmjakoegficnlkhebmhkjfich-google-calendar-3.1.0.crx Binary files differ
diff --git a/chrome/test/data/extensions/pinning/calendar/gmbgaklkmjakoegficnlkhebmhkjfich-google-calendar-3.1.0.crx.INFO b/chrome/test/data/extensions/pinning/calendar/gmbgaklkmjakoegficnlkhebmhkjfich-google-calendar-3.1.0.crx.INFO new file mode 100644 index 0000000..80bfad9e --- /dev/null +++ b/chrome/test/data/extensions/pinning/calendar/gmbgaklkmjakoegficnlkhebmhkjfich-google-calendar-3.1.0.crx.INFO
@@ -0,0 +1,3 @@ +CRX ID = gmbgaklkmjakoegficnlkhebmhkjfich + +This crx belongs to a version "3.1.0" of Google calendar extension from the Chrome Web Store, which is older than current available version.
diff --git a/chrome/test/data/extensions/pinning/no_update_url/key.pem b/chrome/test/data/extensions/pinning/no_update_url/key.pem new file mode 100644 index 0000000..8f5e48a --- /dev/null +++ b/chrome/test/data/extensions/pinning/no_update_url/key.pem
@@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQD3DpzLha8o6vna +yibkOtQyUaz6//SxLrAdHJNl96ydosgpezEDuszc+OXXWICHA31JFvoDSUcDH0yF +JC1J1dbGn4ML3fqAMVHoyffeh0GWlq6A5LlvTm2SzzB1j6pOOLdJp61XbAaGCef7 +11Ke1IzDF/ZobVkm1oNrSz6mcfti7HguKvpMkbfllnl3oaVAZL0mr62QU4jjS7q+ +9FA0X9gs3vWzvMPMSrjfV9UC7mopfQCp7p+gt8mAGbs7yGSHtRffDkg+P2z79j0I +/Q3WOAt+0tnTrgbW7NHaX6dOVh8ZEE/fPuyqptj4bI5dZlKQu+kvD6wQAQmWq7w/ +KWr8CRnBAgMBAAECggEANDfmdC4BY8imntPzfHHiv+/7e+H1ui2AE+ciUH8VAQyS ++hGLvpoRCvOgwO932xGlvXkZxvAKDmLjLZED8YM9LiYw8KUueUHzahymQ2abOlUG +9T9i4l/VUR5xw6dl+7qJIwxJ2xx+FH6rhdNxJxkN136NGm1iVo8on9j7mPqmg7XF +LrPdhaF5PPagju4rbzzcMqf+ubeErraXVAcEfGk8qq1NbWXxJmW5vYUlRKFh9Yz2 +Y4PZ6ZKc3Qc5q3jwI49VlZ6VXgDHLRXEsQF4WU6XJKTGLopkAQf+A9eWHoBuFsnB +goHNfn9zi6Iir1sOBa6SVJ9UXz8Q35aLEK1PxwFmcQKBgQD+/o6/734D0in+ZXDD +4lZWNNW9YiLlQDNk43J4+5+AQw8B4TTlr3nQtDlP7+EI3JuJkqBCvPCOaGl5rVpe +odfFFY3TCxc8IGKc4gEfeXpcQcPIiVIx7LgGd0EqasmU48IE2hfNUwG4Rgr7Arr6 +rCGDIZCAqgeluWsEfCvQazNfLwKBgQD4CAqXxrvBHY3K4WykNLojiOAMY0zVfqnt +uTyjVlz4G+WJUkidfxUQBxCSDWKRJioPXcndMjPH2eLYKhD1oBb2lfkx6veZy71J +PWrK5rQQ6B8OkWOxz73LPg2rt+LyTuLzC5jRa6k6zxtN/E9INRiDamOTzkq0ZIuN +3GnlAHBaDwKBgFqpHQ3m05H+NgoJ/QbYQUQTMu9LpgaGRf+X0oprRDFxJjPP42PK +ePAYM8xVCFiDPxWxuSMhVBH904p8dQXyWunqmOsxJUiuZwFKZYXQRg3pH/f7wuqX +NHKwEc5H+3XhaIkbFZ1d5t2ioaLPPLWFX8DkvSDR0zg77W3BzD4k7zXnAoGAbD5O +KSiw3bmBHO4+FHdyWHmulZlseau6iyWRAhN5pUm/ZauERz+juIfswmCXCJNoPaaH +p0H2eRxstDu/hQJlox2WUCOkBPl2VRU5mu0N3mb+zsPCh2ILCTy+iJdKssacoscH +3TUn+KNT3jfjfba2SPvQEzwvPAS5JqLvj+IeJh8CgYEAqFPxVE0Fish61UNWz0Ky ++SO7SPvnqL/WHVFtnMFbeQwlhAaePFQChylySpSZSyg1qfihUISAkK3hG+nyw/5u +v4qujEw/DwdkS/6r2hmnnbFpV1xUuIwEkaaKDnuvcIUl+a6l2xp1xpgFiQSripio +5TMJhD/b3ksLZBX0qJn7XGw= +-----END PRIVATE KEY-----
diff --git a/chrome/test/data/extensions/pinning/no_update_url/key.pem.INFO b/chrome/test/data/extensions/pinning/no_update_url/key.pem.INFO new file mode 100644 index 0000000..929b731 --- /dev/null +++ b/chrome/test/data/extensions/pinning/no_update_url/key.pem.INFO
@@ -0,0 +1 @@ +This is a key used to create different versions of extension with ID fdlpamochgodkfemfnickdlkabcfmbln used in extension pinning tests.
diff --git a/chrome/test/data/extensions/pinning/no_update_url/v1/manifest.json b/chrome/test/data/extensions/pinning/no_update_url/v1/manifest.json new file mode 100644 index 0000000..0bfb06f8b --- /dev/null +++ b/chrome/test/data/extensions/pinning/no_update_url/v1/manifest.json
@@ -0,0 +1,5 @@ +{ + "name": "Test Extension", + "version": "1", + "manifest_version": 2 +}
diff --git a/chrome/test/data/extensions/pinning/no_update_url/v2/manifest.json b/chrome/test/data/extensions/pinning/no_update_url/v2/manifest.json new file mode 100644 index 0000000..8fcd80f1 --- /dev/null +++ b/chrome/test/data/extensions/pinning/no_update_url/v2/manifest.json
@@ -0,0 +1,5 @@ +{ + "name": "Test Extension", + "version": "2", + "manifest_version": 2 +}
diff --git a/chrome/test/data/extensions/pinning/update_url/key.pem b/chrome/test/data/extensions/pinning/update_url/key.pem new file mode 100644 index 0000000..8f5e48a --- /dev/null +++ b/chrome/test/data/extensions/pinning/update_url/key.pem
@@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQD3DpzLha8o6vna +yibkOtQyUaz6//SxLrAdHJNl96ydosgpezEDuszc+OXXWICHA31JFvoDSUcDH0yF +JC1J1dbGn4ML3fqAMVHoyffeh0GWlq6A5LlvTm2SzzB1j6pOOLdJp61XbAaGCef7 +11Ke1IzDF/ZobVkm1oNrSz6mcfti7HguKvpMkbfllnl3oaVAZL0mr62QU4jjS7q+ +9FA0X9gs3vWzvMPMSrjfV9UC7mopfQCp7p+gt8mAGbs7yGSHtRffDkg+P2z79j0I +/Q3WOAt+0tnTrgbW7NHaX6dOVh8ZEE/fPuyqptj4bI5dZlKQu+kvD6wQAQmWq7w/ +KWr8CRnBAgMBAAECggEANDfmdC4BY8imntPzfHHiv+/7e+H1ui2AE+ciUH8VAQyS ++hGLvpoRCvOgwO932xGlvXkZxvAKDmLjLZED8YM9LiYw8KUueUHzahymQ2abOlUG +9T9i4l/VUR5xw6dl+7qJIwxJ2xx+FH6rhdNxJxkN136NGm1iVo8on9j7mPqmg7XF +LrPdhaF5PPagju4rbzzcMqf+ubeErraXVAcEfGk8qq1NbWXxJmW5vYUlRKFh9Yz2 +Y4PZ6ZKc3Qc5q3jwI49VlZ6VXgDHLRXEsQF4WU6XJKTGLopkAQf+A9eWHoBuFsnB +goHNfn9zi6Iir1sOBa6SVJ9UXz8Q35aLEK1PxwFmcQKBgQD+/o6/734D0in+ZXDD +4lZWNNW9YiLlQDNk43J4+5+AQw8B4TTlr3nQtDlP7+EI3JuJkqBCvPCOaGl5rVpe +odfFFY3TCxc8IGKc4gEfeXpcQcPIiVIx7LgGd0EqasmU48IE2hfNUwG4Rgr7Arr6 +rCGDIZCAqgeluWsEfCvQazNfLwKBgQD4CAqXxrvBHY3K4WykNLojiOAMY0zVfqnt +uTyjVlz4G+WJUkidfxUQBxCSDWKRJioPXcndMjPH2eLYKhD1oBb2lfkx6veZy71J +PWrK5rQQ6B8OkWOxz73LPg2rt+LyTuLzC5jRa6k6zxtN/E9INRiDamOTzkq0ZIuN +3GnlAHBaDwKBgFqpHQ3m05H+NgoJ/QbYQUQTMu9LpgaGRf+X0oprRDFxJjPP42PK +ePAYM8xVCFiDPxWxuSMhVBH904p8dQXyWunqmOsxJUiuZwFKZYXQRg3pH/f7wuqX +NHKwEc5H+3XhaIkbFZ1d5t2ioaLPPLWFX8DkvSDR0zg77W3BzD4k7zXnAoGAbD5O +KSiw3bmBHO4+FHdyWHmulZlseau6iyWRAhN5pUm/ZauERz+juIfswmCXCJNoPaaH +p0H2eRxstDu/hQJlox2WUCOkBPl2VRU5mu0N3mb+zsPCh2ILCTy+iJdKssacoscH +3TUn+KNT3jfjfba2SPvQEzwvPAS5JqLvj+IeJh8CgYEAqFPxVE0Fish61UNWz0Ky ++SO7SPvnqL/WHVFtnMFbeQwlhAaePFQChylySpSZSyg1qfihUISAkK3hG+nyw/5u +v4qujEw/DwdkS/6r2hmnnbFpV1xUuIwEkaaKDnuvcIUl+a6l2xp1xpgFiQSripio +5TMJhD/b3ksLZBX0qJn7XGw= +-----END PRIVATE KEY-----
diff --git a/chrome/test/data/extensions/pinning/update_url/key.pem.INFO b/chrome/test/data/extensions/pinning/update_url/key.pem.INFO new file mode 100644 index 0000000..929b731 --- /dev/null +++ b/chrome/test/data/extensions/pinning/update_url/key.pem.INFO
@@ -0,0 +1 @@ +This is a key used to create different versions of extension with ID fdlpamochgodkfemfnickdlkabcfmbln used in extension pinning tests.
diff --git a/chrome/test/data/extensions/pinning/update_url/v1/manifest.json b/chrome/test/data/extensions/pinning/update_url/v1/manifest.json new file mode 100644 index 0000000..2fc5449 --- /dev/null +++ b/chrome/test/data/extensions/pinning/update_url/v1/manifest.json
@@ -0,0 +1,6 @@ +{ + "name": "Test Extension", + "version": "1", + "manifest_version": 2, + "update_url": "http://update.extension/pinning/update_url/update_manifest.xml" +}
diff --git a/chrome/test/data/extensions/pinning/update_url/v2/manifest.json b/chrome/test/data/extensions/pinning/update_url/v2/manifest.json new file mode 100644 index 0000000..69f24aa --- /dev/null +++ b/chrome/test/data/extensions/pinning/update_url/v2/manifest.json
@@ -0,0 +1,6 @@ +{ + "name": "Test Extension", + "version": "2", + "manifest_version": 2, + "update_url": "http://update.extension/pinning/update_url/update_manifest.xml" +}
diff --git a/chrome/test/data/optimization_guide/amp.html b/chrome/test/data/optimization_guide/amp.html new file mode 100644 index 0000000..a738133 --- /dev/null +++ b/chrome/test/data/optimization_guide/amp.html
@@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html amp> +<head> + <title>Test Page</title> + + <!-- This script is provided by the browsertest, but is intentionally slow. + This provides important time between commit and first layout for any text + dump requests to make it to the renderer, reducing flakes. --> + <script type="text/javascript" src="/slow-first-layout.js"></script> +</head> +<body> + <p>AMP</p> +</body> +</html>
diff --git a/chrome/test/data/optimization_guide/hello_world.html b/chrome/test/data/optimization_guide/hello_world.html index b46bc4a..a03c846 100644 --- a/chrome/test/data/optimization_guide/hello_world.html +++ b/chrome/test/data/optimization_guide/hello_world.html
@@ -11,6 +11,6 @@ <body> <p>hello</p> - <script async type="text/javascript" src="hello_world.js"></script> + <script async type="text/javascript" src="/slow-add-world-text.js"></script> </body> </html>
diff --git a/chrome/test/data/optimization_guide/hello_world.js b/chrome/test/data/optimization_guide/hello_world.js deleted file mode 100644 index 10492407..0000000 --- a/chrome/test/data/optimization_guide/hello_world.js +++ /dev/null
@@ -1,7 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -var p = document.createElement('p'); -p.innerHTML = 'world'; -document.body.appendChild(p);
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn index 1a14bef..ce08268 100644 --- a/chrome/test/data/webui/BUILD.gn +++ b/chrome/test/data/webui/BUILD.gn
@@ -177,15 +177,7 @@ "$root_gen_dir/chrome/test/data/webui/mock_timer.m.js", "$root_gen_dir/chrome/test/data/webui/net_internals/main_test.js", "$root_gen_dir/chrome/test/data/webui/net_internals/test_util.js", - "$root_gen_dir/chrome/test/data/webui/settings/fake_input_method_private.m.js", - "$root_gen_dir/chrome/test/data/webui/settings/fake_language_settings_private.m.js", - "$root_gen_dir/chrome/test/data/webui/settings/fake_settings_private.m.js", "$root_gen_dir/chrome/test/data/webui/settings/route_tests.js", - "$root_gen_dir/chrome/test/data/webui/settings/test_languages_browser_proxy.m.js", - "$root_gen_dir/chrome/test/data/webui/settings/test_lifetime_browser_proxy.m.js", - "$root_gen_dir/chrome/test/data/webui/settings/test_profile_info_browser_proxy.m.js", - "$root_gen_dir/chrome/test/data/webui/settings/test_search_engines_browser_proxy.m.js", - "$root_gen_dir/chrome/test/data/webui/settings/test_sync_browser_proxy.m.js", "$root_gen_dir/chrome/test/data/webui/test_browser_proxy.m.js", "$root_gen_dir/chrome/test/data/webui/test_store.m.js", "$root_gen_dir/chrome/test/data/webui/test_util.m.js", @@ -488,11 +480,13 @@ ":modulize_local", "./cr_components/chromeos:modulize", "./js:modulize", - "./settings:modulize", ] if (is_chromeos_ash) { - deps += [ "./nearby_share/shared:modulize" ] + deps += [ + "./nearby_share/shared:modulize", + "./settings/chromeos:modulize", + ] } }
diff --git a/chrome/test/data/webui/cr_components/chromeos/cellular_setup/activation_code_page_test.js b/chrome/test/data/webui/cr_components/chromeos/cellular_setup/activation_code_page_test.js index 3fe9f6c4..ee03b6a 100644 --- a/chrome/test/data/webui/cr_components/chromeos/cellular_setup/activation_code_page_test.js +++ b/chrome/test/data/webui/cr_components/chromeos/cellular_setup/activation_code_page_test.js
@@ -69,7 +69,7 @@ const startScanningButton = activationCodePage.$$('#startScanningButton'); const scanFinishContainer = activationCodePage.$$('#scanFinishContainer'); const switchCameraButton = activationCodePage.$$('#switchCameraButton'); - const tryAgainButton = activationCodePage.$$('#tryAgainButton'); + const useCameraAgainButton = activationCodePage.$$('#useCameraAgainButton'); const scanSuccessContainer = activationCodePage.$$('#scanSuccessContainer'); const scanFailureContainer = activationCodePage.$$('#scanFailureContainer'); const spinner = activationCodePage.$$('paper-spinner-lite'); @@ -81,7 +81,7 @@ assertTrue(!!startScanningButton); assertTrue(!!scanFinishContainer); assertTrue(!!switchCameraButton); - assertTrue(!!tryAgainButton); + assertTrue(!!useCameraAgainButton); assertTrue(!!scanSuccessContainer); assertTrue(!!scanFailureContainer); assertTrue(!!spinner); @@ -116,8 +116,8 @@ assertFalse(scanSuccessContainer.hidden); assertTrue(scanFailureContainer.hidden); - // Click the 'Try Again' button. - tryAgainButton.click(); + // Click the 'Use camera again' button. + useCameraAgainButton.click(); await flushAsync(); // The video should be visible and start scanning UI hidden. @@ -139,8 +139,8 @@ assertTrue(scanFailureContainer.hidden); assertFalse(activationCodePage.showError); - // Click the 'Try Again' button. - tryAgainButton.click(); + // Click the 'Use camera again' button. + useCameraAgainButton.click(); await flushAsync(); // The video should be visible and start scanning UI hidden. @@ -328,4 +328,53 @@ assertFalse(startScanningContainer.hidden); assertTrue(scanFinishContainer.hidden); }); + + test( + 'Install error after scanning should show error on camera', + async function() { + await flushAsync(); + const input = activationCodePage.$$('#activationCode'); + const startScanningContainer = + activationCodePage.$$('#startScanningContainer'); + const startScanningButton = + activationCodePage.$$('#startScanningButton'); + const scanFinishContainer = + activationCodePage.$$('#scanFinishContainer'); + const scanInstallFailureHeader = + activationCodePage.$$('#scanInstallFailureHeader'); + const scanSucessHeader = activationCodePage.$$('#scanSucessHeader'); + assertTrue(!!input); + assertTrue(!!startScanningContainer); + assertTrue(!!startScanningButton); + assertTrue(!!scanFinishContainer); + assertTrue(!!scanInstallFailureHeader); + assertTrue(!!scanSucessHeader); + assertFalse(input.invalid); + + // Click the start scanning button. + startScanningButton.click(); + await flushAsync(); + + // Mock camera scanning a code. + await intervalFunction(); + await flushAsync(); + + // The code detected UI should be showing. + assertTrue(startScanningContainer.hidden); + assertFalse(scanFinishContainer.hidden); + assertFalse(scanSucessHeader.hidden); + assertTrue(scanInstallFailureHeader.hidden); + + // Mock an install error. + activationCodePage.showError = true; + + // The scan install failure UI should be showing. + assertTrue(startScanningContainer.hidden); + assertFalse(scanFinishContainer.hidden); + assertTrue(scanSucessHeader.hidden); + assertFalse(scanInstallFailureHeader.hidden); + + // There should be no error displayed on the input. + assertFalse(input.invalid); + }); });
diff --git a/chrome/test/data/webui/settings/BUILD.gn b/chrome/test/data/webui/settings/BUILD.gn index 13c4cbe..debccaf 100644 --- a/chrome/test/data/webui/settings/BUILD.gn +++ b/chrome/test/data/webui/settings/BUILD.gn
@@ -15,51 +15,6 @@ in_files = [ "route_tests.js" ] } -group("modulize") { - public_deps = [ ":modulize_local" ] - - if (is_chromeos_ash) { - deps = [ "./chromeos:modulize" ] - } -} - -js_modulizer("modulize_local") { - input_files = [ - "fake_input_method_private.js", - "fake_language_settings_private.js", - "fake_settings_private.js", - "test_languages_browser_proxy.js", - "test_lifetime_browser_proxy.js", - "test_profile_info_browser_proxy.js", - "test_search_engines_browser_proxy.js", - "test_sync_browser_proxy.js", - ] - - namespace_rewrites = settings_namespace_rewrites + test_namespace_rewrites + [ - "export_passwords_tests.run|run", - "settings.buildRouterForTesting|buildRouter", - "settings.defaultSettingLabel|defaultSettingLabel", - "settings.FakeLanguageSettingsPrivate|FakeLanguageSettingsPrivate", - "settings.FakeInputMethodPrivate|FakeInputMethodPrivate", - "settings.FakeSettingsPrivate|FakeSettingsPrivate", - "settings.getFakeLanguagePrefs|getFakeLanguagePrefs", - "settings.kMenuCloseDelay|kMenuCloseDelay", - "settings.setLanguageSettingsPrivateApiForTest|setLanguageSettingsPrivateApiForTest", - "settings.setPageVisibilityForTesting|setPageVisibilityForTesting", - "settings.setSearchManagerForTesting|setSearchManagerForTesting", - "settings.TestLanguagesBrowserProxy|TestLanguagesBrowserProxy", - "settings.TestLifetimeBrowserProxy|TestLifetimeBrowserProxy", - "settings_page_test_util.getPage|getPage", - "settings_page_test_util.getSection|getSection", - "settings_search.createSampleSearchEngine|createSampleSearchEngine", - "settings_search.TestSearchEnginesBrowserProxy|TestSearchEnginesBrowserProxy", - "sync_test_util.getSyncAllPrefs|getSyncAllPrefs", - "sync_test_util.setupRouterWithSyncRoutes|setupRouterWithSyncRoutes", - "sync_test_util.simulateSyncStatus|simulateSyncStatus", - "sync_test_util.simulateStoredAccounts|simulateStoredAccounts", - ] -} - js_type_check("closure_compile") { is_polymer3 = true closure_flags = settings_closure_flags + [ @@ -100,9 +55,9 @@ #":edit_dictionary_page_test", #":ensure_lazy_loaded", #":extension_controlled_indicator_tests", - ":fake_input_method_private.m", - ":fake_language_settings_private.m", - ":fake_settings_private.m", + ":fake_input_method_private", + ":fake_language_settings_private", + ":fake_settings_private", #":help_page_v3_test", #":idle_load_tests", @@ -192,9 +147,9 @@ #":test_extension_control_browser_proxy", ":test_hats_browser_proxy", - ":test_languages_browser_proxy.m", + ":test_languages_browser_proxy", ":test_languages_metrics_proxy", - ":test_lifetime_browser_proxy.m", + ":test_lifetime_browser_proxy", ":test_local_data_browser_proxy", ":test_metrics_browser_proxy", ":test_open_window_proxy", @@ -203,9 +158,9 @@ #":test_profile_info_browser_proxy", #":test_reset_browser_proxy", - ":test_search_engines_browser_proxy.m", + ":test_search_engines_browser_proxy", ":test_site_settings_prefs_browser_proxy", - ":test_sync_browser_proxy.m", + ":test_sync_browser_proxy", ":test_util", #":zoom_levels_tests", @@ -215,7 +170,7 @@ js_library("about_page_tests") { deps = [ ":test_about_page_browser_proxy", - ":test_lifetime_browser_proxy.m", + ":test_lifetime_browser_proxy", "..:chai_assert", "//chrome/browser/resources/settings:settings", "//ui/webui/resources/js:load_time_data.m", @@ -267,38 +222,30 @@ externs_list = [ "$externs_path/mocha-2.5.js" ] } -js_library("fake_language_settings_private.m") { - sources = [ "$root_gen_dir/chrome/test/data/webui/settings/fake_language_settings_private.m.js" ] +js_library("fake_language_settings_private") { deps = [ "..:chai_assert", "..:fake_chrome_event.m", "..:test_browser_proxy.m", "//ui/webui/resources/js:cr.m", ] - extra_deps = [ ":modulize_local" ] } -js_library("fake_input_method_private.m") { - sources = [ "$root_gen_dir/chrome/test/data/webui/settings/fake_input_method_private.m.js" ] - extra_deps = [ ":modulize_local" ] +js_library("fake_input_method_private") { } -js_library("fake_settings_private.m") { - sources = [ - "$root_gen_dir/chrome/test/data/webui/settings/fake_settings_private.m.js", - ] +js_library("fake_settings_private") { deps = [ "..:chai_assert", "..:fake_chrome_event.m", ] - extra_deps = [ ":modulize_local" ] } js_library("languages_page_metrics_test_cros") { deps = [ - ":fake_language_settings_private.m", - ":fake_settings_private.m", - ":test_languages_browser_proxy.m", + ":fake_language_settings_private", + ":fake_settings_private", + ":test_languages_browser_proxy", ":test_languages_metrics_proxy", "..:chai_assert", "..:test_util.m", @@ -310,9 +257,9 @@ js_library("languages_page_metrics_test_browser") { deps = [ - ":fake_language_settings_private.m", - ":fake_settings_private.m", - ":test_languages_browser_proxy.m", + ":fake_language_settings_private", + ":fake_settings_private", + ":test_languages_browser_proxy", "..:chai_assert", "..:test_util.m", "//chrome/browser/resources/settings:lazy_load", @@ -341,7 +288,7 @@ ":test_metrics_browser_proxy", ":test_privacy_page_browser_proxy", ":test_site_settings_prefs_browser_proxy", - ":test_sync_browser_proxy.m", + ":test_sync_browser_proxy", "..:chai_assert", "..:test_util.m", "//chrome/browser/resources/settings:lazy_load", @@ -391,7 +338,7 @@ js_library("safety_check_page_test") { deps = [ ":test_hats_browser_proxy", - ":test_lifetime_browser_proxy.m", + ":test_lifetime_browser_proxy", ":test_metrics_browser_proxy", ":test_open_window_proxy", ":test_password_manager_proxy", @@ -436,7 +383,7 @@ js_library("search_page_test") { deps = [ - ":test_search_engines_browser_proxy.m", + ":test_search_engines_browser_proxy", "..:chai_assert", "//chrome/browser/resources/settings:settings", ] @@ -467,7 +414,7 @@ deps = [ ":test_metrics_browser_proxy", ":test_privacy_page_browser_proxy", - ":test_sync_browser_proxy.m", + ":test_sync_browser_proxy", "..:chai_assert", "..:test_util.m", "//chrome/browser/resources/settings:lazy_load", @@ -522,7 +469,6 @@ "//chrome/browser/resources/settings:settings", "//ui/webui/resources/js:cr.m", ] - extra_deps = [ ":modulize_local" ] } js_library("test_clear_browsing_data_browser_proxy") { @@ -540,16 +486,14 @@ ] } -js_library("test_languages_browser_proxy.m") { - sources = [ "$root_gen_dir/chrome/test/data/webui/settings/test_languages_browser_proxy.m.js" ] +js_library("test_languages_browser_proxy") { deps = [ - ":fake_input_method_private.m", - ":fake_language_settings_private.m", + ":fake_input_method_private", + ":fake_language_settings_private", "..:test_browser_proxy.m", "//chrome/browser/resources/settings:lazy_load", "//ui/webui/resources/js:cr.m", ] - extra_deps = [ ":modulize_local" ] } js_library("test_languages_metrics_proxy") { @@ -559,13 +503,11 @@ ] } -js_library("test_lifetime_browser_proxy.m") { - sources = [ "$root_gen_dir/chrome/test/data/webui/settings/test_lifetime_browser_proxy.m.js" ] +js_library("test_lifetime_browser_proxy") { deps = [ "..:test_browser_proxy.m", "//chrome/browser/resources/settings:settings", ] - extra_deps = [ ":modulize_local" ] } js_library("test_local_data_browser_proxy") { @@ -575,13 +517,11 @@ ] } -js_library("test_search_engines_browser_proxy.m") { - sources = [ "$root_gen_dir/chrome/test/data/webui/settings/test_search_engines_browser_proxy.m.js" ] +js_library("test_search_engines_browser_proxy") { deps = [ "..:test_browser_proxy.m", "//chrome/browser/resources/settings:settings", ] - extra_deps = [ ":modulize_local" ] } js_library("test_site_settings_prefs_browser_proxy") { @@ -592,13 +532,11 @@ ] } -js_library("test_sync_browser_proxy.m") { - sources = [ "$root_gen_dir/chrome/test/data/webui/settings/test_sync_browser_proxy.m.js" ] +js_library("test_sync_browser_proxy") { deps = [ "..:test_browser_proxy.m", "//chrome/browser/resources/settings:settings", ] - extra_deps = [ ":modulize" ] } js_library("test_util") {
diff --git a/chrome/test/data/webui/settings/a11y/edit_dictionary_a11y_v3_test.js b/chrome/test/data/webui/settings/a11y/edit_dictionary_a11y_v3_test.js index a4fb5f0d..aed50af 100644 --- a/chrome/test/data/webui/settings/a11y/edit_dictionary_a11y_v3_test.js +++ b/chrome/test/data/webui/settings/a11y/edit_dictionary_a11y_v3_test.js
@@ -5,8 +5,8 @@ import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {LanguagesBrowserProxyImpl} from 'chrome://settings/lazy_load.js'; import {Router, routes} from 'chrome://settings/settings.js'; -import {FakeLanguageSettingsPrivate} from 'chrome://test/settings/fake_language_settings_private.m.js'; -import {TestLanguagesBrowserProxy} from 'chrome://test/settings/test_languages_browser_proxy.m.js'; +import {FakeLanguageSettingsPrivate} from 'chrome://test/settings/fake_language_settings_private.js'; +import {TestLanguagesBrowserProxy} from 'chrome://test/settings/test_languages_browser_proxy.js'; import {flushTasks} from 'chrome://test/test_util.m.js'; const fakeLanguageSettingsPrivate = new FakeLanguageSettingsPrivate();
diff --git a/chrome/test/data/webui/settings/a11y/sign_out_a11y_v3_test.js b/chrome/test/data/webui/settings/a11y/sign_out_a11y_v3_test.js index 6a8a9fd..0f50bf6 100644 --- a/chrome/test/data/webui/settings/a11y/sign_out_a11y_v3_test.js +++ b/chrome/test/data/webui/settings/a11y/sign_out_a11y_v3_test.js
@@ -7,7 +7,7 @@ import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {routes, StatusAction, SyncBrowserProxyImpl} from 'chrome://settings/settings.js'; import {simulateSyncStatus} from 'chrome://test/settings/sync_test_util.js'; -import {TestSyncBrowserProxy} from 'chrome://test/settings/test_sync_browser_proxy.m.js'; +import {TestSyncBrowserProxy} from 'chrome://test/settings/test_sync_browser_proxy.js'; import {waitBeforeNextRender} from 'chrome://test/test_util.m.js'; // Set the URL of the page to render to load the correct view upon
diff --git a/chrome/test/data/webui/settings/about_page_tests.js b/chrome/test/data/webui/settings/about_page_tests.js index 69fbf72..b3eea21 100644 --- a/chrome/test/data/webui/settings/about_page_tests.js +++ b/chrome/test/data/webui/settings/about_page_tests.js
@@ -11,7 +11,7 @@ import {assertEquals, assertFalse, assertNotEquals, assertTrue} from '../chai_assert.js'; import {TestAboutPageBrowserProxy} from './test_about_page_browser_proxy.js'; -import {TestLifetimeBrowserProxy} from './test_lifetime_browser_proxy.m.js'; +import {TestLifetimeBrowserProxy} from './test_lifetime_browser_proxy.js'; // clang-format on
diff --git a/chrome/test/data/webui/settings/autofill_page_test.js b/chrome/test/data/webui/settings/autofill_page_test.js index 853eeea..7c8b740 100644 --- a/chrome/test/data/webui/settings/autofill_page_test.js +++ b/chrome/test/data/webui/settings/autofill_page_test.js
@@ -6,7 +6,7 @@ import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {AutofillManagerImpl, PaymentsManagerImpl} from 'chrome://settings/lazy_load.js'; import {CrSettingsPrefs, MultiStoreExceptionEntry, MultiStorePasswordUiEntry, OpenWindowProxyImpl, PasswordManagerImpl, Router, routes, SettingsPluralStringProxyImpl} from 'chrome://settings/settings.js'; -import {FakeSettingsPrivate} from 'chrome://test/settings/fake_settings_private.m.js'; +import {FakeSettingsPrivate} from 'chrome://test/settings/fake_settings_private.js'; import {AutofillManagerExpectations, createAddressEntry, createCreditCardEntry, createExceptionEntry, createPasswordEntry, PaymentsManagerExpectations, TestAutofillManager, TestPaymentsManager} from 'chrome://test/settings/passwords_and_autofill_fake_data.js'; import {makeCompromisedCredential} from 'chrome://test/settings/passwords_and_autofill_fake_data.js'; import {TestOpenWindowProxy} from 'chrome://test/settings/test_open_window_proxy.js';
diff --git a/chrome/test/data/webui/settings/avatar_icon_test.js b/chrome/test/data/webui/settings/avatar_icon_test.js index ae446cc2..0069273 100644 --- a/chrome/test/data/webui/settings/avatar_icon_test.js +++ b/chrome/test/data/webui/settings/avatar_icon_test.js
@@ -7,7 +7,7 @@ import 'chrome://settings/lazy_load.js'; import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {SyncBrowserProxy, SyncBrowserProxyImpl} from 'chrome://settings/settings.js'; -import {TestSyncBrowserProxy} from 'chrome://test/settings/test_sync_browser_proxy.m.js'; +import {TestSyncBrowserProxy} from 'chrome://test/settings/test_sync_browser_proxy.js'; suite('AvatarIcon', function() { /** @type {SyncBrowserProxy} */
diff --git a/chrome/test/data/webui/settings/chromeos/input_method_options_page_test.js b/chrome/test/data/webui/settings/chromeos/input_method_options_page_test.js index be03119..7fdfb7e 100644 --- a/chrome/test/data/webui/settings/chromeos/input_method_options_page_test.js +++ b/chrome/test/data/webui/settings/chromeos/input_method_options_page_test.js
@@ -6,7 +6,7 @@ // #import 'chrome://os-settings/chromeos/lazy_load.js'; // #import {CrSettingsPrefs, Router, routes} from 'chrome://os-settings/chromeos/os_settings.js'; // #import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -// #import {FakeSettingsPrivate} from '../fake_settings_private.m.js'; +// #import {FakeSettingsPrivate} from '../fake_settings_private.js'; // #import {waitAfterNextRender} from '../../test_util.m.js'; // clang-format on
diff --git a/chrome/test/data/webui/settings/chromeos/input_page_test.js b/chrome/test/data/webui/settings/chromeos/input_page_test.js index 31ca7d04..21fb1e0 100644 --- a/chrome/test/data/webui/settings/chromeos/input_page_test.js +++ b/chrome/test/data/webui/settings/chromeos/input_page_test.js
@@ -7,8 +7,8 @@ // #import {CrSettingsPrefs, Router, routes} from 'chrome://os-settings/chromeos/os_settings.js'; // #import {keyDownOn} from 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js'; // #import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -// #import {getFakeLanguagePrefs} from '../fake_language_settings_private.m.js' -// #import {FakeSettingsPrivate} from '../fake_settings_private.m.js'; +// #import {getFakeLanguagePrefs} from '../fake_language_settings_private.js' +// #import {FakeSettingsPrivate} from '../fake_settings_private.js'; // #import {TestLanguagesBrowserProxy} from './test_os_languages_browser_proxy.m.js'; // #import {TestLanguagesMetricsProxy} from './test_os_languages_metrics_proxy.m.js'; // #import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
diff --git a/chrome/test/data/webui/settings/chromeos/os_edit_dictionary_page_test.js b/chrome/test/data/webui/settings/chromeos/os_edit_dictionary_page_test.js index 64bac97..1c7e215 100644 --- a/chrome/test/data/webui/settings/chromeos/os_edit_dictionary_page_test.js +++ b/chrome/test/data/webui/settings/chromeos/os_edit_dictionary_page_test.js
@@ -6,8 +6,8 @@ // #import {LanguagesBrowserProxyImpl} from 'chrome://os-settings/chromeos/lazy_load.js'; // #import {CrSettingsPrefs} from 'chrome://os-settings/chromeos/os_settings.js'; // #import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -// #import {FakeLanguageSettingsPrivate} from '../fake_language_settings_private.m.js'; -// #import {FakeSettingsPrivate} from '../fake_settings_private.m.js'; +// #import {FakeLanguageSettingsPrivate} from '../fake_language_settings_private.js'; +// #import {FakeSettingsPrivate} from '../fake_settings_private.js'; // #import {TestLanguagesBrowserProxy} from './test_os_languages_browser_proxy.m.js'; // clang-format on
diff --git a/chrome/test/data/webui/settings/chromeos/os_languages_page_tests.js b/chrome/test/data/webui/settings/chromeos/os_languages_page_tests.js index f2a6ba84..b2fba58 100644 --- a/chrome/test/data/webui/settings/chromeos/os_languages_page_tests.js +++ b/chrome/test/data/webui/settings/chromeos/os_languages_page_tests.js
@@ -7,8 +7,8 @@ // #import {CrSettingsPrefs, Router, routes} from 'chrome://os-settings/chromeos/os_settings.js'; // #import {assert} from 'chrome://resources/js/assert.m.js'; // #import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -// #import {getFakeLanguagePrefs} from '../fake_language_settings_private.m.js' -// #import {FakeSettingsPrivate} from '../fake_settings_private.m.js'; +// #import {getFakeLanguagePrefs} from '../fake_language_settings_private.js' +// #import {FakeSettingsPrivate} from '../fake_settings_private.js'; // #import {TestLanguagesBrowserProxy} from './test_os_languages_browser_proxy.m.js'; // #import {TestLanguagesMetricsProxy} from './test_os_languages_metrics_proxy.m.js'; // #import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
diff --git a/chrome/test/data/webui/settings/chromeos/os_languages_page_v2_tests.js b/chrome/test/data/webui/settings/chromeos/os_languages_page_v2_tests.js index 91c787f1..f4bbb01 100644 --- a/chrome/test/data/webui/settings/chromeos/os_languages_page_v2_tests.js +++ b/chrome/test/data/webui/settings/chromeos/os_languages_page_v2_tests.js
@@ -8,8 +8,8 @@ // #import {assert} from 'chrome://resources/js/assert.m.js'; // #import {keyDownOn} from 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js'; // #import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -// #import {getFakeLanguagePrefs} from '../fake_language_settings_private.m.js' -// #import {FakeSettingsPrivate} from '../fake_settings_private.m.js'; +// #import {getFakeLanguagePrefs} from '../fake_language_settings_private.js' +// #import {FakeSettingsPrivate} from '../fake_settings_private.js'; // #import {TestLanguagesBrowserProxy} from './test_os_languages_browser_proxy.m.js'; // #import {TestLanguagesMetricsProxy} from './test_os_languages_metrics_proxy.m.js'; // #import {TestLifetimeBrowserProxy} from './test_os_lifetime_browser_proxy.m.js';
diff --git a/chrome/test/data/webui/settings/chromeos/os_people_page_test.js b/chrome/test/data/webui/settings/chromeos/os_people_page_test.js index 5798b6d..3a68cae 100644 --- a/chrome/test/data/webui/settings/chromeos/os_people_page_test.js +++ b/chrome/test/data/webui/settings/chromeos/os_people_page_test.js
@@ -10,7 +10,7 @@ // #import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js'; // #import {assert} from 'chrome://resources/js/assert.m.js'; // #import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -// #import {TestProfileInfoBrowserProxy} from 'chrome://test/settings/test_profile_info_browser_proxy.m.js'; +// #import {TestProfileInfoBrowserProxy} from 'chrome://test/settings/test_profile_info_browser_proxy.js'; // #import {TestSyncBrowserProxy} from './test_os_sync_browser_proxy.m.js'; // #import {FakeQuickUnlockPrivate} from './fake_quick_unlock_private.m.js'; // #import {webUIListenerCallback} from 'chrome://resources/js/cr.m.js';
diff --git a/chrome/test/data/webui/settings/chromeos/quick_unlock_authenticate_browsertest_chromeos.js b/chrome/test/data/webui/settings/chromeos/quick_unlock_authenticate_browsertest_chromeos.js index 3598effc..c68702d 100644 --- a/chrome/test/data/webui/settings/chromeos/quick_unlock_authenticate_browsertest_chromeos.js +++ b/chrome/test/data/webui/settings/chromeos/quick_unlock_authenticate_browsertest_chromeos.js
@@ -11,7 +11,7 @@ // #import {FakeQuickUnlockPrivate} from './fake_quick_unlock_private.m.js'; // #import {FakeQuickUnlockUma} from './fake_quick_unlock_uma.m.js'; // #import {LockScreenProgress} from 'chrome://resources/cr_components/chromeos/quick_unlock/lock_screen_constants.m.js'; -// #import {FakeSettingsPrivate} from 'chrome://test/settings/fake_settings_private.m.js'; +// #import {FakeSettingsPrivate} from 'chrome://test/settings/fake_settings_private.js'; // #import {CrSettingsPrefs, Router, routes} from 'chrome://os-settings/chromeos/os_settings.js'; // #import {getDeepActiveElement} from 'chrome://resources/js/util.m.js'; // #import {eventToPromise, waitAfterNextRender, waitBeforeNextRender} from '../../../test_util.m.js';
diff --git a/chrome/test/data/webui/settings/chromeos/test_os_languages_browser_proxy.js b/chrome/test/data/webui/settings/chromeos/test_os_languages_browser_proxy.js index 54f6265..578ed93 100644 --- a/chrome/test/data/webui/settings/chromeos/test_os_languages_browser_proxy.js +++ b/chrome/test/data/webui/settings/chromeos/test_os_languages_browser_proxy.js
@@ -4,8 +4,8 @@ // clang-format off // #import {LanguagesBrowserProxy} from 'chrome://os-settings/chromeos/lazy_load.js'; -// #import {FakeInputMethodPrivate} from '../fake_input_method_private.m.js'; -// #import {FakeLanguageSettingsPrivate} from '../fake_language_settings_private.m.js'; +// #import {FakeInputMethodPrivate} from '../fake_input_method_private.js'; +// #import {FakeLanguageSettingsPrivate} from '../fake_language_settings_private.js'; // #import {TestBrowserProxy} from '../../test_browser_proxy.m.js'; // clang-format on
diff --git a/chrome/test/data/webui/settings/clear_browsing_data_test.js b/chrome/test/data/webui/settings/clear_browsing_data_test.js index 0feb7ae9..61b1f81 100644 --- a/chrome/test/data/webui/settings/clear_browsing_data_test.js +++ b/chrome/test/data/webui/settings/clear_browsing_data_test.js
@@ -10,7 +10,7 @@ import {ClearBrowsingDataBrowserProxyImpl} from 'chrome://settings/lazy_load.js'; import {Router, routes, StatusAction, SyncBrowserProxyImpl} from 'chrome://settings/settings.js'; import {TestClearBrowsingDataBrowserProxy} from 'chrome://test/settings/test_clear_browsing_data_browser_proxy.js'; -import {TestSyncBrowserProxy} from 'chrome://test/settings/test_sync_browser_proxy.m.js'; +import {TestSyncBrowserProxy} from 'chrome://test/settings/test_sync_browser_proxy.js'; import {eventToPromise, isChildVisible, isVisible, whenAttributeIs} from 'chrome://test/test_util.m.js'; // clang-format on
diff --git a/chrome/test/data/webui/settings/edit_dictionary_page_test.js b/chrome/test/data/webui/settings/edit_dictionary_page_test.js index d5c138e..a9f6c312cf 100644 --- a/chrome/test/data/webui/settings/edit_dictionary_page_test.js +++ b/chrome/test/data/webui/settings/edit_dictionary_page_test.js
@@ -7,9 +7,9 @@ import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {LanguagesBrowserProxyImpl} from 'chrome://settings/lazy_load.js'; import {CrSettingsPrefs} from 'chrome://settings/settings.js'; -import {FakeLanguageSettingsPrivate} from 'chrome://test/settings/fake_language_settings_private.m.js'; -import {FakeSettingsPrivate} from 'chrome://test/settings/fake_settings_private.m.js'; -import {TestLanguagesBrowserProxy} from 'chrome://test/settings/test_languages_browser_proxy.m.js'; +import {FakeLanguageSettingsPrivate} from 'chrome://test/settings/fake_language_settings_private.js'; +import {FakeSettingsPrivate} from 'chrome://test/settings/fake_settings_private.js'; +import {TestLanguagesBrowserProxy} from 'chrome://test/settings/test_languages_browser_proxy.js'; // clang-format on
diff --git a/chrome/test/data/webui/settings/fake_input_method_private.js b/chrome/test/data/webui/settings/fake_input_method_private.js index 95e09aa..51a625b 100644 --- a/chrome/test/data/webui/settings/fake_input_method_private.js +++ b/chrome/test/data/webui/settings/fake_input_method_private.js
@@ -6,34 +6,29 @@ * @fileoverview Fake implementation of chrome.inputMethodPrivate * for testing. */ -cr.define('settings', function() { /** * Fake of the chrome.inputMethodsPrivate API. Only methods that are called * during testing have been implemented. * * @constructor */ - /* #export */ function FakeInputMethodPrivate() {} +export function FakeInputMethodPrivate() {} - FakeInputMethodPrivate.prototype = { - getCurrentInputMethod: function(callback) { - callback(null); - }, +FakeInputMethodPrivate.prototype = { + getCurrentInputMethod: function(callback) { + callback(null); + }, - setCurrentInputMethod: () => {}, + setCurrentInputMethod: () => {}, - get onChanged() { - return { - addListener: function() { - // Nothing to do here. - }, - removeListener: function() { - // Nothing to do here. - }, - }; - }, - }; - - // #cr_define_end - return {FakeInputMethodPrivate: FakeInputMethodPrivate}; -}); + get onChanged() { + return { + addListener: function() { + // Nothing to do here. + }, + removeListener: function() { + // Nothing to do here. + }, + }; + }, +};
diff --git a/chrome/test/data/webui/settings/fake_language_settings_private.js b/chrome/test/data/webui/settings/fake_language_settings_private.js index e2b6a4f3..f9fc68b5 100644 --- a/chrome/test/data/webui/settings/fake_language_settings_private.js +++ b/chrome/test/data/webui/settings/fake_language_settings_private.js
@@ -7,559 +7,543 @@ * for testing. */ -// #import {assert, assertNotReached} from 'chrome://resources/js/assert.m.js'; -// #import {isChromeOS} from 'chrome://resources/js/cr.m.js'; -// #import {FakeChromeEvent} from '../fake_chrome_event.m.js'; -// #import {TestBrowserProxy} from '../test_browser_proxy.m.js'; +import {assert, assertNotReached} from 'chrome://resources/js/assert.m.js'; +import {isChromeOS} from 'chrome://resources/js/cr.m.js'; +import {FakeChromeEvent} from '../fake_chrome_event.m.js'; +import {TestBrowserProxy} from '../test_browser_proxy.m.js'; -cr.define('settings', function() { +/** + * Fake of the chrome.languageSettingsPrivate API. + * @implements {LanguageSettingsPrivate} + */ +export class FakeLanguageSettingsPrivate extends TestBrowserProxy { + constructor() { + // List of method names expected to be tested with whenCalled() + super([ + 'getSpellcheckWords', + ]); + + // /** @type {!SettingsPrefsElement} */ + this.settingsPrefs_ = null; + + /** + * Called when the pref for the dictionaries used for spell checking + * changes or the status of one of the spell check dictionaries changes. + * @type {!ChromeEvent} + */ + this.onSpellcheckDictionariesChanged = + /** @type {!ChromeEvent} */ (new FakeChromeEvent()); + + /** + * Called when words are added to and/or removed from the custom spell + * check dictionary. + * @type {!ChromeEvent} + */ + this.onCustomDictionaryChanged = + /** @type {!ChromeEvent} */ (new FakeChromeEvent()); + + /** + * Called when an input method is added. + * @type {!ChromeEvent} + */ + this.onInputMethodAdded = + /** @type {!ChromeEvent} */ (new FakeChromeEvent()); + + this.onInputMethodRemoved = + /** @type {!ChromeEvent} */ (new FakeChromeEvent()); + + /** @type {!Array<!chrome.languageSettingsPrivate.Language>} */ + this.languages = [ + { + // English and some variants. + code: 'en', + displayName: 'English', + nativeDisplayName: 'English', + supportsTranslate: true, + }, + { + code: 'en-CA', + displayName: 'English (Canada)', + nativeDisplayName: 'English (Canada)', + supportsSpellcheck: true, + supportsUI: true, + }, + { + code: 'en-US', + displayName: 'English (United States)', + nativeDisplayName: 'English (United States)', + supportsSpellcheck: true, + supportsUI: true, + }, + { + // A standalone language. + code: 'sw', + displayName: 'Swahili', + nativeDisplayName: 'Kiswahili', + supportsSpellcheck: true, + supportsTranslate: true, + supportsUI: true, + }, + { + // A standalone language that doesn't support anything. + code: 'tk', + displayName: 'Turkmen', + nativeDisplayName: 'Turkmen' + }, + { + // Edge cases: + // Norwegian is the macrolanguage for "nb" (see below). + code: 'no', + displayName: 'Norwegian', + nativeDisplayName: 'norsk', + supportsTranslate: true, + }, + { + // Norwegian language codes don't start with "no-" but should still + // fall under the Norwegian macrolanguage. + // TODO(michaelpg): Test this is ordered correctly. + code: 'nb', + displayName: 'Norwegian Bokmål', + nativeDisplayName: 'norsk bokmål', + supportsSpellcheck: true, + supportsUI: true, + }, + { + // A language where displayName and nativeDisplayName have different + // values. Used for testing search functionality. + code: 'el', + displayName: 'Greek', + nativeDisplayName: 'Ελληνικά', + supportsUI: true, + }, + { + // A fake language for ARC IMEs which is for internal use only. The + // value of the |code| must be the same as |kArcImeLanguage| in + // ui/base/ime/chromeos/extension_ime_util.cc. + code: '_arc_ime_language_', + displayName: 'Keyboard apps', + }, + { + // Hebrew. This is used to test that the old language code "iw" + // still works. + code: 'he', + displayName: 'Hebrew', + nativeDisplayName: 'Hebrew', + supportsUI: true, + }, + ]; + + /** @type {!Array<string>} */ + this.alwaysTranslateList = ['de, es, nl']; + + /** @type {!Array<!chrome.languageSettingsPrivate.InputMethod>} */ + this.componentExtensionImes = [ + { + id: '_comp_ime_jkghodnilhceideoidjikpgommlajknkxkb:us::eng', + displayName: 'US keyboard', + languageCodes: ['en', 'en-US'], + tags: ['US keyboard', 'English', 'English(United States)'], + enabled: true, + }, + { + id: '_comp_ime_fgoepimhcoialccpbmpnnblemnepkkaoxkb:us:dvorak:eng', + displayName: 'US Dvorak keyboard', + languageCodes: ['en', 'en-US'], + tags: ['US Dvorak keyboard', 'English', 'English(United States)'], + enabled: true, + }, + { + id: '_comp_ime_abcdefghijklmnopqrstuvwxyzabcdefxkb:sw:sw', + displayName: 'Swahili keyboard', + languageCodes: ['sw', 'tk'], + tags: ['Swahili keyboard', 'Swahili', 'Turkmen'], + enabled: false, + }, + { + id: 'ime_abcdefghijklmnopqrstuvwxyzabcdefxkb:us:sw', + displayName: 'US Swahili keyboard', + languageCodes: ['en', 'en-US', 'sw'], + tags: [ + 'US Swahili keyboard', 'English', 'English(United States)', 'Swahili' + ], + enabled: false, + }, + { + id: '_comp_ime_abcdefghijklmnopqrstuvwxyzabcdefxkb:us:intl', + displayName: 'US International keyboard', + languageCodes: ['en-US'], + tags: ['US International keyboard', 'English(United States)'], + enabled: false, + isProhibitedByPolicy: true, + }, + { + id: '_comp_ime_abcdefghijklmnopqrstuvwxyzabcdefxkb:vi:vi', + displayName: 'Vietnamese keyboard', + languageCodes: ['vi'], + tags: ['Vietnamese keyboard', 'Vietnamese'], + enabled: false, + }, + ]; + } + + /** @param {SettingsPrefsElement} settingsPrefs */ + setSettingsPrefs(settingsPrefs) { + this.settingsPrefs_ = settingsPrefs; + } + + // LanguageSettingsPrivate fake. + /** - * Fake of the chrome.languageSettingsPrivate API. - * @implements {LanguageSettingsPrivate} + * Gets languages available for translate, spell checking, input and locale. + * @param {function(!Array<!chrome.languageSettingsPrivate.Language>)} + * callback */ - /* #export */ class FakeLanguageSettingsPrivate extends TestBrowserProxy { - constructor() { - // List of method names expected to be tested with whenCalled() - super([ - 'getSpellcheckWords', - ]); + getLanguageList(callback) { + setTimeout(function() { + callback( + /** @type {!Array<!chrome.languageSettingsPrivate.Language>} */ ( + JSON.parse(JSON.stringify(this.languages)))); + }.bind(this)); + } - // /** @type {!SettingsPrefsElement} */ - this.settingsPrefs_ = null; + /** + * Gets languages that should always be automatically translated. + * @param {function(!Array<!string>)} + * callback + */ + getAlwaysTranslateLanguages(callback) { + setTimeout(function() { + callback( + /** @type {!Array<!string>} */ (this.alwaysTranslateList)); + }.bind(this)); + } - /** - * Called when the pref for the dictionaries used for spell checking - * changes or the status of one of the spell check dictionaries changes. - * @type {!ChromeEvent} - */ - this.onSpellcheckDictionariesChanged = - /** @type {!ChromeEvent} */ (new FakeChromeEvent()); - - /** - * Called when words are added to and/or removed from the custom spell - * check dictionary. - * @type {!ChromeEvent} - */ - this.onCustomDictionaryChanged = - /** @type {!ChromeEvent} */ (new FakeChromeEvent()); - - /** - * Called when an input method is added. - * @type {!ChromeEvent} - */ - this.onInputMethodAdded = - /** @type {!ChromeEvent} */ (new FakeChromeEvent()); - - /** - * Called when an input method is removed. - * @type {!ChromeEvent} - */ - this.onInputMethodRemoved = - /** @type {!ChromeEvent} */ (new FakeChromeEvent()); - - /** @type {!Array<!chrome.languageSettingsPrivate.Language>} */ - this.languages = [ - { - // English and some variants. - code: 'en', - displayName: 'English', - nativeDisplayName: 'English', - supportsTranslate: true, - }, - { - code: 'en-CA', - displayName: 'English (Canada)', - nativeDisplayName: 'English (Canada)', - supportsSpellcheck: true, - supportsUI: true, - }, - { - code: 'en-US', - displayName: 'English (United States)', - nativeDisplayName: 'English (United States)', - supportsSpellcheck: true, - supportsUI: true, - }, - { - // A standalone language. - code: 'sw', - displayName: 'Swahili', - nativeDisplayName: 'Kiswahili', - supportsSpellcheck: true, - supportsTranslate: true, - supportsUI: true, - }, - { - // A standalone language that doesn't support anything. - code: 'tk', - displayName: 'Turkmen', - nativeDisplayName: 'Turkmen' - }, - { - // Edge cases: - // Norwegian is the macrolanguage for "nb" (see below). - code: 'no', - displayName: 'Norwegian', - nativeDisplayName: 'norsk', - supportsTranslate: true, - }, - { - // Norwegian language codes don't start with "no-" but should still - // fall under the Norwegian macrolanguage. - // TODO(michaelpg): Test this is ordered correctly. - code: 'nb', - displayName: 'Norwegian Bokmål', - nativeDisplayName: 'norsk bokmål', - supportsSpellcheck: true, - supportsUI: true, - }, - { - // A language where displayName and nativeDisplayName have different - // values. Used for testing search functionality. - code: 'el', - displayName: 'Greek', - nativeDisplayName: 'Ελληνικά', - supportsUI: true, - }, - { - // A fake language for ARC IMEs which is for internal use only. The - // value of the |code| must be the same as |kArcImeLanguage| in - // ui/base/ime/chromeos/extension_ime_util.cc. - code: '_arc_ime_language_', - displayName: 'Keyboard apps', - }, - { - // Hebrew. This is used to test that the old language code "iw" - // still works. - code: 'he', - displayName: 'Hebrew', - nativeDisplayName: 'Hebrew', - supportsUI: true, - }, - ]; - - /** @type {!Array<string>} */ - this.alwaysTranslateList = ['de, es, nl']; - - /** @type {!Array<!chrome.languageSettingsPrivate.InputMethod>} */ - this.componentExtensionImes = [ - { - id: '_comp_ime_jkghodnilhceideoidjikpgommlajknkxkb:us::eng', - displayName: 'US keyboard', - languageCodes: ['en', 'en-US'], - tags: ['US keyboard', 'English', 'English(United States)'], - enabled: true, - }, - { - id: '_comp_ime_fgoepimhcoialccpbmpnnblemnepkkaoxkb:us:dvorak:eng', - displayName: 'US Dvorak keyboard', - languageCodes: ['en', 'en-US'], - tags: ['US Dvorak keyboard', 'English', 'English(United States)'], - enabled: true, - }, - { - id: '_comp_ime_abcdefghijklmnopqrstuvwxyzabcdefxkb:sw:sw', - displayName: 'Swahili keyboard', - languageCodes: ['sw', 'tk'], - tags: ['Swahili keyboard', 'Swahili', 'Turkmen'], - enabled: false, - }, - { - id: 'ime_abcdefghijklmnopqrstuvwxyzabcdefxkb:us:sw', - displayName: 'US Swahili keyboard', - languageCodes: ['en', 'en-US', 'sw'], - tags: [ - 'US Swahili keyboard', 'English', 'English(United States)', - 'Swahili' - ], - enabled: false, - }, - { - id: '_comp_ime_abcdefghijklmnopqrstuvwxyzabcdefxkb:us:intl', - displayName: 'US International keyboard', - languageCodes: ['en-US'], - tags: ['US International keyboard', 'English(United States)'], - enabled: false, - isProhibitedByPolicy: true, - }, - { - id: '_comp_ime_abcdefghijklmnopqrstuvwxyzabcdefxkb:vi:vi', - displayName: 'Vietnamese keyboard', - languageCodes: ['vi'], - tags: ['Vietnamese keyboard', 'Vietnamese'], - enabled: false, - }, - ]; - } - - /** @param {SettingsPrefsElement} settingsPrefs */ - setSettingsPrefs(settingsPrefs) { - this.settingsPrefs_ = settingsPrefs; - } - - // LanguageSettingsPrivate fake. - - /** - * Gets languages available for translate, spell checking, input and locale. - * @param {function(!Array<!chrome.languageSettingsPrivate.Language>)} - * callback - */ - getLanguageList(callback) { - setTimeout(function() { - callback( - /** @type {!Array<!chrome.languageSettingsPrivate.Language>} */ ( - JSON.parse(JSON.stringify(this.languages)))); - }.bind(this)); - } - - /** - * Gets languages that should always be automatically translated. - * @param {function(!Array<!string>)} - * callback - */ - getAlwaysTranslateLanguages(callback) { - setTimeout(function() { - callback( - /** @type {!Array<!string>} */ (this.alwaysTranslateList)); - }.bind(this)); - } - - /** - * Sets whether a given language should always be automatically translated. - * @param {string} languageCode - * @param {boolean} alwaysTranslate - */ - setLanguageAlwaysTranslateState(languageCode, alwaysTranslate) { - if (alwaysTranslate) { - this.alwaysTranslateList.push(languageCode); - } else { - const index = this.alwaysTranslateList.indexOf(languageCode); - if (index === -1) { - return; - } - this.alwaysTranslateList.splice(index, 1); - } - } - - /** - * Enables a language, adding it to the Accept-Language list (used to decide - * which languages to translate, generate the Accept-Language header, etc.). - * @param {string} languageCode - */ - enableLanguage(languageCode) { - let languageCodes = - this.settingsPrefs_.get('prefs.intl.accept_languages.value'); - const languages = languageCodes.split(','); - if (languages.indexOf(languageCode) !== -1) { - return; - } - languages.push(languageCode); - languageCodes = languages.join(','); - this.settingsPrefs_.set( - 'prefs.intl.accept_languages.value', languageCodes); - if (cr.isChromeOS) { - this.settingsPrefs_.set( - 'prefs.settings.language.preferred_languages.value', languageCodes); - } - } - - /** - * Disables a language, removing it from the Accept-Language list. - * @param {string} languageCode - */ - disableLanguage(languageCode) { - let languageCodes = - this.settingsPrefs_.get('prefs.intl.accept_languages.value'); - const languages = languageCodes.split(','); - const index = languages.indexOf(languageCode); + /** + * Sets whether a given language should always be automatically translated. + * @param {string} languageCode + * @param {boolean} alwaysTranslate + */ + setLanguageAlwaysTranslateState(languageCode, alwaysTranslate) { + if (alwaysTranslate) { + this.alwaysTranslateList.push(languageCode); + } else { + const index = this.alwaysTranslateList.indexOf(languageCode); if (index === -1) { return; } - languages.splice(index, 1); - languageCodes = languages.join(','); - this.settingsPrefs_.set( - 'prefs.intl.accept_languages.value', languageCodes); - if (cr.isChromeOS) { - this.settingsPrefs_.set( - 'prefs.settings.language.preferred_languages.value', languageCodes); - } - } - - /** - * Enables/Disables translation for the given language. - * This respectively removes/adds the language to the blocked set in the - * preferences. - * @param {string} languageCode - * @param {boolean} enable - */ - setEnableTranslationForLanguage(languageCode, enable) { - const index = - this.settingsPrefs_.get('prefs.translate_blocked_languages.value') - .indexOf(languageCode); - if (enable) { - if (index === -1) { - return; - } - this.settingsPrefs_.splice( - 'prefs.translate_blocked_languages.value', index, 1); - } else { - if (index !== -1) { - return; - } - this.settingsPrefs_.push( - 'prefs.translate_blocked_languages.value', languageCode); - } - } - - /** - * Moves a language inside the language list. - * Movement is determined by the |moveType| parameter. - * @param {string} languageCode - * @param {chrome.languageSettingsPrivate.MoveType} moveType - */ - moveLanguage(languageCode, moveType) { - let languageCodes = - this.settingsPrefs_.get('prefs.intl.accept_languages.value'); - const languages = languageCodes.split(','); - const index = languages.indexOf(languageCode); - - if (moveType === chrome.languageSettingsPrivate.MoveType.TOP) { - if (index < 1) { - return; - } - - languages.splice(index, 1); - languages.unshift(languageCode); - } else if (moveType === chrome.languageSettingsPrivate.MoveType.UP) { - if (index < 1) { - return; - } - - const temp = languages[index - 1]; - languages[index - 1] = languageCode; - languages[index] = temp; - } else if (moveType === chrome.languageSettingsPrivate.MoveType.DOWN) { - if (index === -1 || index === languages.length - 1) { - return; - } - - const temp = languages[index + 1]; - languages[index + 1] = languageCode; - languages[index] = temp; - } - - languageCodes = languages.join(','); - this.settingsPrefs_.set( - 'prefs.intl.accept_languages.value', languageCodes); - if (cr.isChromeOS) { - this.settingsPrefs_.set( - 'prefs.settings.language.preferred_languages.value', languageCodes); - } - } - - /** - * Gets the current status of the chosen spell check dictionaries. - * @param {function(!Array< - * !chrome.languageSettingsPrivate.SpellcheckDictionaryStatus>):void} - * callback - */ - getSpellcheckDictionaryStatuses(callback) { - callback([]); - } - - /** - * Gets the custom spell check words, in sorted order. - * @param {function(!Array<string>):void} callback - */ - getSpellcheckWords(callback) { - callback([]); - this.methodCalled('getSpellcheckWords'); - } - - /** - * Adds a word to the custom dictionary. - * @param {string} word - */ - addSpellcheckWord(word) { - /** @type {FakeChromeEvent} */ (this.onCustomDictionaryChanged) - .callListeners([word], []); - } - - /** - * Removes a word from the custom dictionary. - * @param {string} word - */ - removeSpellcheckWord(word) { - /** @type {FakeChromeEvent} */ (this.onCustomDictionaryChanged) - .callListeners([], [word]); - } - - /** - * Gets the translate target language (in most cases, the display locale). - * @param {function(string):void} callback - */ - getTranslateTargetLanguage(callback) { - setTimeout(callback.bind(null, 'en')); - } - - /** - * Gets all supported input methods, including third-party IMEs. Chrome OS - * only. - * @param {function(!chrome.languageSettingsPrivate.InputMethodLists):void} - * callback - */ - getInputMethodLists(callback) { - if (!cr.isChromeOS) { - assertNotReached(); - } - callback({ - componentExtensionImes: - /** @type {!Array<!chrome.languageSettingsPrivate.InputMethod>} */ ( - JSON.parse(JSON.stringify(this.componentExtensionImes))), - thirdPartyExtensionImes: [], - }); - } - - /** - * Adds the input method to the current user's list of enabled input - * methods, enabling the input method for the current user. Chrome OS only. - * @param {string} inputMethodId - */ - addInputMethod(inputMethodId) { - assert(cr.isChromeOS); - const inputMethod = this.componentExtensionImes.find(function(ime) { - return ime.id === inputMethodId; - }); - assert(!!inputMethod); - inputMethod.enabled = true; - const prefPath = 'prefs.settings.language.preload_engines.value'; - const enabledInputMethods = this.settingsPrefs_.get(prefPath).split(','); - enabledInputMethods.push(inputMethodId); - this.settingsPrefs_.set(prefPath, enabledInputMethods.join(',')); - } - - /** - * Removes the input method from the current user's list of enabled input - * methods, disabling the input method for the current user. Chrome OS only. - * @param {string} inputMethodId - */ - removeInputMethod(inputMethodId) { - assert(cr.isChromeOS); - const inputMethod = this.componentExtensionImes.find(function(ime) { - return ime.id === inputMethodId; - }); - assert(!!inputMethod); - inputMethod.enabled = false; - this.settingsPrefs_.set( - 'prefs.settings.language.preload_engines.value', - this.settingsPrefs_ - .get('prefs.settings.language.preload_engines.value') - .replace(inputMethodId, '')); - } - - /** - * Tries to download the dictionary after a failed download. - * @param {string} languageCode - */ - retryDownloadDictionary(languageCode) { - /** @type {FakeChromeEvent} */ (this.onSpellcheckDictionariesChanged) - .callListeners([ - {languageCode, isReady: false, isDownlading: true}, - ]); - /** @type {FakeChromeEvent} */ (this.onSpellcheckDictionariesChanged) - .callListeners([ - {languageCode, isReady: false, downloadFailed: true}, - ]); + this.alwaysTranslateList.splice(index, 1); } } + /** + * Enables a language, adding it to the Accept-Language list (used to decide + * which languages to translate, generate the Accept-Language header, etc.). + * @param {string} languageCode + */ + enableLanguage(languageCode) { + let languageCodes = + this.settingsPrefs_.get('prefs.intl.accept_languages.value'); + const languages = languageCodes.split(','); + if (languages.indexOf(languageCode) !== -1) { + return; + } + languages.push(languageCode); + languageCodes = languages.join(','); + this.settingsPrefs_.set('prefs.intl.accept_languages.value', languageCodes); + if (isChromeOS) { + this.settingsPrefs_.set( + 'prefs.settings.language.preferred_languages.value', languageCodes); + } + } + + /** + * Disables a language, removing it from the Accept-Language list. + * @param {string} languageCode + */ + disableLanguage(languageCode) { + let languageCodes = + this.settingsPrefs_.get('prefs.intl.accept_languages.value'); + const languages = languageCodes.split(','); + const index = languages.indexOf(languageCode); + if (index === -1) { + return; + } + languages.splice(index, 1); + languageCodes = languages.join(','); + this.settingsPrefs_.set('prefs.intl.accept_languages.value', languageCodes); + if (isChromeOS) { + this.settingsPrefs_.set( + 'prefs.settings.language.preferred_languages.value', languageCodes); + } + } + + /** + * Enables/Disables translation for the given language. + * This respectively removes/adds the language to the blocked set in the + * preferences. + * @param {string} languageCode + * @param {boolean} enable + */ + setEnableTranslationForLanguage(languageCode, enable) { + const index = + this.settingsPrefs_.get('prefs.translate_blocked_languages.value') + .indexOf(languageCode); + if (enable) { + if (index === -1) { + return; + } + this.settingsPrefs_.splice( + 'prefs.translate_blocked_languages.value', index, 1); + } else { + if (index !== -1) { + return; + } + this.settingsPrefs_.push( + 'prefs.translate_blocked_languages.value', languageCode); + } + } + + /** + * Moves a language inside the language list. + * Movement is determined by the |moveType| parameter. + * @param {string} languageCode + * @param {chrome.languageSettingsPrivate.MoveType} moveType + */ + moveLanguage(languageCode, moveType) { + let languageCodes = + this.settingsPrefs_.get('prefs.intl.accept_languages.value'); + const languages = languageCodes.split(','); + const index = languages.indexOf(languageCode); + + if (moveType === chrome.languageSettingsPrivate.MoveType.TOP) { + if (index < 1) { + return; + } + + languages.splice(index, 1); + languages.unshift(languageCode); + } else if (moveType === chrome.languageSettingsPrivate.MoveType.UP) { + if (index < 1) { + return; + } + + const temp = languages[index - 1]; + languages[index - 1] = languageCode; + languages[index] = temp; + } else if (moveType === chrome.languageSettingsPrivate.MoveType.DOWN) { + if (index === -1 || index === languages.length - 1) { + return; + } + + const temp = languages[index + 1]; + languages[index + 1] = languageCode; + languages[index] = temp; + } + + languageCodes = languages.join(','); + this.settingsPrefs_.set('prefs.intl.accept_languages.value', languageCodes); + if (isChromeOS) { + this.settingsPrefs_.set( + 'prefs.settings.language.preferred_languages.value', languageCodes); + } + } + + /** + * Gets the current status of the chosen spell check dictionaries. + * @param {function(!Array< + * !chrome.languageSettingsPrivate.SpellcheckDictionaryStatus>):void} + * callback + */ + getSpellcheckDictionaryStatuses(callback) { + callback([]); + } + + /** + * Gets the custom spell check words, in sorted order. + * @param {function(!Array<string>):void} callback + */ + getSpellcheckWords(callback) { + callback([]); + this.methodCalled('getSpellcheckWords'); + } + + /** + * Adds a word to the custom dictionary. + * @param {string} word + */ + addSpellcheckWord(word) { + /** @type {FakeChromeEvent} */ (this.onCustomDictionaryChanged) + .callListeners([word], []); + } + + /** + * Removes a word from the custom dictionary. + * @param {string} word + */ + removeSpellcheckWord(word) { + /** @type {FakeChromeEvent} */ (this.onCustomDictionaryChanged) + .callListeners([], [word]); + } + + /** + * Gets the translate target language (in most cases, the display locale). + * @param {function(string):void} callback + */ + getTranslateTargetLanguage(callback) { + setTimeout(callback.bind(null, 'en')); + } + + /** + * Gets all supported input methods, including third-party IMEs. Chrome OS + * only. + * @param {function(!chrome.languageSettingsPrivate.InputMethodLists):void} + * callback + */ + getInputMethodLists(callback) { + if (!isChromeOS) { + assertNotReached(); + } + callback({ + componentExtensionImes: + /** @type {!Array<!chrome.languageSettingsPrivate.InputMethod>} */ ( + JSON.parse(JSON.stringify(this.componentExtensionImes))), + thirdPartyExtensionImes: [], + }); + } + + /** + * Adds the input method to the current user's list of enabled input + * methods, enabling the input method for the current user. Chrome OS only. + * @param {string} inputMethodId + */ + addInputMethod(inputMethodId) { + assert(isChromeOS); + const inputMethod = this.componentExtensionImes.find(function(ime) { + return ime.id === inputMethodId; + }); + assert(!!inputMethod); + inputMethod.enabled = true; + const prefPath = 'prefs.settings.language.preload_engines.value'; + const enabledInputMethods = this.settingsPrefs_.get(prefPath).split(','); + enabledInputMethods.push(inputMethodId); + this.settingsPrefs_.set(prefPath, enabledInputMethods.join(',')); + } + + /** + * Removes the input method from the current user's list of enabled input + * methods, disabling the input method for the current user. Chrome OS only. + * @param {string} inputMethodId + */ + removeInputMethod(inputMethodId) { + assert(isChromeOS); + const inputMethod = this.componentExtensionImes.find(function(ime) { + return ime.id === inputMethodId; + }); + assert(!!inputMethod); + inputMethod.enabled = false; + this.settingsPrefs_.set( + 'prefs.settings.language.preload_engines.value', + this.settingsPrefs_.get('prefs.settings.language.preload_engines.value') + .replace(inputMethodId, '')); + } + + /** + * Tries to download the dictionary after a failed download. + * @param {string} languageCode + */ + retryDownloadDictionary(languageCode) { + /** @type {FakeChromeEvent} */ (this.onSpellcheckDictionariesChanged) + .callListeners([ + {languageCode, isReady: false, isDownlading: true}, + ]); + /** @type {FakeChromeEvent} */ (this.onSpellcheckDictionariesChanged) + .callListeners([ + {languageCode, isReady: false, downloadFailed: true}, + ]); + } +} + // List of language-related preferences suitable for testing. - /* #export */ function getFakeLanguagePrefs() { - const fakePrefs = [ - { - key: 'browser.enable_spellchecking', - type: chrome.settingsPrivate.PrefType.BOOLEAN, - value: true, - }, - { - key: 'intl.app_locale', - type: chrome.settingsPrivate.PrefType.STRING, - value: 'en-US', - }, - { - key: 'intl.accept_languages', - type: chrome.settingsPrivate.PrefType.STRING, - value: 'en-US,sw', - }, - { - key: 'intl.forced_languages', - type: chrome.settingsPrivate.PrefType.LIST, - value: '', - }, - { - key: 'spellcheck.blocked_dictionaries', - type: chrome.settingsPrivate.PrefType.LIST, - value: [], - }, - { - key: 'spellcheck.dictionaries', - type: chrome.settingsPrivate.PrefType.LIST, - value: ['en-US'], - }, - { - key: 'spellcheck.forced_dictionaries', - type: chrome.settingsPrivate.PrefType.LIST, - value: [], - }, - { - key: 'spellcheck.use_spelling_service', - type: chrome.settingsPrivate.PrefType.BOOLEAN, - value: false, - }, - { - key: 'translate.enabled', - type: chrome.settingsPrivate.PrefType.BOOLEAN, - value: true, - }, - { - key: 'translate_blocked_languages', - type: chrome.settingsPrivate.PrefType.LIST, - value: ['en-US'], - } - ]; - if (cr.isChromeOS) { - fakePrefs.push({ - key: 'settings.language.preferred_languages', - type: chrome.settingsPrivate.PrefType.STRING, - value: 'en-US,sw', - }); - fakePrefs.push({ - key: 'settings.language.preload_engines', - type: chrome.settingsPrivate.PrefType.STRING, - value: '_comp_ime_jkghodnilhceideoidjikpgommlajknkxkb:us::eng,' + - '_comp_ime_fgoepimhcoialccpbmpnnblemnepkkaoxkb:us:dvorak:eng', - }); - fakePrefs.push({ - key: 'settings.language.enabled_extension_imes', - type: chrome.settingsPrivate.PrefType.STRING, - value: '', - }); - fakePrefs.push({ - key: 'settings.language.ime_menu_activated', - type: chrome.settingsPrivate.PrefType.BOOLEAN, - value: false, - }); - fakePrefs.push({ - key: 'settings.language.allowed_input_methods', - type: chrome.settingsPrivate.PrefType.LIST, - value: [], - }); +export function getFakeLanguagePrefs() { + const fakePrefs = [ + { + key: 'browser.enable_spellchecking', + type: chrome.settingsPrivate.PrefType.BOOLEAN, + value: true, + }, + { + key: 'intl.app_locale', + type: chrome.settingsPrivate.PrefType.STRING, + value: 'en-US', + }, + { + key: 'intl.accept_languages', + type: chrome.settingsPrivate.PrefType.STRING, + value: 'en-US,sw', + }, + { + key: 'intl.forced_languages', + type: chrome.settingsPrivate.PrefType.LIST, + value: '', + }, + { + key: 'spellcheck.blocked_dictionaries', + type: chrome.settingsPrivate.PrefType.LIST, + value: [], + }, + { + key: 'spellcheck.dictionaries', + type: chrome.settingsPrivate.PrefType.LIST, + value: ['en-US'], + }, + { + key: 'spellcheck.forced_dictionaries', + type: chrome.settingsPrivate.PrefType.LIST, + value: [], + }, + { + key: 'spellcheck.use_spelling_service', + type: chrome.settingsPrivate.PrefType.BOOLEAN, + value: false, + }, + { + key: 'translate.enabled', + type: chrome.settingsPrivate.PrefType.BOOLEAN, + value: true, + }, + { + key: 'translate_blocked_languages', + type: chrome.settingsPrivate.PrefType.LIST, + value: ['en-US'], } - return fakePrefs; + ]; + if (isChromeOS) { + fakePrefs.push({ + key: 'settings.language.preferred_languages', + type: chrome.settingsPrivate.PrefType.STRING, + value: 'en-US,sw', + }); + fakePrefs.push({ + key: 'settings.language.preload_engines', + type: chrome.settingsPrivate.PrefType.STRING, + value: '_comp_ime_jkghodnilhceideoidjikpgommlajknkxkb:us::eng,' + + '_comp_ime_fgoepimhcoialccpbmpnnblemnepkkaoxkb:us:dvorak:eng', + }); + fakePrefs.push({ + key: 'settings.language.enabled_extension_imes', + type: chrome.settingsPrivate.PrefType.STRING, + value: '', + }); + fakePrefs.push({ + key: 'settings.language.ime_menu_activated', + type: chrome.settingsPrivate.PrefType.BOOLEAN, + value: false, + }); + fakePrefs.push({ + key: 'settings.language.allowed_input_methods', + type: chrome.settingsPrivate.PrefType.LIST, + value: [], + }); } - // #cr_define_end - return { - FakeLanguageSettingsPrivate: FakeLanguageSettingsPrivate, - getFakeLanguagePrefs: getFakeLanguagePrefs, - }; -}); + return fakePrefs; +}
diff --git a/chrome/test/data/webui/settings/fake_settings_private.js b/chrome/test/data/webui/settings/fake_settings_private.js index a8bbda1..11b8cb56 100644 --- a/chrome/test/data/webui/settings/fake_settings_private.js +++ b/chrome/test/data/webui/settings/fake_settings_private.js
@@ -3,27 +3,26 @@ // found in the LICENSE file. // clang-format off -// #import {assertEquals, assertNotEquals} from '../chai_assert.js'; -// #import {FakeChromeEvent} from '../fake_chrome_event.m.js'; +import {assertEquals, assertNotEquals} from '../chai_assert.js'; +import {FakeChromeEvent} from '../fake_chrome_event.m.js'; // clang-format on /** @fileoverview Fake implementation of chrome.settingsPrivate for testing. */ -cr.define('settings', function() { /** * @typedef {Array<{key: string, * type: chrome.settingsPrivate.PrefType, * values: !Array<*>}>} */ - /* #export */ let FakeSettingsPrivatePref; +export let FakeSettingsPrivatePref; - /** - * Creates a deep copy of the object. - * @param {*} obj - * @return {*} - */ - function deepCopy(obj) { - return JSON.parse(JSON.stringify(obj)); - } +/** + * Creates a deep copy of the object. + * @param {*} obj + * @return {*} + */ +function deepCopy(obj) { + return JSON.parse(JSON.stringify(obj)); +} /** * Fake of chrome.settingsPrivate API. Use by setting @@ -31,125 +30,118 @@ * FakeSettingsPrivate to settings-prefs#initialize(). * @implements {SettingsPrivate} */ - /* #export */ class FakeSettingsPrivate { - /** @param {Array<!settings.FakeSettingsPrivatePref>=} opt_initialPrefs */ - constructor(opt_initialPrefs) { - this.disallowSetPref_ = false; +export class FakeSettingsPrivate { + /** @param {Array<!FakeSettingsPrivatePref>=} opt_initialPrefs */ + constructor(opt_initialPrefs) { + this.disallowSetPref_ = false; + this.failNextSetPref_ = false; + + this.prefs = {}; + + if (!opt_initialPrefs) { + return; + } + for (const pref of opt_initialPrefs) { + this.addPref_(pref.type, pref.key, pref.value); + } + + // chrome.settingsPrivate override. + this.onPrefsChanged = /** @type {!ChromeEvent} */ (new FakeChromeEvent()); + } + + // chrome.settingsPrivate overrides. + getAllPrefs(callback) { + // Send a copy of prefs to keep our internal state private. + const prefs = []; + for (const key in this.prefs) { + prefs.push(deepCopy(this.prefs[key])); + } + + // Run the callback asynchronously to test that the prefs aren't actually + // used before they become available. + setTimeout(callback.bind(null, prefs)); + } + + setPref(key, value, pageId, callback) { + const pref = this.prefs[key]; + assertNotEquals(undefined, pref); + assertEquals(typeof value, typeof pref.value); + assertEquals(Array.isArray(value), Array.isArray(pref.value)); + + if (this.failNextSetPref_) { + callback(false); this.failNextSetPref_ = false; - - this.prefs = {}; - - if (!opt_initialPrefs) { - return; - } - for (const pref of opt_initialPrefs) { - this.addPref_(pref.type, pref.key, pref.value); - } - - // chrome.settingsPrivate override. - this.onPrefsChanged = /** @type {!ChromeEvent} */ (new FakeChromeEvent()); + return; } + assertNotEquals(true, this.disallowSetPref_); - // chrome.settingsPrivate overrides. - getAllPrefs(callback) { - // Send a copy of prefs to keep our internal state private. - const prefs = []; - for (const key in this.prefs) { - prefs.push(deepCopy(this.prefs[key])); - } + const changed = JSON.stringify(pref.value) !== JSON.stringify(value); + pref.value = deepCopy(value); + callback(true); - // Run the callback asynchronously to test that the prefs aren't actually - // used before they become available. - setTimeout(callback.bind(null, prefs)); - } - - setPref(key, value, pageId, callback) { - const pref = this.prefs[key]; - assertNotEquals(undefined, pref); - assertEquals(typeof value, typeof pref.value); - assertEquals(Array.isArray(value), Array.isArray(pref.value)); - - if (this.failNextSetPref_) { - callback(false); - this.failNextSetPref_ = false; - return; - } - assertNotEquals(true, this.disallowSetPref_); - - const changed = JSON.stringify(pref.value) !== JSON.stringify(value); - pref.value = deepCopy(value); - callback(true); - - // Like chrome.settingsPrivate, send a notification when prefs change. - if (changed) { - this.sendPrefChanges([{key: key, value: deepCopy(value)}]); - } - } - - getPref(key, callback) { - const pref = this.prefs[key]; - assertNotEquals(undefined, pref); - callback( - /** @type {!chrome.settingsPrivate.PrefObject} */ (deepCopy(pref))); - } - - // Functions used by tests. - - /** Instructs the API to return a failure when setPref is next called. */ - failNextSetPref() { - this.failNextSetPref_ = true; - } - - /** Instructs the API to assert (fail the test) if setPref is called. */ - disallowSetPref() { - this.disallowSetPref_ = true; - } - - allowSetPref() { - this.disallowSetPref_ = false; - } - - /** - * Notifies the listeners of pref changes. - * @param {!Array<{key: string, value: *}>} changes - */ - sendPrefChanges(changes) { - const prefs = []; - for (const change of changes) { - const pref = this.prefs[change.key]; - assertNotEquals(undefined, pref); - pref.value = change.value; - prefs.push(deepCopy(pref)); - } - /** @type {FakeChromeEvent} */ (this.onPrefsChanged).callListeners(prefs); - } - - /** @override */ - getDefaultZoom() {} - - /** @override */ - setDefaultZoom() {} - - // Private methods for use by the fake API. - - /** - * @param {!chrome.settingsPrivate.PrefType} type - * @param {string} key - * @param {*} value - * @private - */ - addPref_(type, key, value) { - this.prefs[key] = { - type: type, - key: key, - value: value, - }; + // Like chrome.settingsPrivate, send a notification when prefs change. + if (changed) { + this.sendPrefChanges([{key: key, value: deepCopy(value)}]); } } - // #cr_define_end - return { - FakeSettingsPrivate: FakeSettingsPrivate, - FakeSettingsPrivatePref: FakeSettingsPrivatePref, - }; -}); + getPref(key, callback) { + const pref = this.prefs[key]; + assertNotEquals(undefined, pref); + callback( + /** @type {!chrome.settingsPrivate.PrefObject} */ (deepCopy(pref))); + } + + // Functions used by tests. + + /** Instructs the API to return a failure when setPref is next called. */ + failNextSetPref() { + this.failNextSetPref_ = true; + } + + /** Instructs the API to assert (fail the test) if setPref is called. */ + disallowSetPref() { + this.disallowSetPref_ = true; + } + + allowSetPref() { + this.disallowSetPref_ = false; + } + + /** + * Notifies the listeners of pref changes. + * @param {!Array<{key: string, value: *}>} changes + */ + sendPrefChanges(changes) { + const prefs = []; + for (const change of changes) { + const pref = this.prefs[change.key]; + assertNotEquals(undefined, pref); + pref.value = change.value; + prefs.push(deepCopy(pref)); + } + /** @type {FakeChromeEvent} */ (this.onPrefsChanged).callListeners(prefs); + } + + /** @override */ + getDefaultZoom() {} + + /** @override */ + setDefaultZoom() {} + + // Private methods for use by the fake API. + + /** + * @param {!chrome.settingsPrivate.PrefType} type + * @param {string} key + * @param {*} value + * @private + */ + addPref_(type, key, value) { + this.prefs[key] = { + type: type, + key: key, + value: value, + }; + } +}
diff --git a/chrome/test/data/webui/settings/languages_page_metrics_test_browser.js b/chrome/test/data/webui/settings/languages_page_metrics_test_browser.js index 38b74aa7..24c2055 100644 --- a/chrome/test/data/webui/settings/languages_page_metrics_test_browser.js +++ b/chrome/test/data/webui/settings/languages_page_metrics_test_browser.js
@@ -11,9 +11,9 @@ import {TestBrowserProxy} from '../test_browser_proxy.m.js'; import {fakeDataBind} from '../test_util.m.js'; -import {getFakeLanguagePrefs} from './fake_language_settings_private.m.js'; -import {FakeSettingsPrivate} from './fake_settings_private.m.js'; -import {TestLanguagesBrowserProxy} from './test_languages_browser_proxy.m.js'; +import {getFakeLanguagePrefs} from './fake_language_settings_private.js'; +import {FakeSettingsPrivate} from './fake_settings_private.js'; +import {TestLanguagesBrowserProxy} from './test_languages_browser_proxy.js'; /** * A test version of LanguageSettingsMetricsProxy.
diff --git a/chrome/test/data/webui/settings/languages_page_metrics_test_cros.js b/chrome/test/data/webui/settings/languages_page_metrics_test_cros.js index 0bd1193..f7a646c 100644 --- a/chrome/test/data/webui/settings/languages_page_metrics_test_cros.js +++ b/chrome/test/data/webui/settings/languages_page_metrics_test_cros.js
@@ -10,9 +10,9 @@ import {assertEquals, assertFalse, assertTrue} from '../chai_assert.js'; import {fakeDataBind} from '../test_util.m.js'; -import {getFakeLanguagePrefs} from './fake_language_settings_private.m.js'; -import {FakeSettingsPrivate} from './fake_settings_private.m.js'; -import {TestLanguagesBrowserProxy} from './test_languages_browser_proxy.m.js'; +import {getFakeLanguagePrefs} from './fake_language_settings_private.js'; +import {FakeSettingsPrivate} from './fake_settings_private.js'; +import {TestLanguagesBrowserProxy} from './test_languages_browser_proxy.js'; import {TestLanguagesMetricsProxy} from './test_languages_metrics_proxy.js'; // TODO(crbug/1109431): Remove this test once migration is complete.
diff --git a/chrome/test/data/webui/settings/languages_page_tests.js b/chrome/test/data/webui/settings/languages_page_tests.js index 671e639b..e8da1c4 100644 --- a/chrome/test/data/webui/settings/languages_page_tests.js +++ b/chrome/test/data/webui/settings/languages_page_tests.js
@@ -7,9 +7,9 @@ import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {LanguagesBrowserProxyImpl} from 'chrome://settings/lazy_load.js'; import {CrSettingsPrefs} from 'chrome://settings/settings.js'; -import {getFakeLanguagePrefs} from 'chrome://test/settings/fake_language_settings_private.m.js'; -import {FakeSettingsPrivate} from 'chrome://test/settings/fake_settings_private.m.js'; -import {TestLanguagesBrowserProxy} from 'chrome://test/settings/test_languages_browser_proxy.m.js'; +import {getFakeLanguagePrefs} from 'chrome://test/settings/fake_language_settings_private.js'; +import {FakeSettingsPrivate} from 'chrome://test/settings/fake_settings_private.js'; +import {TestLanguagesBrowserProxy} from 'chrome://test/settings/test_languages_browser_proxy.js'; import {fakeDataBind, isChildVisible} from 'chrome://test/test_util.m.js'; // clang-format on
diff --git a/chrome/test/data/webui/settings/languages_subpage_tests.js b/chrome/test/data/webui/settings/languages_subpage_tests.js index 61e8b21c..6f9be841 100644 --- a/chrome/test/data/webui/settings/languages_subpage_tests.js +++ b/chrome/test/data/webui/settings/languages_subpage_tests.js
@@ -9,9 +9,9 @@ import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {kMenuCloseDelay, LanguagesBrowserProxyImpl} from 'chrome://settings/lazy_load.js'; import {CrSettingsPrefs} from 'chrome://settings/settings.js'; -import {getFakeLanguagePrefs} from 'chrome://test/settings/fake_language_settings_private.m.js'; -import {FakeSettingsPrivate} from 'chrome://test/settings/fake_settings_private.m.js'; -import {TestLanguagesBrowserProxy} from 'chrome://test/settings/test_languages_browser_proxy.m.js'; +import {getFakeLanguagePrefs} from 'chrome://test/settings/fake_language_settings_private.js'; +import {FakeSettingsPrivate} from 'chrome://test/settings/fake_settings_private.js'; +import {TestLanguagesBrowserProxy} from 'chrome://test/settings/test_languages_browser_proxy.js'; import {eventToPromise, fakeDataBind} from 'chrome://test/test_util.m.js'; // clang-format on
diff --git a/chrome/test/data/webui/settings/languages_tests.js b/chrome/test/data/webui/settings/languages_tests.js index 4611667b..1482c54 100644 --- a/chrome/test/data/webui/settings/languages_tests.js +++ b/chrome/test/data/webui/settings/languages_tests.js
@@ -7,9 +7,9 @@ import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {LanguagesBrowserProxyImpl} from 'chrome://settings/lazy_load.js'; import {CrSettingsPrefs} from 'chrome://settings/settings.js'; -import {getFakeLanguagePrefs} from 'chrome://test/settings/fake_language_settings_private.m.js'; -import {FakeSettingsPrivate} from 'chrome://test/settings/fake_settings_private.m.js'; -import {TestLanguagesBrowserProxy} from 'chrome://test/settings/test_languages_browser_proxy.m.js'; +import {getFakeLanguagePrefs} from 'chrome://test/settings/fake_language_settings_private.js'; +import {FakeSettingsPrivate} from 'chrome://test/settings/fake_settings_private.js'; +import {TestLanguagesBrowserProxy} from 'chrome://test/settings/test_languages_browser_proxy.js'; import {fakeDataBind} from 'chrome://test/test_util.m.js'; // clang-format on
diff --git a/chrome/test/data/webui/settings/password_check_test.js b/chrome/test/data/webui/settings/password_check_test.js index 5903495..f9d6348 100644 --- a/chrome/test/data/webui/settings/password_check_test.js +++ b/chrome/test/data/webui/settings/password_check_test.js
@@ -17,7 +17,7 @@ import {getSyncAllPrefs,simulateSyncStatus} from 'chrome://test/settings/sync_test_util.js'; import {TestOpenWindowProxy} from 'chrome://test/settings/test_open_window_proxy.js'; import {TestPasswordManagerProxy} from 'chrome://test/settings/test_password_manager_proxy.js'; -import {TestSyncBrowserProxy} from 'chrome://test/settings/test_sync_browser_proxy.m.js'; +import {TestSyncBrowserProxy} from 'chrome://test/settings/test_sync_browser_proxy.js'; import {eventToPromise} from 'chrome://test/test_util.m.js'; // clang-format on
diff --git a/chrome/test/data/webui/settings/passwords_device_section_test.js b/chrome/test/data/webui/settings/passwords_device_section_test.js index da8f837..56633225 100644 --- a/chrome/test/data/webui/settings/passwords_device_section_test.js +++ b/chrome/test/data/webui/settings/passwords_device_section_test.js
@@ -9,7 +9,7 @@ import {createMultiStorePasswordEntry, createPasswordEntry, PasswordDeviceSectionElementFactory} from 'chrome://test/settings/passwords_and_autofill_fake_data.js'; import {simulateStoredAccounts, simulateSyncStatus} from 'chrome://test/settings/sync_test_util.js'; import {TestPasswordManagerProxy} from 'chrome://test/settings/test_password_manager_proxy.js'; -import {TestSyncBrowserProxy} from 'chrome://test/settings/test_sync_browser_proxy.m.js'; +import {TestSyncBrowserProxy} from 'chrome://test/settings/test_sync_browser_proxy.js'; import {eventToPromise} from 'chrome://test/test_util.m.js'; import {assertEquals, assertTrue} from '../chai_assert.js';
diff --git a/chrome/test/data/webui/settings/people_page_sync_controls_test.js b/chrome/test/data/webui/settings/people_page_sync_controls_test.js index 02deb4e3..347a4eb 100644 --- a/chrome/test/data/webui/settings/people_page_sync_controls_test.js +++ b/chrome/test/data/webui/settings/people_page_sync_controls_test.js
@@ -10,7 +10,7 @@ import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {Router, StatusAction,SyncBrowserProxyImpl} from 'chrome://settings/settings.js'; import {getSyncAllPrefs, setupRouterWithSyncRoutes} from 'chrome://test/settings/sync_test_util.js'; -import {TestSyncBrowserProxy} from 'chrome://test/settings/test_sync_browser_proxy.m.js'; +import {TestSyncBrowserProxy} from 'chrome://test/settings/test_sync_browser_proxy.js'; import {waitBeforeNextRender} from 'chrome://test/test_util.m.js'; // clang-format on
diff --git a/chrome/test/data/webui/settings/people_page_sync_page_interactive_test.js b/chrome/test/data/webui/settings/people_page_sync_page_interactive_test.js index 9376a4c..055e312a 100644 --- a/chrome/test/data/webui/settings/people_page_sync_page_interactive_test.js +++ b/chrome/test/data/webui/settings/people_page_sync_page_interactive_test.js
@@ -9,7 +9,7 @@ import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {Router, SyncBrowserProxyImpl} from 'chrome://settings/settings.js'; import {setupRouterWithSyncRoutes} from 'chrome://test/settings/sync_test_util.js'; -import {TestSyncBrowserProxy} from 'chrome://test/settings/test_sync_browser_proxy.m.js'; +import {TestSyncBrowserProxy} from 'chrome://test/settings/test_sync_browser_proxy.js'; // clang-format on
diff --git a/chrome/test/data/webui/settings/people_page_sync_page_test.js b/chrome/test/data/webui/settings/people_page_sync_page_test.js index c173cad..2d79b7ed 100644 --- a/chrome/test/data/webui/settings/people_page_sync_page_test.js +++ b/chrome/test/data/webui/settings/people_page_sync_page_test.js
@@ -10,7 +10,7 @@ import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {PageStatus, Router, routes, StatusAction, SyncBrowserProxyImpl} from 'chrome://settings/settings.js'; import {getSyncAllPrefs, setupRouterWithSyncRoutes, simulateStoredAccounts} from 'chrome://test/settings/sync_test_util.js'; -import {TestSyncBrowserProxy} from 'chrome://test/settings/test_sync_browser_proxy.m.js'; +import {TestSyncBrowserProxy} from 'chrome://test/settings/test_sync_browser_proxy.js'; import {eventToPromise, waitBeforeNextRender} from 'chrome://test/test_util.m.js'; // clang-format on
diff --git a/chrome/test/data/webui/settings/people_page_test.js b/chrome/test/data/webui/settings/people_page_test.js index 7688231..1777078 100644 --- a/chrome/test/data/webui/settings/people_page_test.js +++ b/chrome/test/data/webui/settings/people_page_test.js
@@ -11,8 +11,8 @@ import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {pageVisibility, ProfileInfoBrowserProxyImpl, Router, routes, StatusAction, SyncBrowserProxyImpl} from 'chrome://settings/settings.js'; import {simulateStoredAccounts, simulateSyncStatus} from 'chrome://test/settings/sync_test_util.js'; -import {TestProfileInfoBrowserProxy} from 'chrome://test/settings/test_profile_info_browser_proxy.m.js'; -import {TestSyncBrowserProxy} from 'chrome://test/settings/test_sync_browser_proxy.m.js'; +import {TestProfileInfoBrowserProxy} from 'chrome://test/settings/test_profile_info_browser_proxy.js'; +import {TestSyncBrowserProxy} from 'chrome://test/settings/test_sync_browser_proxy.js'; import {TestBrowserProxy} from 'chrome://test/test_browser_proxy.m.js'; import {waitBeforeNextRender} from 'chrome://test/test_util.m.js'; // clang-format on
diff --git a/chrome/test/data/webui/settings/people_page_test_cros.js b/chrome/test/data/webui/settings/people_page_test_cros.js index 1620655..79aca09 100644 --- a/chrome/test/data/webui/settings/people_page_test_cros.js +++ b/chrome/test/data/webui/settings/people_page_test_cros.js
@@ -8,8 +8,8 @@ import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {AccountManagerBrowserProxyImpl, pageVisibility, ProfileInfoBrowserProxyImpl, Router, SyncBrowserProxyImpl} from 'chrome://settings/settings.js'; import {simulateSyncStatus} from 'chrome://test/settings/sync_test_util.js'; -import {TestProfileInfoBrowserProxy} from 'chrome://test/settings/test_profile_info_browser_proxy.m.js'; -import {TestSyncBrowserProxy} from 'chrome://test/settings/test_sync_browser_proxy.m.js'; +import {TestProfileInfoBrowserProxy} from 'chrome://test/settings/test_profile_info_browser_proxy.js'; +import {TestSyncBrowserProxy} from 'chrome://test/settings/test_sync_browser_proxy.js'; import {TestBrowserProxy} from 'chrome://test/test_browser_proxy.m.js'; // clang-format on
diff --git a/chrome/test/data/webui/settings/personalization_options_test.js b/chrome/test/data/webui/settings/personalization_options_test.js index 2feecc18..edebb90 100644 --- a/chrome/test/data/webui/settings/personalization_options_test.js +++ b/chrome/test/data/webui/settings/personalization_options_test.js
@@ -9,7 +9,7 @@ import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {PrivacyPageBrowserProxyImpl, StatusAction, SyncBrowserProxyImpl} from 'chrome://settings/settings.js'; import {TestPrivacyPageBrowserProxy} from 'chrome://test/settings/test_privacy_page_browser_proxy.js'; -import {TestSyncBrowserProxy} from 'chrome://test/settings/test_sync_browser_proxy.m.js'; +import {TestSyncBrowserProxy} from 'chrome://test/settings/test_sync_browser_proxy.js'; import {eventToPromise, isChildVisible, isVisible} from 'chrome://test/test_util.m.js'; // clang-format on
diff --git a/chrome/test/data/webui/settings/prefs_test_cases.js b/chrome/test/data/webui/settings/prefs_test_cases.js index d6be1ee..f27b2a8b 100644 --- a/chrome/test/data/webui/settings/prefs_test_cases.js +++ b/chrome/test/data/webui/settings/prefs_test_cases.js
@@ -3,7 +3,7 @@ // found in the LICENSE file. // clang-format off -import {FakeSettingsPrivatePref} from 'chrome://test/settings/fake_settings_private.m.js'; +import {FakeSettingsPrivatePref} from 'chrome://test/settings/fake_settings_private.js'; // clang-format on /**
diff --git a/chrome/test/data/webui/settings/prefs_tests.js b/chrome/test/data/webui/settings/prefs_tests.js index faa580f..1f78a5c 100644 --- a/chrome/test/data/webui/settings/prefs_tests.js +++ b/chrome/test/data/webui/settings/prefs_tests.js
@@ -4,7 +4,7 @@ // clang-format off import {CrSettingsPrefs} from 'chrome://settings/settings.js'; -import {FakeSettingsPrivate} from 'chrome://test/settings/fake_settings_private.m.js'; +import {FakeSettingsPrivate} from 'chrome://test/settings/fake_settings_private.js'; import {prefsTestCases} from 'chrome://test/settings/prefs_test_cases.js'; // clang-format on
diff --git a/chrome/test/data/webui/settings/safety_check_page_test.js b/chrome/test/data/webui/settings/safety_check_page_test.js index d269550..53da477 100644 --- a/chrome/test/data/webui/settings/safety_check_page_test.js +++ b/chrome/test/data/webui/settings/safety_check_page_test.js
@@ -12,7 +12,7 @@ import {TestBrowserProxy} from '../test_browser_proxy.m.js'; import {TestHatsBrowserProxy} from './test_hats_browser_proxy.js'; -import {TestLifetimeBrowserProxy} from './test_lifetime_browser_proxy.m.js'; +import {TestLifetimeBrowserProxy} from './test_lifetime_browser_proxy.js'; import {TestMetricsBrowserProxy} from './test_metrics_browser_proxy.js'; import {TestOpenWindowProxy} from './test_open_window_proxy.js'; import {TestPasswordManagerProxy} from './test_password_manager_proxy.js';
diff --git a/chrome/test/data/webui/settings/search_engines_page_test.js b/chrome/test/data/webui/settings/search_engines_page_test.js index b13b3e7..5e59adec 100644 --- a/chrome/test/data/webui/settings/search_engines_page_test.js +++ b/chrome/test/data/webui/settings/search_engines_page_test.js
@@ -9,7 +9,7 @@ import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {ExtensionControlBrowserProxyImpl, SearchEnginesBrowserProxyImpl} from 'chrome://settings/settings.js'; import {TestExtensionControlBrowserProxy} from 'chrome://test/settings/test_extension_control_browser_proxy.js'; -import {TestSearchEnginesBrowserProxy} from 'chrome://test/settings/test_search_engines_browser_proxy.m.js'; +import {TestSearchEnginesBrowserProxy} from 'chrome://test/settings/test_search_engines_browser_proxy.js'; import {eventToPromise} from 'chrome://test/test_util.m.js'; // clang-format on
diff --git a/chrome/test/data/webui/settings/search_page_test.js b/chrome/test/data/webui/settings/search_page_test.js index 3c92a4b2..11200fa 100644 --- a/chrome/test/data/webui/settings/search_page_test.js +++ b/chrome/test/data/webui/settings/search_page_test.js
@@ -11,7 +11,7 @@ import {assertEquals, assertFalse, assertNotReached, assertTrue} from '../chai_assert.js'; -import {createSampleSearchEngine, TestSearchEnginesBrowserProxy} from './test_search_engines_browser_proxy.m.js'; +import {createSampleSearchEngine, TestSearchEnginesBrowserProxy} from './test_search_engines_browser_proxy.js'; // clang-format on
diff --git a/chrome/test/data/webui/settings/sync_account_control_test.js b/chrome/test/data/webui/settings/sync_account_control_test.js index fbc4b00..29b795ae 100644 --- a/chrome/test/data/webui/settings/sync_account_control_test.js +++ b/chrome/test/data/webui/settings/sync_account_control_test.js
@@ -7,7 +7,7 @@ import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {MAX_SIGNIN_PROMO_IMPRESSION, Router, routes, StatusAction, SyncBrowserProxyImpl} from 'chrome://settings/settings.js'; import {setupRouterWithSyncRoutes, simulateStoredAccounts} from 'chrome://test/settings/sync_test_util.js'; -import {TestSyncBrowserProxy} from 'chrome://test/settings/test_sync_browser_proxy.m.js'; +import {TestSyncBrowserProxy} from 'chrome://test/settings/test_sync_browser_proxy.js'; import {isChildVisible, isVisible} from 'chrome://test/test_util.m.js'; // clang-format on
diff --git a/chrome/test/data/webui/settings/system_page_tests.js b/chrome/test/data/webui/settings/system_page_tests.js index 3a72ce1..98d18ac 100644 --- a/chrome/test/data/webui/settings/system_page_tests.js +++ b/chrome/test/data/webui/settings/system_page_tests.js
@@ -7,7 +7,7 @@ import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {SystemPageBrowserProxyImpl} from 'chrome://settings/lazy_load.js'; import {LifetimeBrowserProxyImpl} from 'chrome://settings/settings.js'; -import {TestLifetimeBrowserProxy} from 'chrome://test/settings/test_lifetime_browser_proxy.m.js'; +import {TestLifetimeBrowserProxy} from 'chrome://test/settings/test_lifetime_browser_proxy.js'; import {TestBrowserProxy} from 'chrome://test/test_browser_proxy.m.js'; // clang-format on
diff --git a/chrome/test/data/webui/settings/test_languages_browser_proxy.js b/chrome/test/data/webui/settings/test_languages_browser_proxy.js index 707d3c7..6ff2c1c4 100644 --- a/chrome/test/data/webui/settings/test_languages_browser_proxy.js +++ b/chrome/test/data/webui/settings/test_languages_browser_proxy.js
@@ -3,68 +3,61 @@ // found in the LICENSE file. // clang-format off -// #import {FakeInputMethodPrivate} from './fake_input_method_private.m.js'; -// #import {FakeLanguageSettingsPrivate} from './fake_language_settings_private.m.js'; -// #import {isChromeOS, isWindows} from 'chrome://resources/js/cr.m.js'; -// #import {LanguagesBrowserProxy} from 'chrome://settings/lazy_load.js'; -// #import {TestBrowserProxy} from '../test_browser_proxy.m.js'; +import {isChromeOS, isWindows} from 'chrome://resources/js/cr.m.js'; +import {LanguagesBrowserProxy} from 'chrome://settings/lazy_load.js'; + +import {TestBrowserProxy} from '../test_browser_proxy.m.js'; + +import {FakeInputMethodPrivate} from './fake_input_method_private.js'; +import {FakeLanguageSettingsPrivate} from './fake_language_settings_private.js'; // clang-format on -cr.define('settings', function() { - /** @implements {settings.LanguagesBrowserProxy} */ - /* #export */ class TestLanguagesBrowserProxy extends TestBrowserProxy { - constructor() { - const methodNames = []; - if (cr.isChromeOS || cr.isWindows) { - methodNames.push( - 'getProspectiveUILanguage', 'setProspectiveUILanguage'); - } - - super(methodNames); - - /** @private {!LanguageSettingsPrivate} */ - this.languageSettingsPrivate_ = - new settings.FakeLanguageSettingsPrivate(); - - /** @private {!InputMethodPrivate} */ - this.inputMethodPrivate_ = /** @type{!InputMethodPrivate} */ ( - new settings.FakeInputMethodPrivate()); +/** @implements {LanguagesBrowserProxy} */ +export class TestLanguagesBrowserProxy extends TestBrowserProxy { + constructor() { + const methodNames = []; + if (isChromeOS || isWindows) { + methodNames.push('getProspectiveUILanguage', 'setProspectiveUILanguage'); } - /** @override */ - getLanguageSettingsPrivate() { - return this.languageSettingsPrivate_; - } + super(methodNames); - /** @param {!LanguageSettingsPrivate} languageSettingsPrivate */ - setLanguageSettingsPrivate(languageSettingsPrivate) { - this.languageSettingsPrivate_ = languageSettingsPrivate; - } + /** @private {!LanguageSettingsPrivate} */ + this.languageSettingsPrivate_ = new FakeLanguageSettingsPrivate(); + + /** @private {!InputMethodPrivate} */ + this.inputMethodPrivate_ = + /** @type{!InputMethodPrivate} */ (new FakeInputMethodPrivate()); } - if (cr.isChromeOS || cr.isWindows) { - /** @override */ - TestLanguagesBrowserProxy.prototype.getProspectiveUILanguage = function() { - this.methodCalled('getProspectiveUILanguage'); - return Promise.resolve('en-US'); - }; - - /** @override */ - TestLanguagesBrowserProxy.prototype.setProspectiveUILanguage = function( - language) { - this.methodCalled('setProspectiveUILanguage', language); - }; + /** @override */ + getLanguageSettingsPrivate() { + return this.languageSettingsPrivate_; } - if (cr.isChromeOS) { - /** @override */ - TestLanguagesBrowserProxy.prototype.getInputMethodPrivate = function() { - return this.inputMethodPrivate_; - }; + /** @param {!LanguageSettingsPrivate} languageSettingsPrivate */ + setLanguageSettingsPrivate(languageSettingsPrivate) { + this.languageSettingsPrivate_ = languageSettingsPrivate; } +} - // #cr_define_end - return { - TestLanguagesBrowserProxy: TestLanguagesBrowserProxy, +if (isChromeOS || isWindows) { + /** @override */ + TestLanguagesBrowserProxy.prototype.getProspectiveUILanguage = function() { + this.methodCalled('getProspectiveUILanguage'); + return Promise.resolve('en-US'); }; -}); + + /** @override */ + TestLanguagesBrowserProxy.prototype.setProspectiveUILanguage = function( + language) { + this.methodCalled('setProspectiveUILanguage', language); + }; +} + +if (isChromeOS) { + /** @override */ + TestLanguagesBrowserProxy.prototype.getInputMethodPrivate = function() { + return this.inputMethodPrivate_; + }; +}
diff --git a/chrome/test/data/webui/settings/test_lifetime_browser_proxy.js b/chrome/test/data/webui/settings/test_lifetime_browser_proxy.js index 3a1dda3..7866099d 100644 --- a/chrome/test/data/webui/settings/test_lifetime_browser_proxy.js +++ b/chrome/test/data/webui/settings/test_lifetime_browser_proxy.js
@@ -2,52 +2,46 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// #import {isChromeOS} from 'chrome://resources/js/cr.m.js'; -// #import {TestBrowserProxy} from '../test_browser_proxy.m.js'; -// #import {LifetimeBrowserProxy} from 'chrome://settings/settings.js'; +import {isChromeOS} from 'chrome://resources/js/cr.m.js'; +import {LifetimeBrowserProxy} from 'chrome://settings/settings.js'; -cr.define('settings', function() { - /** - * A test version of LifetimeBrowserProxy. - * - * @implements {settings.LifetimeBrowserProxy} - */ - /* #export */ class TestLifetimeBrowserProxy extends TestBrowserProxy { - constructor() { - const methodNames = ['restart', 'relaunch']; - if (cr.isChromeOS) { - methodNames.push('signOutAndRestart', 'factoryReset'); - } +import {TestBrowserProxy} from '../test_browser_proxy.m.js'; - super(methodNames); +/** + * A test version of LifetimeBrowserProxy. + * + * @implements {LifetimeBrowserProxy} + */ +export class TestLifetimeBrowserProxy extends TestBrowserProxy { + constructor() { + const methodNames = ['restart', 'relaunch']; + if (isChromeOS) { + methodNames.push('signOutAndRestart', 'factoryReset'); } - /** @override */ - restart() { - this.methodCalled('restart'); - } - - /** @override */ - relaunch() { - this.methodCalled('relaunch'); - } + super(methodNames); } - if (cr.isChromeOS) { - /** @override */ - TestLifetimeBrowserProxy.prototype.signOutAndRestart = function() { - this.methodCalled('signOutAndRestart'); - }; - - /** @override */ - TestLifetimeBrowserProxy.prototype.factoryReset = function( - requestTpmFirmwareUpdate) { - this.methodCalled('factoryReset', requestTpmFirmwareUpdate); - }; + /** @override */ + restart() { + this.methodCalled('restart'); } - // #cr_define_end - return { - TestLifetimeBrowserProxy: TestLifetimeBrowserProxy, + /** @override */ + relaunch() { + this.methodCalled('relaunch'); + } +} + +if (isChromeOS) { + /** @override */ + TestLifetimeBrowserProxy.prototype.signOutAndRestart = function() { + this.methodCalled('signOutAndRestart'); }; -}); + + /** @override */ + TestLifetimeBrowserProxy.prototype.factoryReset = function( + requestTpmFirmwareUpdate) { + this.methodCalled('factoryReset', requestTpmFirmwareUpdate); + }; +}
diff --git a/chrome/test/data/webui/settings/test_profile_info_browser_proxy.js b/chrome/test/data/webui/settings/test_profile_info_browser_proxy.js index 9cde7f0..51e0c62 100644 --- a/chrome/test/data/webui/settings/test_profile_info_browser_proxy.js +++ b/chrome/test/data/webui/settings/test_profile_info_browser_proxy.js
@@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// #import {TestBrowserProxy} from 'chrome://test/test_browser_proxy.m.js'; +import {TestBrowserProxy} from 'chrome://test/test_browser_proxy.m.js'; -/** @implements {settings.ProfileInfoBrowserProxy} */ -/* #export */ class TestProfileInfoBrowserProxy extends TestBrowserProxy { +/** @implements {ProfileInfoBrowserProxy} */ +export class TestProfileInfoBrowserProxy extends TestBrowserProxy { constructor() { super([ 'getProfileInfo',
diff --git a/chrome/test/data/webui/settings/test_search_engines_browser_proxy.js b/chrome/test/data/webui/settings/test_search_engines_browser_proxy.js index 705c753..b7a3fa9a 100644 --- a/chrome/test/data/webui/settings/test_search_engines_browser_proxy.js +++ b/chrome/test/data/webui/settings/test_search_engines_browser_proxy.js
@@ -3,108 +3,101 @@ // found in the LICENSE file. // clang-format off -// #import {TestBrowserProxy} from '../test_browser_proxy.m.js'; -// #import {SearchEnginesBrowserProxy, SearchEnginesInfo, SearchEngine} from 'chrome://settings/settings.js'; +import { SearchEngine,SearchEnginesBrowserProxy, SearchEnginesInfo} from 'chrome://settings/settings.js'; + +import {TestBrowserProxy} from '../test_browser_proxy.m.js'; // clang-format on -cr.define('settings_search', function() { - /** - * A test version of SearchEnginesBrowserProxy. Provides helper methods - * for allowing tests to know when a method was called, as well as - * specifying mock responses. - * - * @implements {settings.SearchEnginesBrowserProxy} - */ - /* #export */ class TestSearchEnginesBrowserProxy extends TestBrowserProxy { - constructor() { - super([ - 'getSearchEnginesList', - 'removeSearchEngine', - 'searchEngineEditCancelled', - 'searchEngineEditCompleted', - 'searchEngineEditStarted', - 'setDefaultSearchEngine', - 'validateSearchEngineInput', - ]); +/** + * A test version of SearchEnginesBrowserProxy. Provides helper methods + * for allowing tests to know when a method was called, as well as + * specifying mock responses. + * + * @implements {SearchEnginesBrowserProxy} + */ +export class TestSearchEnginesBrowserProxy extends TestBrowserProxy { + constructor() { + super([ + 'getSearchEnginesList', + 'removeSearchEngine', + 'searchEngineEditCancelled', + 'searchEngineEditCompleted', + 'searchEngineEditStarted', + 'setDefaultSearchEngine', + 'validateSearchEngineInput', + ]); - /** @private {!SearchEnginesInfo} */ - this.searchEnginesInfo_ = {defaults: [], others: [], extensions: []}; - } - - /** @override */ - setDefaultSearchEngine(modelIndex) { - this.methodCalled('setDefaultSearchEngine', modelIndex); - } - - /** @override */ - removeSearchEngine(modelIndex) { - this.methodCalled('removeSearchEngine', modelIndex); - } - - /** @override */ - searchEngineEditStarted(modelIndex) { - this.methodCalled('searchEngineEditStarted', modelIndex); - } - - /** @override */ - searchEngineEditCancelled() { - this.methodCalled('searchEngineEditCancelled'); - } - - /** @override */ - searchEngineEditCompleted(searchEngine, keyword, queryUrl) { - this.methodCalled('searchEngineEditCompleted'); - } - - /** @override */ - getSearchEnginesList() { - this.methodCalled('getSearchEnginesList'); - return Promise.resolve(this.searchEnginesInfo_); - } - - /** @override */ - validateSearchEngineInput(fieldName, fieldValue) { - this.methodCalled('validateSearchEngineInput'); - return Promise.resolve(true); - } - - /** - * Sets the response to be returned by |getSearchEnginesList|. - * @param {!SearchEnginesInfo} searchEnginesInfo - */ - setSearchEnginesInfo(searchEnginesInfo) { - this.searchEnginesInfo_ = searchEnginesInfo; - } + /** @private {!SearchEnginesInfo} */ + this.searchEnginesInfo_ = {defaults: [], others: [], extensions: []}; } + /** @override */ + setDefaultSearchEngine(modelIndex) { + this.methodCalled('setDefaultSearchEngine', modelIndex); + } + + /** @override */ + removeSearchEngine(modelIndex) { + this.methodCalled('removeSearchEngine', modelIndex); + } + + /** @override */ + searchEngineEditStarted(modelIndex) { + this.methodCalled('searchEngineEditStarted', modelIndex); + } + + /** @override */ + searchEngineEditCancelled() { + this.methodCalled('searchEngineEditCancelled'); + } + + /** @override */ + searchEngineEditCompleted(searchEngine, keyword, queryUrl) { + this.methodCalled('searchEngineEditCompleted'); + } + + /** @override */ + getSearchEnginesList() { + this.methodCalled('getSearchEnginesList'); + return Promise.resolve(this.searchEnginesInfo_); + } + + /** @override */ + validateSearchEngineInput(fieldName, fieldValue) { + this.methodCalled('validateSearchEngineInput'); + return Promise.resolve(true); + } + + /** + * Sets the response to be returned by |getSearchEnginesList|. + * @param {!SearchEnginesInfo} searchEnginesInfo + */ + setSearchEnginesInfo(searchEnginesInfo) { + this.searchEnginesInfo_ = searchEnginesInfo; + } +} + /** * @param {boolean} canBeDefault * @param {boolean} canBeEdited * @param {boolean} canBeRemoved * @return {!SearchEngine} */ - /* #export */ function createSampleSearchEngine( - canBeDefault, canBeEdited, canBeRemoved) { - return { - canBeDefault: canBeDefault, - canBeEdited: canBeEdited, - canBeRemoved: canBeRemoved, - default: false, - displayName: 'Google', - iconURL: 'http://www.google.com/favicon.ico', - id: 0, - isOmniboxExtension: false, - keyword: 'google.com', - modelIndex: 0, - name: 'Google', - url: 'https://search.foo.com/search?p=%s', - urlLocked: false, - }; - } - - // #cr_define_end +export function createSampleSearchEngine( + canBeDefault, canBeEdited, canBeRemoved) { return { - createSampleSearchEngine: createSampleSearchEngine, - TestSearchEnginesBrowserProxy: TestSearchEnginesBrowserProxy, + canBeDefault: canBeDefault, + canBeEdited: canBeEdited, + canBeRemoved: canBeRemoved, + default: false, + displayName: 'Google', + iconURL: 'http://www.google.com/favicon.ico', + id: 0, + isOmniboxExtension: false, + keyword: 'google.com', + modelIndex: 0, + name: 'Google', + url: 'https://search.foo.com/search?p=%s', + urlLocked: false, }; -}); +}
diff --git a/chrome/test/data/webui/settings/test_sync_browser_proxy.js b/chrome/test/data/webui/settings/test_sync_browser_proxy.js index 567f747..dcb84105 100644 --- a/chrome/test/data/webui/settings/test_sync_browser_proxy.js +++ b/chrome/test/data/webui/settings/test_sync_browser_proxy.js
@@ -3,13 +3,14 @@ // found in the LICENSE file. // clang-format off -// #import {PageStatus, StoredAccount, SyncBrowserProxy, SyncStatus} from 'chrome://settings/settings.js'; -// #import {TestBrowserProxy} from '../test_browser_proxy.m.js'; -// #import {isChromeOS} from 'chrome://resources/js/cr.m.js'; +import {isChromeOS} from 'chrome://resources/js/cr.m.js'; +import {PageStatus, StoredAccount, SyncBrowserProxy, SyncStatus} from 'chrome://settings/settings.js'; + +import {TestBrowserProxy} from '../test_browser_proxy.m.js'; // clang-format on -/** @implements {settings.SyncBrowserProxy} */ -/* #export */ class TestSyncBrowserProxy extends TestBrowserProxy { +/** @implements {SyncBrowserProxy} */ +export class TestSyncBrowserProxy extends TestBrowserProxy { constructor() { const methodNames = [ 'didNavigateAwayFromSyncPage', @@ -28,7 +29,7 @@ 'startSyncingWithEmail', ]; - if (cr.isChromeOS) { + if (isChromeOS) { methodNames.push('turnOnSync', 'turnOffSync'); } @@ -42,10 +43,10 @@ this.encryptionPassphraseSuccess = false; /** @type {boolean} */ this.decryptionPassphraseSuccess = false; - /** @type {!Array<!settings.StoredAccount>} */ + /** @type {!Array<!StoredAccount>} */ this.storedAccounts = []; - /** @type {!settings.SyncStatus} */ - this.syncStatus = /** @type {!settings.SyncStatus} */ ( + /** @type {!SyncStatus} */ + this.syncStatus = /** @type {!SyncStatus} */ ( {signedIn: true, signedInUsername: 'fakeUsername'}); } @@ -110,7 +111,7 @@ /** @override */ setSyncDatatypes(syncPrefs) { this.methodCalled('setSyncDatatypes', syncPrefs); - return Promise.resolve(settings.PageStatus.CONFIGURE); + return Promise.resolve(PageStatus.CONFIGURE); } /** @override */ @@ -140,7 +141,7 @@ startKeyRetrieval() {} } -if (cr.isChromeOS) { +if (isChromeOS) { /** @override */ TestSyncBrowserProxy.prototype.turnOnSync = function() { this.methodCalled('turnOnSync');
diff --git a/chromecast/browser/accessibility/flutter/ax_tree_source_flutter_unittest.cc b/chromecast/browser/accessibility/flutter/ax_tree_source_flutter_unittest.cc index 951a480..e4cf2c2 100644 --- a/chromecast/browser/accessibility/flutter/ax_tree_source_flutter_unittest.cc +++ b/chromecast/browser/accessibility/flutter/ax_tree_source_flutter_unittest.cc
@@ -6,6 +6,8 @@ #include <string> +#include "base/unguessable_token.h" +#include "base/util/values/values_util.h" #include "chromecast/browser/accessibility/flutter/flutter_semantics_node_wrapper.h" #include "content/public/browser/content_browser_client.h" #include "content/public/browser/tts_controller.h" @@ -475,7 +477,12 @@ child = AddChild(&event2, root2, 2, 0, 0, 400, 600, false); child = AddChild(&event2, root2, 3, 400, 0, 400, 600, false); child = AddChild(&event2, root2, 4, 0, 0, 200, 200, false); - child->set_plugin_id("1234"); + + // We need a plugin id that is the right length. Here we use + base::UnguessableToken token = base::UnguessableToken::Create(); + std::string token_to_string = + util::UnguessableTokenToValue(token).GetString(); + child->set_plugin_id(token_to_string); // focus should move to node with child tree CallNotifyAccessibilityEvent(&event2);
diff --git a/chromecast/browser/accessibility/flutter/flutter_semantics_node_wrapper.cc b/chromecast/browser/accessibility/flutter/flutter_semantics_node_wrapper.cc index 762adb5..a099473 100644 --- a/chromecast/browser/accessibility/flutter/flutter_semantics_node_wrapper.cc +++ b/chromecast/browser/accessibility/flutter/flutter_semantics_node_wrapper.cc
@@ -418,16 +418,14 @@ for (CastWebContents* contents : all_contents) { if (contents->id() == web_contents_id) { content::WebContents* web_contents = contents->web_contents(); - out_data->AddStringAttribute( - ax::mojom::StringAttribute::kChildTreeId, - web_contents->GetMainFrame()->GetAXTreeID().ToString()); + out_data->AddChildTreeId(web_contents->GetMainFrame()->GetAXTreeID()); break; } } } else { // Use the value as a tree id. - out_data->AddStringAttribute(ax::mojom::StringAttribute::kChildTreeId, - ax_tree_id); + ui::AXTreeID child_ax_tree_id = ui::AXTreeID::FromString(ax_tree_id); + out_data->AddChildTreeId(child_ax_tree_id); } }
diff --git a/chromeos/network/cellular_esim_connection_handler.cc b/chromeos/network/cellular_esim_connection_handler.cc index 823604f..23d399a 100644 --- a/chromeos/network/cellular_esim_connection_handler.cc +++ b/chromeos/network/cellular_esim_connection_handler.cc
@@ -270,6 +270,7 @@ TransitionToConnectionState(ConnectionState::kInhibitingScans); cellular_inhibitor_->InhibitCellularScanning( + CellularInhibitor::InhibitReason::kConnectingToProfile, base::BindOnce(&CellularESimConnectionHandler::OnInhibitScanResult, weak_ptr_factory_.GetWeakPtr())); }
diff --git a/chromeos/network/cellular_esim_connection_handler_unittest.cc b/chromeos/network/cellular_esim_connection_handler_unittest.cc index 791d317..38606628c1 100644 --- a/chromeos/network/cellular_esim_connection_handler_unittest.cc +++ b/chromeos/network/cellular_esim_connection_handler_unittest.cc
@@ -184,11 +184,14 @@ std::unique_ptr<CellularInhibitor::InhibitLock> InhibitCellular() { base::RunLoop run_loop; std::unique_ptr<CellularInhibitor::InhibitLock> inhibit_lock; - inhibitor_.InhibitCellularScanning(base::BindLambdaForTesting( - [&](std::unique_ptr<CellularInhibitor::InhibitLock> new_inhibit_lock) { - inhibit_lock = std::move(new_inhibit_lock); - run_loop.Quit(); - })); + inhibitor_.InhibitCellularScanning( + CellularInhibitor::InhibitReason::kRemovingProfile, + base::BindLambdaForTesting( + [&](std::unique_ptr<CellularInhibitor::InhibitLock> + new_inhibit_lock) { + inhibit_lock = std::move(new_inhibit_lock); + run_loop.Quit(); + })); run_loop.Run(); return inhibit_lock; }
diff --git a/chromeos/network/cellular_esim_uninstall_handler.cc b/chromeos/network/cellular_esim_uninstall_handler.cc index bdff4e8..2660cd9 100644 --- a/chromeos/network/cellular_esim_uninstall_handler.cc +++ b/chromeos/network/cellular_esim_uninstall_handler.cc
@@ -135,6 +135,7 @@ void CellularESimUninstallHandler::AttemptShillInhibit() { cellular_inhibitor_->InhibitCellularScanning( + CellularInhibitor::InhibitReason::kRemovingProfile, base::BindOnce(&CellularESimUninstallHandler::OnShillInhibit, weak_ptr_factory_.GetWeakPtr())); }
diff --git a/chromeos/network/cellular_inhibitor.cc b/chromeos/network/cellular_inhibitor.cc index 3887477..b07a2bd 100644 --- a/chromeos/network/cellular_inhibitor.cc +++ b/chromeos/network/cellular_inhibitor.cc
@@ -5,6 +5,7 @@ #include "chromeos/network/cellular_inhibitor.h" #include <memory> +#include <sstream> #include "base/bind.h" #include "base/callback_helpers.h" @@ -27,6 +28,14 @@ } // namespace +CellularInhibitor::InhibitRequest::InhibitRequest( + InhibitReason inhibit_reason, + InhibitCallback inhibit_callback) + : inhibit_reason(inhibit_reason), + inhibit_callback(std::move(inhibit_callback)) {} + +CellularInhibitor::InhibitRequest::~InhibitRequest() = default; + CellularInhibitor::InhibitLock::InhibitLock(base::OnceClosure unlock_callback) : unlock_callback_(std::move(unlock_callback)) {} @@ -49,11 +58,38 @@ network_state_handler_->AddObserver(this, FROM_HERE); } -void CellularInhibitor::InhibitCellularScanning(InhibitCallback callback) { - inhibit_requests_.push(std::move(callback)); +void CellularInhibitor::InhibitCellularScanning(InhibitReason reason, + InhibitCallback callback) { + inhibit_requests_.push( + std::make_unique<InhibitRequest>(reason, std::move(callback))); ProcessRequests(); } +base::Optional<CellularInhibitor::InhibitReason> +CellularInhibitor::GetInhibitReason() const { + if (state_ == State::kIdle) + return base::nullopt; + + return inhibit_requests_.front()->inhibit_reason; +} + +void CellularInhibitor::AddObserver(Observer* observer) { + observer_list_.AddObserver(observer); +} + +void CellularInhibitor::RemoveObserver(Observer* observer) { + observer_list_.RemoveObserver(observer); +} + +bool CellularInhibitor::HasObserver(Observer* observer) const { + return observer_list_.HasObserver(observer); +} + +void CellularInhibitor::NotifyInhibitStateChanged() { + for (auto& observer : observer_list_) + observer.OnInhibitStateChanged(); +} + void CellularInhibitor::DeviceListChanged() { CheckScanningIfNeeded(); } @@ -68,8 +104,24 @@ } void CellularInhibitor::TransitionToState(State state) { - NET_LOG(EVENT) << "CellularInhibitor state: " << state_ << " => " << state; + State old_state = state_; state_ = state; + + bool was_inhibited = old_state != State::kIdle; + bool is_inhibited = state_ != State::kIdle; + + std::stringstream ss; + ss << "CellularInhibitor state: " << old_state << " => " << state_; + + if (!is_inhibited) { + DCHECK(!GetInhibitReason()); + NET_LOG(EVENT) << ss.str(); + } else { + NET_LOG(EVENT) << ss.str() << state_ << ", reason: " << *GetInhibitReason(); + } + + if (was_inhibited != is_inhibited) + NotifyInhibitStateChanged(); } void CellularInhibitor::ProcessRequests() { @@ -95,11 +147,11 @@ std::unique_ptr<InhibitLock> lock = std::make_unique<InhibitLock>( base::BindOnce(&CellularInhibitor::AttemptUninhibit, weak_ptr_factory_.GetWeakPtr(), /*attempts_so_far=*/0)); - std::move(inhibit_requests_.front()).Run(std::move(lock)); + std::move(inhibit_requests_.front()->inhibit_callback).Run(std::move(lock)); return; } - std::move(inhibit_requests_.front()).Run(nullptr); + std::move(inhibit_requests_.front()->inhibit_callback).Run(nullptr); PopRequestAndProcessNext(); } @@ -246,3 +298,26 @@ } } // namespace chromeos + +std::ostream& operator<<( + std::ostream& stream, + const chromeos::CellularInhibitor::InhibitReason& inhibit_reason) { + switch (inhibit_reason) { + case chromeos::CellularInhibitor::InhibitReason::kInstallingProfile: + stream << "[Installing profile]"; + break; + case chromeos::CellularInhibitor::InhibitReason::kRenamingProfile: + stream << "[Renaming profile]"; + break; + case chromeos::CellularInhibitor::InhibitReason::kRemovingProfile: + stream << "[Removing profile]"; + break; + case chromeos::CellularInhibitor::InhibitReason::kConnectingToProfile: + stream << "[Connecting to profile]"; + break; + case chromeos::CellularInhibitor::InhibitReason::kRefreshingProfileList: + stream << "[Refreshing profile list]"; + break; + } + return stream; +}
diff --git a/chromeos/network/cellular_inhibitor.h b/chromeos/network/cellular_inhibitor.h index d73d940..7d455856 100644 --- a/chromeos/network/cellular_inhibitor.h +++ b/chromeos/network/cellular_inhibitor.h
@@ -8,6 +8,8 @@ #include "base/component_export.h" #include "base/containers/queue.h" #include "base/memory/weak_ptr.h" +#include "base/observer_list.h" +#include "base/observer_list_types.h" #include "chromeos/network/network_handler_callbacks.h" #include "chromeos/network/network_state_handler_observer.h" @@ -50,6 +52,23 @@ base::OnceClosure unlock_callback_; }; + class Observer : public base::CheckedObserver { + public: + ~Observer() override = default; + + // Invoked when the inhibit state has changed; observers should use the + // GetInhibitReason() function to determine the current state. + virtual void OnInhibitStateChanged() = 0; + }; + + enum class InhibitReason { + kInstallingProfile, + kRenamingProfile, + kRemovingProfile, + kConnectingToProfile, + kRefreshingProfileList + }; + // Callback which returns InhibitLock on inhibit success or nullptr on // failure. using InhibitCallback = @@ -58,9 +77,31 @@ // Puts the Cellular device in Inhibited state and returns an InhibitLock // object which when destroyed automatically uninhibits the Cellular device. A // call to this method will block until the last issues lock is deleted. - void InhibitCellularScanning(InhibitCallback callback); + void InhibitCellularScanning(InhibitReason reason, InhibitCallback callback); + + // Returns the reason that cellular scanning is currently inhibited, or null + // if it is not inhibited. + base::Optional<InhibitReason> GetInhibitReason() const; + + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + bool HasObserver(Observer* observer) const; + + protected: + void NotifyInhibitStateChanged(); private: + struct InhibitRequest { + InhibitRequest(InhibitReason inhibit_reason, + InhibitCallback inhibit_callback); + InhibitRequest(const InhibitRequest&) = delete; + InhibitRequest& operator=(const InhibitRequest&) = delete; + ~InhibitRequest(); + + InhibitReason inhibit_reason; + InhibitCallback inhibit_callback; + }; + enum class State { kIdle, kInhibiting, @@ -105,11 +146,17 @@ NetworkDeviceHandler* network_device_handler_ = nullptr; State state_ = State::kIdle; - base::queue<InhibitCallback> inhibit_requests_; + base::queue<std::unique_ptr<InhibitRequest>> inhibit_requests_; + + base::ObserverList<Observer> observer_list_; base::WeakPtrFactory<CellularInhibitor> weak_ptr_factory_{this}; }; } // namespace chromeos +std::ostream& operator<<( + std::ostream& stream, + const chromeos::CellularInhibitor::InhibitReason& inhibit_reason); + #endif // CHROMEOS_NETWORK_CELLULAR_INHIBITOR_H_
diff --git a/chromeos/network/cellular_inhibitor_unittest.cc b/chromeos/network/cellular_inhibitor_unittest.cc index 920279eb..3c3b02fe 100644 --- a/chromeos/network/cellular_inhibitor_unittest.cc +++ b/chromeos/network/cellular_inhibitor_unittest.cc
@@ -30,6 +30,20 @@ enum class GetInhibitedPropertyResult { kTrue, kFalse, kOperationFailed }; +class TestObserver : public CellularInhibitor::Observer { + public: + TestObserver() = default; + ~TestObserver() override = default; + + size_t num_observer_events() const { return num_observer_events_; } + + private: + // CellularInhibitor::Observer: + void OnInhibitStateChanged() override { ++num_observer_events_; } + + size_t num_observer_events_ = 0u; +}; + } // namespace class CellularInhibitorTest : public testing::Test { @@ -45,35 +59,43 @@ helper_.device_test()->ClearDevices(); cellular_inhibitor_.Init(helper_.network_state_handler(), helper_.network_device_handler()); + cellular_inhibitor_.AddObserver(&observer_); } + void TearDown() override { cellular_inhibitor_.RemoveObserver(&observer_); } + void AddCellularDevice() { helper_.device_test()->AddDevice(kDefaultCellularDevicePath, shill::kTypeCellular, "cellular1"); base::RunLoop().RunUntilIdle(); } - std::unique_ptr<CellularInhibitor::InhibitLock> - InhibitCellularScanningSync() { + std::unique_ptr<CellularInhibitor::InhibitLock> InhibitCellularScanningSync( + CellularInhibitor::InhibitReason inhibit_reason) { base::RunLoop run_loop; std::unique_ptr<CellularInhibitor::InhibitLock> inhibit_lock; - cellular_inhibitor_.InhibitCellularScanning(base::BindLambdaForTesting( - [&](std::unique_ptr<CellularInhibitor::InhibitLock> result) { - inhibit_lock = std::move(result); - run_loop.Quit(); - })); + cellular_inhibitor_.InhibitCellularScanning( + inhibit_reason, + base::BindLambdaForTesting( + [&](std::unique_ptr<CellularInhibitor::InhibitLock> result) { + inhibit_lock = std::move(result); + run_loop.Quit(); + })); run_loop.Run(); return inhibit_lock; } void InhibitCellularScanning( + CellularInhibitor::InhibitReason inhibit_reason, std::unique_ptr<CellularInhibitor::InhibitLock>& lock) { - cellular_inhibitor_.InhibitCellularScanning(base::BindLambdaForTesting( - [&](std::unique_ptr<CellularInhibitor::InhibitLock> result) { - lock = std::move(result); - })); + cellular_inhibitor_.InhibitCellularScanning( + inhibit_reason, + base::BindLambdaForTesting( + [&](std::unique_ptr<CellularInhibitor::InhibitLock> result) { + lock = std::move(result); + })); } void SetScanning(bool is_scanning) { @@ -101,6 +123,14 @@ : GetInhibitedPropertyResult::kFalse; } + base::Optional<CellularInhibitor::InhibitReason> GetInhibitReason() const { + return cellular_inhibitor_.GetInhibitReason(); + } + + size_t GetNumObserverEvents() const { + return observer_.num_observer_events(); + } + private: void GetPropertiesCallback(const std::string& device_path, base::Optional<base::Value> properties) { @@ -116,6 +146,7 @@ base::test::SingleThreadTaskEnvironment task_environment_; NetworkStateTestHelper helper_; CellularInhibitor cellular_inhibitor_; + TestObserver observer_; std::unique_ptr<base::DictionaryValue> properties_; }; @@ -124,16 +155,33 @@ AddCellularDevice(); std::unique_ptr<CellularInhibitor::InhibitLock> inhibit_lock = - InhibitCellularScanningSync(); + InhibitCellularScanningSync( + CellularInhibitor::InhibitReason::kInstallingProfile); // Ensure that a valid lock is returned and Inhibit property is set on // Cellular device. EXPECT_TRUE(inhibit_lock); + EXPECT_EQ(1u, GetNumObserverEvents()); + EXPECT_EQ(CellularInhibitor::InhibitReason::kInstallingProfile, + GetInhibitReason()); EXPECT_EQ(GetInhibitedPropertyResult::kTrue, GetInhibitedProperty()); // Ensure that deleting lock uninhibits the Cellular device. inhibit_lock.reset(); base::RunLoop().RunUntilIdle(); EXPECT_EQ(GetInhibitedPropertyResult::kFalse, GetInhibitedProperty()); + + // At this point, we are still in the inhibited state, since scanning has not + // yet started and stopped. + EXPECT_EQ(1u, GetNumObserverEvents()); + EXPECT_EQ(CellularInhibitor::InhibitReason::kInstallingProfile, + GetInhibitReason()); + + // Start and stop scanning; this should alert observers that the inhibit + // operation has completed. + SetScanning(true); + SetScanning(false); + EXPECT_EQ(2u, GetNumObserverEvents()); + EXPECT_FALSE(GetInhibitReason().has_value()); } TEST_F(CellularInhibitorTest, SuccessMultipleRequests) { @@ -142,13 +190,18 @@ // Make two inhibit requests in parallel. std::unique_ptr<CellularInhibitor::InhibitLock> inhibit_lock; std::unique_ptr<CellularInhibitor::InhibitLock> inhibit_lock2; - InhibitCellularScanning(inhibit_lock); - InhibitCellularScanning(inhibit_lock2); + InhibitCellularScanning(CellularInhibitor::InhibitReason::kInstallingProfile, + inhibit_lock); + InhibitCellularScanning(CellularInhibitor::InhibitReason::kRemovingProfile, + inhibit_lock2); base::RunLoop().RunUntilIdle(); // Ensure that the only one inhibit lock has been granted. EXPECT_TRUE(inhibit_lock); EXPECT_FALSE(inhibit_lock2); + EXPECT_EQ(1u, GetNumObserverEvents()); + EXPECT_EQ(CellularInhibitor::InhibitReason::kInstallingProfile, + GetInhibitReason()); EXPECT_EQ(GetInhibitedPropertyResult::kTrue, GetInhibitedProperty()); // Release the first lock; though this causes the Inhibited property to false, @@ -156,6 +209,9 @@ // flow has not yet started. inhibit_lock.reset(); base::RunLoop().RunUntilIdle(); + EXPECT_EQ(1u, GetNumObserverEvents()); + EXPECT_EQ(CellularInhibitor::InhibitReason::kInstallingProfile, + GetInhibitReason()); EXPECT_EQ(GetInhibitedPropertyResult::kFalse, GetInhibitedProperty()); EXPECT_FALSE(inhibit_lock2); @@ -163,6 +219,9 @@ // inhibit flow within Shill. This still should not start the next inhibit // flow. SetScanning(true); + EXPECT_EQ(1u, GetNumObserverEvents()); + EXPECT_EQ(CellularInhibitor::InhibitReason::kInstallingProfile, + GetInhibitReason()); EXPECT_EQ(GetInhibitedPropertyResult::kFalse, GetInhibitedProperty()); EXPECT_FALSE(inhibit_lock2); @@ -170,11 +229,17 @@ // set. SetScanning(false); EXPECT_TRUE(inhibit_lock2); + EXPECT_EQ(3u, GetNumObserverEvents()); + EXPECT_EQ(CellularInhibitor::InhibitReason::kRemovingProfile, + GetInhibitReason()); EXPECT_EQ(GetInhibitedPropertyResult::kTrue, GetInhibitedProperty()); // Ensure that inhibited property is set to false when all locks are deleted. inhibit_lock2.reset(); base::RunLoop().RunUntilIdle(); + EXPECT_EQ(3u, GetNumObserverEvents()); + EXPECT_EQ(CellularInhibitor::InhibitReason::kRemovingProfile, + GetInhibitReason()); EXPECT_EQ(GetInhibitedPropertyResult::kFalse, GetInhibitedProperty()); } @@ -183,7 +248,8 @@ // since the device cannot be inhibited if it does not exist. std::unique_ptr<CellularInhibitor::InhibitLock> inhibit_lock = - InhibitCellularScanningSync(); + InhibitCellularScanningSync( + CellularInhibitor::InhibitReason::kInstallingProfile); EXPECT_EQ(GetInhibitedPropertyResult::kOperationFailed, GetInhibitedProperty()); EXPECT_FALSE(inhibit_lock);
diff --git a/chromeos/network/cellular_metrics_logger.cc b/chromeos/network/cellular_metrics_logger.cc index 0a24063..07a007f 100644 --- a/chromeos/network/cellular_metrics_logger.cc +++ b/chromeos/network/cellular_metrics_logger.cc
@@ -99,10 +99,60 @@ } } +CellularMetricsLogger::SimType CellularMetricsLogger::GetSimType( + const NetworkState* network) { + return network->eid().empty() ? SimType::kPSim : SimType::kESim; +} + +CellularMetricsLogger::ConnectResult +CellularMetricsLogger::NetworkConnectionErrorToConnectResult( + const std::string& error_name) { + if (error_name == NetworkConnectionHandler::kErrorNotFound) + return CellularMetricsLogger::ConnectResult::kInvalidGuid; + + if (error_name == NetworkConnectionHandler::kErrorConnected || + error_name == NetworkConnectionHandler::kErrorConnecting) { + return CellularMetricsLogger::ConnectResult::kInvalidState; + } + + if (error_name == NetworkConnectionHandler::kErrorConnectCanceled) + return CellularMetricsLogger::ConnectResult::kCanceled; + + if (error_name == NetworkConnectionHandler::kErrorPassphraseRequired || + error_name == NetworkConnectionHandler::kErrorBadPassphrase || + error_name == NetworkConnectionHandler::kErrorCertificateRequired || + error_name == NetworkConnectionHandler::kErrorConfigurationRequired || + error_name == NetworkConnectionHandler::kErrorAuthenticationRequired || + error_name == NetworkConnectionHandler::kErrorCertLoadTimeout || + error_name == NetworkConnectionHandler::kErrorConfigureFailed) { + return CellularMetricsLogger::ConnectResult::kNotConfigured; + } + + if (error_name == NetworkConnectionHandler::kErrorBlockedByPolicy) + return CellularMetricsLogger::ConnectResult::kBlocked; + + return CellularMetricsLogger::ConnectResult::kUnknown; +} + +void CellularMetricsLogger::LogCellularConnectionSuccessHistogram( + CellularMetricsLogger::ConnectResult start_connect_result, + CellularMetricsLogger::SimType sim_type) { + if (sim_type == SimType::kPSim) { + UMA_HISTOGRAM_ENUMERATION("Network.Cellular.PSim.ConnectionSuccess", + start_connect_result); + } else { + UMA_HISTOGRAM_ENUMERATION("Network.Cellular.ESim.ConnectionSuccess", + start_connect_result); + } +} + CellularMetricsLogger::ConnectionInfo::ConnectionInfo( const std::string& network_guid, - bool is_connected) - : network_guid(network_guid), is_connected(is_connected) {} + bool is_connected, + bool is_connecting) + : network_guid(network_guid), + is_connected(is_connected), + is_connecting(is_connecting) {} CellularMetricsLogger::ConnectionInfo::ConnectionInfo( const std::string& network_guid) @@ -191,7 +241,8 @@ guid_to_connection_info_map_.insert_or_assign( guid, - std::make_unique<ConnectionInfo>(guid, network->IsConnectedState())); + std::make_unique<ConnectionInfo>(guid, network->IsConnectedState(), + network->IsConnectingState())); } } @@ -233,6 +284,10 @@ } CheckForTimeToConnectedMetric(network); + // Check for connection failures triggered by shill changes, unlike in + // ConnectFailed() which is triggered by connection attempt failures at + // chrome layers. + CheckForShillConnectionFailureMetric(network); CheckForConnectionStateMetric(network); } @@ -258,9 +313,16 @@ return; if (network->IsConnectedState()) { - UMA_HISTOGRAM_MEDIUM_TIMES( - "Network.Cellular.Connection.TimeToConnected", - base::TimeTicks::Now() - *connection_info->last_connect_start_time); + base::TimeDelta time_to_connected = + base::TimeTicks::Now() - *connection_info->last_connect_start_time; + + if (GetSimType(network) == SimType::kPSim) { + UMA_HISTOGRAM_MEDIUM_TIMES("Network.Cellular.PSim.TimeToConnected", + time_to_connected); + } else { + UMA_HISTOGRAM_MEDIUM_TIMES("Network.Cellular.ESim.TimeToConnected", + time_to_connected); + } } // This is hit when the network is no longer in connecting state, @@ -269,6 +331,22 @@ connection_info->last_connect_start_time.reset(); } +void CellularMetricsLogger::ConnectFailed(const std::string& service_path, + const std::string& error_name) { + const NetworkState* network = + network_state_handler_->GetNetworkState(service_path); + if (!network || network->type().empty() || + !network->Matches(NetworkTypePattern::Cellular())) { + return; + } + + // Check for connection failures at chrome layers, instead of connection + // failures triggered by shill which is tracked in + // CheckForShillConnectionFailureMetric(). + LogCellularConnectionSuccessHistogram( + NetworkConnectionErrorToConnectResult(error_name), GetSimType(network)); +} + void CellularMetricsLogger::DisconnectRequested( const std::string& service_path) { const NetworkState* network = @@ -301,9 +379,31 @@ } void CellularMetricsLogger::LogCellularDisconnectionsHistogram( - ConnectionState connection_state) { - UMA_HISTOGRAM_ENUMERATION("Network.Cellular.Connection.Disconnections", - connection_state); + ConnectionState connection_state, + CellularMetricsLogger::SimType sim_type) { + if (sim_type == SimType::kPSim) { + UMA_HISTOGRAM_ENUMERATION("Network.Cellular.PSim.Disconnections", + connection_state); + } else { + UMA_HISTOGRAM_ENUMERATION("Network.Cellular.ESim.Disconnections", + connection_state); + } +} + +void CellularMetricsLogger::CheckForShillConnectionFailureMetric( + const NetworkState* network) { + ConnectionInfo* connection_info = + GetConnectionInfoForCellularNetwork(network->guid()); + + // If the network connection state just failed. + if (!network->IsConnectingOrConnected() && connection_info->is_connecting) { + // Note: Currently all shill errors that result in a connection failure are + // mapped to CellularMetricsLogger::ConnectResult::kUnknown. + LogCellularConnectionSuccessHistogram( + CellularMetricsLogger::ConnectResult::kUnknown, GetSimType(network)); + } + + connection_info->is_connecting = network->IsConnectingState(); } void CellularMetricsLogger::CheckForConnectionStateMetric( @@ -318,7 +418,10 @@ connection_info->is_connected = new_is_connected; if (new_is_connected) { - LogCellularDisconnectionsHistogram(ConnectionState::kConnected); + LogCellularConnectionSuccessHistogram( + CellularMetricsLogger::ConnectResult::kSuccess, GetSimType(network)); + LogCellularDisconnectionsHistogram(ConnectionState::kConnected, + GetSimType(network)); connection_info->last_disconnect_request_time.reset(); return; } @@ -342,7 +445,8 @@ time_since_disconnect_requested < kDisconnectRequestTimeout) { return; } - LogCellularDisconnectionsHistogram(ConnectionState::kDisconnected); + LogCellularDisconnectionsHistogram(ConnectionState::kDisconnected, + GetSimType(network)); } void CellularMetricsLogger::CheckForESimProfileStatusMetric() { @@ -428,7 +532,7 @@ size_t esim_profiles = 0; for (const auto* network : network_list) { - if (!network->eid().empty()) + if (GetSimType(network) == SimType::kESim) esim_profiles++; else psim_networks++;
diff --git a/chromeos/network/cellular_metrics_logger.h b/chromeos/network/cellular_metrics_logger.h index a1a49e3..5b1be1d 100644 --- a/chromeos/network/cellular_metrics_logger.h +++ b/chromeos/network/cellular_metrics_logger.h
@@ -75,10 +75,13 @@ void OnShuttingDown() override; // NetworkConnectionObserver:: + void ConnectFailed(const std::string& service_path, + const std::string& error_name) override; void DisconnectRequested(const std::string& service_path) override; private: friend class CellularMetricsLoggerTest; + FRIEND_TEST_ALL_PREFIXES(CellularMetricsLoggerTest, CellularConnectResult); FRIEND_TEST_ALL_PREFIXES(CellularMetricsLoggerTest, CellularESimProfileStatusAtLoginTest); FRIEND_TEST_ALL_PREFIXES(CellularMetricsLoggerTest, @@ -109,10 +112,13 @@ // Stores connection related information for a cellular network. struct ConnectionInfo { ConnectionInfo(const std::string& network_guid); - ConnectionInfo(const std::string& network_guid, bool is_connected); + ConnectionInfo(const std::string& network_guid, + bool is_connected, + bool is_connecting); ~ConnectionInfo(); const std::string network_guid; base::Optional<bool> is_connected; + base::Optional<bool> is_connecting; base::Optional<base::TimeTicks> last_disconnect_request_time; base::Optional<base::TimeTicks> last_connect_start_time; }; @@ -124,7 +130,7 @@ }; // Usage type for cellular network. These values are persisted to logs. - // Entries should not be renumbered and numberic values should never + // Entries should not be renumbered and numeric values should never // be reused. enum class CellularUsage { kConnectedAndOnlyNetwork = 0, @@ -157,7 +163,7 @@ }; // Cellular connection state. These values are persisted to logs. - // Entries should not be renumbered and numberic values should + // Entries should not be renumbered and numeric values should // never be reused. enum class ConnectionState { kConnected = 0, @@ -184,6 +190,22 @@ kMaxValue = kErrorUnknown, }; + // Result of connecting to a cellular network. These values are persisted to + // logs. Entries should not be renumbered and numeric values should never be + // reused. + enum class ConnectResult { + kUnknown = 0, + kInvalidGuid = 1, + kInvalidState = 2, + kCanceled = 3, + kNotConfigured = 4, + kBlocked = 5, + kSuccess = 6, + kMaxValue = kSuccess + }; + + SimType GetSimType(const NetworkState* network); + // Convert shill error name string to SimPinOperationResult enum. static SimPinOperationResult GetSimPinOperationResultForShillError( const std::string& shill_error_name); @@ -191,8 +213,18 @@ // Convert shill activation state string to PSimActivationState enum PSimActivationState PSimActivationStateToEnum(const std::string& state); + // Converts a NetworkConnectionHandler string error to a ConnectResult enum. + ConnectResult NetworkConnectionErrorToConnectResult( + const std::string& error_name); + // Helper method to save cellular disconnections histogram. - void LogCellularDisconnectionsHistogram(ConnectionState connection_state); + void LogCellularDisconnectionsHistogram( + ConnectionState connection_state, + CellularMetricsLogger::SimType sim_type); + + void LogCellularConnectionSuccessHistogram( + ConnectResult start_connect_result, + CellularMetricsLogger::SimType sim_type); void OnInitializationTimeout(); @@ -211,6 +243,9 @@ // if |is_esim_profile_status_logged_| is false. void CheckForESimProfileStatusMetric(); + // Tracks errors from shill that result in an unsuccessful connection. + void CheckForShillConnectionFailureMetric(const NetworkState* network); + // This checks the state of connected networks and logs // cellular network usage histogram. Histogram is only logged // when usage state changes.
diff --git a/chromeos/network/cellular_metrics_logger_unittest.cc b/chromeos/network/cellular_metrics_logger_unittest.cc index ee4adb4f..aa4a6363 100644 --- a/chromeos/network/cellular_metrics_logger_unittest.cc +++ b/chromeos/network/cellular_metrics_logger_unittest.cc
@@ -12,6 +12,7 @@ #include "base/test/task_environment.h" #include "chromeos/login/login_state/login_state.h" #include "chromeos/network/cellular_esim_profile.h" +#include "chromeos/network/network_connection_handler.h" #include "chromeos/network/network_state_handler.h" #include "chromeos/network/network_state_test_helper.h" #include "chromeos/network/test_cellular_esim_profile_handler.h" @@ -46,10 +47,20 @@ const char kESimStatusAtLoginHistogram[] = "Network.Cellular.ESim.StatusAtLogin"; -const char kTimeToConnectedHistogram[] = - "Network.Cellular.Connection.TimeToConnected"; -const char kDisconnectionsHistogram[] = - "Network.Cellular.Connection.Disconnections"; +const char kPSimTimeToConnectedHistogram[] = + "Network.Cellular.PSim.TimeToConnected"; +const char kESimTimeToConnectedHistogram[] = + "Network.Cellular.ESim.TimeToConnected"; + +const char kPSimDisconnectionsHistogram[] = + "Network.Cellular.PSim.Disconnections"; +const char kESimDisconnectionsHistogram[] = + "Network.Cellular.ESim.Disconnections"; + +const char kPSimConnectionSuccessHistogram[] = + "Network.Cellular.PSim.ConnectionSuccess"; +const char kESimConnectionSuccessHistogram[] = + "Network.Cellular.ESim.ConnectionSuccess"; } // namespace @@ -466,6 +477,84 @@ histogram_tester.ExpectTotalCount(kPSimStatusAtLoginHistogram, 3); } +TEST_F(CellularMetricsLoggerTest, CellularConnectResult) { + InitCellular(); + base::HistogramTester histogram_tester; + const base::Value kFailure(shill::kStateFailure); + const base::Value kAssocStateValue(shill::kStateAssociation); + + // Set cellular networks to connecting state. + service_client_test()->SetServiceProperty( + kTestCellularServicePath, shill::kStateProperty, kAssocStateValue); + service_client_test()->SetServiceProperty( + kTestCellularServicePath2, shill::kStateProperty, kAssocStateValue); + base::RunLoop().RunUntilIdle(); + histogram_tester.ExpectTotalCount(kESimConnectionSuccessHistogram, 0); + histogram_tester.ExpectTotalCount(kPSimConnectionSuccessHistogram, 0); + + // Set cellular networks to failed state. + service_client_test()->SetServiceProperty(kTestCellularServicePath, + shill::kStateProperty, + base::Value(shill::kStateFailure)); + service_client_test()->SetServiceProperty(kTestCellularServicePath2, + shill::kStateProperty, + base::Value(shill::kStateFailure)); + base::RunLoop().RunUntilIdle(); + histogram_tester.ExpectTotalCount(kESimConnectionSuccessHistogram, 1); + histogram_tester.ExpectTotalCount(kPSimConnectionSuccessHistogram, 1); + + histogram_tester.ExpectBucketCount( + kESimConnectionSuccessHistogram, + CellularMetricsLogger::ConnectResult::kUnknown, 1); + histogram_tester.ExpectBucketCount( + kPSimConnectionSuccessHistogram, + CellularMetricsLogger::ConnectResult::kUnknown, 1); + + // Set cellular networks to connecting state. + service_client_test()->SetServiceProperty( + kTestCellularServicePath, shill::kStateProperty, kAssocStateValue); + service_client_test()->SetServiceProperty( + kTestCellularServicePath2, shill::kStateProperty, kAssocStateValue); + base::RunLoop().RunUntilIdle(); + + // Set cellular networks to connected state. + service_client_test()->SetServiceProperty(kTestCellularServicePath, + shill::kStateProperty, + base::Value(shill::kStateOnline)); + service_client_test()->SetServiceProperty(kTestCellularServicePath2, + shill::kStateProperty, + base::Value(shill::kStateOnline)); + base::RunLoop().RunUntilIdle(); + + histogram_tester.ExpectTotalCount(kESimConnectionSuccessHistogram, 2); + histogram_tester.ExpectTotalCount(kPSimConnectionSuccessHistogram, 2); + + histogram_tester.ExpectBucketCount( + kESimConnectionSuccessHistogram, + CellularMetricsLogger::ConnectResult::kSuccess, 1); + histogram_tester.ExpectBucketCount( + kPSimConnectionSuccessHistogram, + CellularMetricsLogger::ConnectResult::kSuccess, 1); + + // Simulate chrome connect failure + cellular_metrics_logger()->ConnectFailed( + kTestCellularServicePath, + NetworkConnectionHandler::kErrorConnectCanceled); + cellular_metrics_logger()->ConnectFailed( + kTestCellularServicePath2, + NetworkConnectionHandler::kErrorConnectCanceled); + + histogram_tester.ExpectTotalCount(kESimConnectionSuccessHistogram, 3); + histogram_tester.ExpectTotalCount(kPSimConnectionSuccessHistogram, 3); + + histogram_tester.ExpectBucketCount( + kESimConnectionSuccessHistogram, + CellularMetricsLogger::ConnectResult::kCanceled, 1); + histogram_tester.ExpectBucketCount( + kPSimConnectionSuccessHistogram, + CellularMetricsLogger::ConnectResult::kCanceled, 1); +} + TEST_F(CellularMetricsLoggerTest, CellularTimeToConnectedTest) { constexpr base::TimeDelta kTestConnectionTime = base::TimeDelta::FromMilliseconds(321); @@ -482,7 +571,7 @@ service_client_test()->SetServiceProperty( kTestCellularServicePath, shill::kStateProperty, kOnlineStateValue); base::RunLoop().RunUntilIdle(); - histogram_tester.ExpectTotalCount(kTimeToConnectedHistogram, 0); + histogram_tester.ExpectTotalCount(kPSimTimeToConnectedHistogram, 0); // Set cellular networks to activated state and connecting state. service_client_test()->SetServiceProperty( @@ -502,7 +591,7 @@ service_client_test()->SetServiceProperty( kTestCellularServicePath, shill::kStateProperty, kOnlineStateValue); base::RunLoop().RunUntilIdle(); - histogram_tester.ExpectTimeBucketCount(kTimeToConnectedHistogram, + histogram_tester.ExpectTimeBucketCount(kPSimTimeToConnectedHistogram, kTestConnectionTime, 1); // Should log second network's connection time independently. @@ -510,7 +599,7 @@ service_client_test()->SetServiceProperty( kTestCellularServicePath2, shill::kStateProperty, kOnlineStateValue); base::RunLoop().RunUntilIdle(); - histogram_tester.ExpectTimeBucketCount(kTimeToConnectedHistogram, + histogram_tester.ExpectTimeBucketCount(kESimTimeToConnectedHistogram, 2 * kTestConnectionTime, 1); } @@ -523,9 +612,14 @@ // Should log connected state. service_client_test()->SetServiceProperty( kTestCellularServicePath, shill::kStateProperty, kOnlineStateValue); + service_client_test()->SetServiceProperty( + kTestCellularServicePath2, shill::kStateProperty, kOnlineStateValue); base::RunLoop().RunUntilIdle(); histogram_tester.ExpectBucketCount( - kDisconnectionsHistogram, + kPSimDisconnectionsHistogram, + CellularMetricsLogger::ConnectionState::kConnected, 1); + histogram_tester.ExpectBucketCount( + kESimDisconnectionsHistogram, CellularMetricsLogger::ConnectionState::kConnected, 1); // Should not log user initiated disconnections. @@ -536,33 +630,51 @@ kTestCellularServicePath, shill::kStateProperty, kIdleStateValue); base::RunLoop().RunUntilIdle(); histogram_tester.ExpectBucketCount( - kDisconnectionsHistogram, + kPSimDisconnectionsHistogram, + CellularMetricsLogger::ConnectionState::kDisconnected, 0); + histogram_tester.ExpectBucketCount( + kESimDisconnectionsHistogram, CellularMetricsLogger::ConnectionState::kDisconnected, 0); // Should log non user initiated disconnects. service_client_test()->SetServiceProperty( kTestCellularServicePath, shill::kStateProperty, kOnlineStateValue); + service_client_test()->SetServiceProperty( + kTestCellularServicePath2, shill::kStateProperty, kOnlineStateValue); base::RunLoop().RunUntilIdle(); service_client_test()->SetServiceProperty( kTestCellularServicePath, shill::kStateProperty, kIdleStateValue); + service_client_test()->SetServiceProperty( + kTestCellularServicePath2, shill::kStateProperty, kIdleStateValue); base::RunLoop().RunUntilIdle(); histogram_tester.ExpectBucketCount( - kDisconnectionsHistogram, + kPSimDisconnectionsHistogram, + CellularMetricsLogger::ConnectionState::kDisconnected, 1); + histogram_tester.ExpectBucketCount( + kESimDisconnectionsHistogram, CellularMetricsLogger::ConnectionState::kDisconnected, 1); // Should log non user initiated disconnects when a previous // disconnect request timed out. service_client_test()->SetServiceProperty( kTestCellularServicePath, shill::kStateProperty, kOnlineStateValue); + service_client_test()->SetServiceProperty( + kTestCellularServicePath2, shill::kStateProperty, kOnlineStateValue); base::RunLoop().RunUntilIdle(); cellular_metrics_logger()->DisconnectRequested(kTestCellularServicePath); + cellular_metrics_logger()->DisconnectRequested(kTestCellularServicePath2); task_environment_.FastForwardBy( CellularMetricsLogger::kDisconnectRequestTimeout * 2); service_client_test()->SetServiceProperty( kTestCellularServicePath, shill::kStateProperty, kIdleStateValue); + service_client_test()->SetServiceProperty( + kTestCellularServicePath2, shill::kStateProperty, kIdleStateValue); base::RunLoop().RunUntilIdle(); histogram_tester.ExpectBucketCount( - kDisconnectionsHistogram, + kPSimDisconnectionsHistogram, + CellularMetricsLogger::ConnectionState::kDisconnected, 2); + histogram_tester.ExpectBucketCount( + kESimDisconnectionsHistogram, CellularMetricsLogger::ConnectionState::kDisconnected, 2); }
diff --git a/chromeos/network/test_cellular_inhibitor.h b/chromeos/network/test_cellular_inhibitor.h index bcd91f14..74c52e3 100644 --- a/chromeos/network/test_cellular_inhibitor.h +++ b/chromeos/network/test_cellular_inhibitor.h
@@ -16,6 +16,8 @@ TestCellularInhibitor(); ~TestCellularInhibitor() override; + using CellularInhibitor::NotifyInhibitStateChanged; + private: // CellularESimProfileHandler: bool HasScanningStarted() override;
diff --git a/chromeos/profiles/atom.afdo.newest.txt b/chromeos/profiles/atom.afdo.newest.txt index 3297fe5..4cb000d4 100644 --- a/chromeos/profiles/atom.afdo.newest.txt +++ b/chromeos/profiles/atom.afdo.newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-atom-91-4430.19-1615803233-benchmark-91.0.4448.0-r1-redacted.afdo.xz +chromeos-chrome-amd64-atom-91-4430.19-1615803233-benchmark-91.0.4449.0-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/bigcore.afdo.newest.txt b/chromeos/profiles/bigcore.afdo.newest.txt index c48f52a..55afb4f 100644 --- a/chromeos/profiles/bigcore.afdo.newest.txt +++ b/chromeos/profiles/bigcore.afdo.newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-bigcore-91-4430.19-1615806685-benchmark-91.0.4448.0-r1-redacted.afdo.xz +chromeos-chrome-amd64-bigcore-91-4430.19-1615806685-benchmark-91.0.4449.0-r1-redacted.afdo.xz
diff --git a/chromeos/services/cellular_setup/esim_profile.cc b/chromeos/services/cellular_setup/esim_profile.cc index 4ba2f1f9..158f974e 100644 --- a/chromeos/services/cellular_setup/esim_profile.cc +++ b/chromeos/services/cellular_setup/esim_profile.cc
@@ -108,9 +108,11 @@ EnsureProfileExistsOnEuiccCallback perform_install_profile_callback = base::BindOnce(&ESimProfile::PerformInstallProfile, weak_ptr_factory_.GetWeakPtr(), confirmation_code); - esim_manager_->cellular_inhibitor()->InhibitCellularScanning(base::BindOnce( - &ESimProfile::EnsureProfileExistsOnEuicc, weak_ptr_factory_.GetWeakPtr(), - std::move(perform_install_profile_callback))); + esim_manager_->cellular_inhibitor()->InhibitCellularScanning( + CellularInhibitor::InhibitReason::kInstallingProfile, + base::BindOnce(&ESimProfile::EnsureProfileExistsOnEuicc, + weak_ptr_factory_.GetWeakPtr(), + std::move(perform_install_profile_callback))); } void ESimProfile::UninstallProfile(UninstallProfileCallback callback) { @@ -198,9 +200,11 @@ EnsureProfileExistsOnEuiccCallback perform_set_profile_nickname_callback = base::BindOnce(&ESimProfile::PerformSetProfileNickname, weak_ptr_factory_.GetWeakPtr(), nickname); - esim_manager_->cellular_inhibitor()->InhibitCellularScanning(base::BindOnce( - &ESimProfile::EnsureProfileExistsOnEuicc, weak_ptr_factory_.GetWeakPtr(), - std::move(perform_set_profile_nickname_callback))); + esim_manager_->cellular_inhibitor()->InhibitCellularScanning( + CellularInhibitor::InhibitReason::kRenamingProfile, + base::BindOnce(&ESimProfile::EnsureProfileExistsOnEuicc, + weak_ptr_factory_.GetWeakPtr(), + std::move(perform_set_profile_nickname_callback))); } void ESimProfile::UpdateProperties(
diff --git a/chromeos/services/cellular_setup/euicc.cc b/chromeos/services/cellular_setup/euicc.cc index 2758d65..4473c3de 100644 --- a/chromeos/services/cellular_setup/euicc.cc +++ b/chromeos/services/cellular_setup/euicc.cc
@@ -111,15 +111,18 @@ // currently being installed to prevent multiple attempts for the same // activation code. NET_LOG(USER) << "Attempting installation with code " << activation_code; - esim_manager_->cellular_inhibitor()->InhibitCellularScanning(base::BindOnce( - &Euicc::PerformInstallProfileFromActivationCode, - weak_ptr_factory_.GetWeakPtr(), activation_code, confirmation_code, - CreateTimedInstallProfileCallback(std::move(callback)))); + esim_manager_->cellular_inhibitor()->InhibitCellularScanning( + CellularInhibitor::InhibitReason::kInstallingProfile, + base::BindOnce(&Euicc::PerformInstallProfileFromActivationCode, + weak_ptr_factory_.GetWeakPtr(), activation_code, + confirmation_code, + CreateTimedInstallProfileCallback(std::move(callback)))); } void Euicc::RequestPendingProfiles(RequestPendingProfilesCallback callback) { NET_LOG(EVENT) << "Requesting Pending profiles"; esim_manager_->cellular_inhibitor()->InhibitCellularScanning( + CellularInhibitor::InhibitReason::kRefreshingProfileList, base::BindOnce(&Euicc::PerformRequestPendingProfiles, weak_ptr_factory_.GetWeakPtr(), std::move(callback))); }
diff --git a/chromeos/services/libassistant/conversation_controller.cc b/chromeos/services/libassistant/conversation_controller.cc index 7cbcbefe8..8eaf23a 100644 --- a/chromeos/services/libassistant/conversation_controller.cc +++ b/chromeos/services/libassistant/conversation_controller.cc
@@ -15,7 +15,6 @@ #include "chromeos/services/assistant/public/cpp/features.h" #include "chromeos/services/assistant/public/cpp/migration/libassistant_v1_api.h" #include "chromeos/services/libassistant/public/mojom/conversation_controller.mojom.h" -#include "chromeos/services/libassistant/service_controller.h" #include "chromeos/strings/grit/chromeos_strings.h" #include "libassistant/shared/internal_api/assistant_manager_delegate.h" #include "libassistant/shared/internal_api/assistant_manager_internal.h" @@ -207,20 +206,14 @@ // ConversationController //////////////////////////////////////////////////////////////////////////////// -ConversationController::ConversationController( - ServiceController* service_controller) +ConversationController::ConversationController() : receiver_(this), - service_controller_(service_controller), assistant_manager_delegate_( std::make_unique<AssistantManagerDelegateImpl>(this)), action_module_(std::make_unique<assistant::action::CrosActionModule>( assistant::features::IsAppSupportEnabled(), assistant::features::IsWaitSchedulingEnabled())), mojom_task_runner_(base::SequencedTaskRunnerHandle::Get()) { - // TODO(jeroendh): We should not pass in the |ServiceController| into this - // constructor. Instead, we should access the |AssistantManager| through - // the methods offered by |AssistantManagerObserver|. - DCHECK(service_controller_); action_module_->AddObserver(this); } @@ -265,16 +258,27 @@ v1_api->SetActionModule(action_module_.get()); } +void ConversationController::OnAssistantManagerRunning( + assistant_client::AssistantManager* assistant_manager, + assistant_client::AssistantManagerInternal* assistant_manager_internal) { + // Only when Libassistant is running we can start sending queries. + assistant_manager_internal_ = assistant_manager_internal; + requests_are_allowed_ = true; +} + +void ConversationController::OnDestroyingAssistantManager( + assistant_client::AssistantManager* assistant_manager, + assistant_client::AssistantManagerInternal* assistant_manager_internal) { + assistant_manager_internal_ = nullptr; +} + void ConversationController::SendTextQuery(const std::string& query, AssistantQuerySource source, bool allow_tts) { - // DCHECKs if this function gets invoked after the service has been fully - // started. - // TODO(meilinw): only check for the |ServiceState::kRunning| state instead - // after it has been wired up. - DCHECK(service_controller_->IsStarted()) - << "Libassistant service is not ready to handle queries."; - DCHECK(assistant_manager_internal()); + DCHECK(requests_are_allowed_) + << "Should not receive requests before Libassistant is running"; + if (!assistant_manager_internal_) + return; // Configs |VoicelessOptions|. assistant_client::VoicelessOptions options; @@ -291,12 +295,17 @@ // Builds text interaction. std::string interaction = assistant::CreateTextQueryInteraction(query); - assistant_manager_internal()->SendVoicelessInteraction( + assistant_manager_internal_->SendVoicelessInteraction( interaction, /*description=*/"text_query", options, [](auto) {}); } void ConversationController::StartEditReminderInteraction( const std::string& client_id) { + DCHECK(requests_are_allowed_) + << "Should not receive requests before Libassistant is running"; + if (!assistant_manager_internal_) + return; + SendVoicelessInteraction(assistant::CreateEditReminderInteraction(client_id), /*description=*/std::string(), /*is_user_initiated=*/true); @@ -305,6 +314,11 @@ void ConversationController::RetrieveNotification( AssistantNotification notification, int32_t action_index) { + DCHECK(requests_are_allowed_) + << "Should not receive requests before Libassistant is running"; + if (!assistant_manager_internal_) + return; + const std::string request_interaction = assistant::SerializeNotificationRequestInteraction( notification.server_id, notification.consistency_token, @@ -317,9 +331,9 @@ void ConversationController::DismissNotification( AssistantNotification notification) { - // |assistant_manager_internal()| may not exist if we are dismissing - // notifications as part of a shutdown sequence. - if (!assistant_manager_internal()) + DCHECK(requests_are_allowed_) + << "Should not receive requests before Libassistant is running"; + if (!assistant_manager_internal_) return; const std::string dismissed_interaction = @@ -330,13 +344,18 @@ assistant_client::VoicelessOptions options; options.obfuscated_gaia_id = notification.obfuscated_gaia_id; - assistant_manager_internal()->SendVoicelessInteraction( + assistant_manager_internal_->SendVoicelessInteraction( dismissed_interaction, /*description=*/"DismissNotification", options, [](auto) {}); } void ConversationController::SendAssistantFeedback( const AssistantFeedback& feedback) { + DCHECK(requests_are_allowed_) + << "Should not receive requests before Libassistant is running"; + if (!assistant_manager_internal_) + return; + std::string raw_image_data(feedback.screenshot_png.begin(), feedback.screenshot_png.end()); const std::string interaction = assistant::CreateSendFeedbackInteraction( @@ -419,7 +438,7 @@ assistant_client::VoicelessOptions options; options.obfuscated_gaia_id = interaction.user_id; - assistant_manager_internal()->SendVoicelessInteraction( + assistant_manager_internal_->SendVoicelessInteraction( interaction_proto, /*description=*/"open_provider_response", options, [](auto) {}); } @@ -466,14 +485,9 @@ assistant_client::VoicelessOptions voiceless_options; voiceless_options.is_user_initiated = is_user_initiated; - assistant_manager_internal()->SendVoicelessInteraction( + assistant_manager_internal_->SendVoicelessInteraction( interaction, description, voiceless_options, [](auto) {}); } -assistant_client::AssistantManagerInternal* -ConversationController::assistant_manager_internal() { - return service_controller_->assistant_manager_internal(); -} - } // namespace libassistant } // namespace chromeos
diff --git a/chromeos/services/libassistant/conversation_controller.h b/chromeos/services/libassistant/conversation_controller.h index 2c716ed..dad8d04 100644 --- a/chromeos/services/libassistant/conversation_controller.h +++ b/chromeos/services/libassistant/conversation_controller.h
@@ -29,8 +29,6 @@ namespace libassistant { -class ServiceController; - class COMPONENT_EXPORT(LIBASSISTANT_SERVICE) ConversationController : public mojom::ConversationController, public AssistantManagerObserver, @@ -40,7 +38,7 @@ using AssistantQuerySource = ::chromeos::assistant::AssistantQuerySource; using AssistantFeedback = ::chromeos::assistant::AssistantFeedback; - explicit ConversationController(ServiceController* service_controller); + ConversationController(); ConversationController(const ConversationController&) = delete; ConversationController& operator=(const ConversationController&) = delete; ~ConversationController() override; @@ -60,6 +58,14 @@ assistant_client::AssistantManager* assistant_manager, assistant_client::AssistantManagerInternal* assistant_manager_internal) override; + void OnAssistantManagerRunning( + assistant_client::AssistantManager* assistant_manager, + assistant_client::AssistantManagerInternal* assistant_manager_internal) + override; + void OnDestroyingAssistantManager( + assistant_client::AssistantManager* assistant_manager, + assistant_client::AssistantManagerInternal* assistant_manager_internal) + override; // mojom::ConversationController implementation: void SendTextQuery(const std::string& query, @@ -99,16 +105,17 @@ const std::string& description, bool is_user_initiated); - assistant_client::AssistantManagerInternal* assistant_manager_internal(); - mojo::Receiver<mojom::ConversationController> receiver_; mojo::RemoteSet<mojom::ConversationObserver> observers_; mojo::RemoteSet<mojom::AuthenticationStateObserver> authentication_state_observers_; mojo::Remote<mojom::NotificationDelegate> notification_delegate_; - // Owned by |LibassistantService|. - ServiceController* const service_controller_; + assistant_client::AssistantManagerInternal* assistant_manager_internal_ = + nullptr; + // False until libassistant is running for the first time. + // Any request that comes in before that is an error and will be DCHECK'ed. + bool requests_are_allowed_ = false; std::unique_ptr<AssistantManagerDelegateImpl> assistant_manager_delegate_; std::unique_ptr<assistant::action::CrosActionModule> action_module_;
diff --git a/chromeos/services/libassistant/conversation_observer_unittest.cc b/chromeos/services/libassistant/conversation_observer_unittest.cc index 24f18c8..a5ce2e23 100644 --- a/chromeos/services/libassistant/conversation_observer_unittest.cc +++ b/chromeos/services/libassistant/conversation_observer_unittest.cc
@@ -8,6 +8,7 @@ #include "chromeos/assistant/internal/action/cros_action_module.h" #include "chromeos/assistant/internal/test_support/fake_assistant_manager.h" #include "chromeos/assistant/internal/test_support/fake_assistant_manager_internal.h" +#include "chromeos/services/libassistant/conversation_controller.h" #include "chromeos/services/libassistant/libassistant_service.h" #include "chromeos/services/libassistant/public/cpp/android_app_info.h" #include "chromeos/services/libassistant/public/mojom/conversation_observer.mojom.h" @@ -113,12 +114,14 @@ } // namespace -class ConversationObserverTest : public ::testing::Test { +class AssistantConversationObserverTest : public ::testing::Test { public: - ConversationObserverTest() = default; - ConversationObserverTest(const ConversationObserverTest&) = delete; - ConversationObserverTest& operator=(const ConversationObserverTest&) = delete; - ~ConversationObserverTest() override = default; + AssistantConversationObserverTest() = default; + AssistantConversationObserverTest(const AssistantConversationObserverTest&) = + delete; + AssistantConversationObserverTest& operator=( + const AssistantConversationObserverTest&) = delete; + ~AssistantConversationObserverTest() override = default; void SetUp() override { service_tester_.conversation_controller().AddRemoteObserver( @@ -126,6 +129,10 @@ service_tester_.Start(); + controller().OnAssistantManagerRunning( + &service_tester_.assistant_manager(), + &service_tester_.assistant_manager_internal()); + action_module_helper_ = std::make_unique<CrosActionModuleHelper>( static_cast<assistant::action::CrosActionModule*>( service_tester_.assistant_manager_internal().action_module())); @@ -141,6 +148,10 @@ ConversationObserverMock& observer_mock() { return observer_mock_; } + ConversationController& controller() { + return service_tester_.service().conversation_controller(); + } + private: base::test::SingleThreadTaskEnvironment environment_; ::testing::StrictMock<ConversationObserverMock> observer_mock_; @@ -148,7 +159,7 @@ std::unique_ptr<CrosActionModuleHelper> action_module_helper_; }; -TEST_F(ConversationObserverTest, +TEST_F(AssistantConversationObserverTest, ShouldReceiveOnTurnFinishedEventWhenFinishedNormally) { EXPECT_CALL( observer_mock(), @@ -160,7 +171,7 @@ observer_mock().FlushForTesting(); } -TEST_F(ConversationObserverTest, +TEST_F(AssistantConversationObserverTest, ShouldReceiveOnTurnFinishedEventWhenBeingInterrupted) { EXPECT_CALL( observer_mock(), @@ -172,7 +183,7 @@ observer_mock().FlushForTesting(); } -TEST_F(ConversationObserverTest, +TEST_F(AssistantConversationObserverTest, ShouldReceiveOnTtsStartedEventWhenFinishingNormally) { EXPECT_CALL(observer_mock(), OnTtsStarted(/*due_to_error=*/false)); @@ -180,7 +191,7 @@ observer_mock().FlushForTesting(); } -TEST_F(ConversationObserverTest, +TEST_F(AssistantConversationObserverTest, ShouldReceiveOnTtsStartedEventWhenErrorOccured) { EXPECT_CALL(observer_mock(), OnTtsStarted(/*due_to_error=*/true)); @@ -188,7 +199,7 @@ observer_mock().FlushForTesting(); } -TEST_F(ConversationObserverTest, ShouldReceiveOnHtmlResponse) { +TEST_F(AssistantConversationObserverTest, ShouldReceiveOnHtmlResponse) { const std::string fake_html = "<h1>Hello world!</h1>"; EXPECT_CALL(observer_mock(), OnHtmlResponse(fake_html, "")); @@ -197,7 +208,7 @@ observer_mock().FlushForTesting(); } -TEST_F(ConversationObserverTest, ShouldReceiveOnTextResponse) { +TEST_F(AssistantConversationObserverTest, ShouldReceiveOnTextResponse) { const std::string fake_text = "I'm a text response"; EXPECT_CALL(observer_mock(), OnTextResponse(fake_text)); @@ -205,7 +216,7 @@ observer_mock().FlushForTesting(); } -TEST_F(ConversationObserverTest, ShouldReceiveOnSuggestionsResponse) { +TEST_F(AssistantConversationObserverTest, ShouldReceiveOnSuggestionsResponse) { const std::string fake_text = "text"; const std::string fake_icon_url = "https://icon-url/"; const std::string fake_action_url = "https://action-url/"; @@ -224,7 +235,7 @@ observer_mock().FlushForTesting(); } -TEST_F(ConversationObserverTest, ShouldReceiveOnOpenUrlResponse) { +TEST_F(AssistantConversationObserverTest, ShouldReceiveOnOpenUrlResponse) { const std::string fake_url = "https://fake-url/"; EXPECT_CALL(observer_mock(), OnOpenUrlResponse(GURL(fake_url), /*in_background=*/false)); @@ -233,7 +244,7 @@ observer_mock().FlushForTesting(); } -TEST_F(ConversationObserverTest, ShouldReceiveOnOpenAppResponse) { +TEST_F(AssistantConversationObserverTest, ShouldReceiveOnOpenAppResponse) { assistant::AndroidAppInfo fake_app_info; fake_app_info.package_name = "fake package name"; fake_app_info.version = 123; @@ -255,7 +266,7 @@ observer_mock().FlushForTesting(); } -TEST_F(ConversationObserverTest, ShouldReceiveOnWaitStarted) { +TEST_F(AssistantConversationObserverTest, ShouldReceiveOnWaitStarted) { EXPECT_CALL(observer_mock(), OnWaitStarted()); action_module_helper().ScheduleWait();
diff --git a/chromeos/services/libassistant/libassistant_service.cc b/chromeos/services/libassistant/libassistant_service.cc index 0a3a466f..b589510b 100644 --- a/chromeos/services/libassistant/libassistant_service.cc +++ b/chromeos/services/libassistant/libassistant_service.cc
@@ -62,7 +62,7 @@ libassistant_factory_( FactoryOrDefault(std::move(factory), &platform_api_)), service_controller_(libassistant_factory_.get()), - conversation_controller_(&service_controller_), + conversation_controller_(), conversation_state_listener_( &speech_recognition_observers_, conversation_controller_.conversation_observers(),
diff --git a/chromeos/services/libassistant/libassistant_service.h b/chromeos/services/libassistant/libassistant_service.h index a4ba932..ad0e2d9 100644 --- a/chromeos/services/libassistant/libassistant_service.h +++ b/chromeos/services/libassistant/libassistant_service.h
@@ -66,6 +66,10 @@ chromeos::libassistant::mojom::AuthenticationStateObserver> observer) override; + ConversationController& conversation_controller() { + return conversation_controller_; + } + private: ServiceController& service_controller() { return service_controller_; }
diff --git a/chromeos/services/network_config/BUILD.gn b/chromeos/services/network_config/BUILD.gn index 1f73bbf9..cbff7ebd 100644 --- a/chromeos/services/network_config/BUILD.gn +++ b/chromeos/services/network_config/BUILD.gn
@@ -11,6 +11,7 @@ ] deps = [ + "//ash/constants", "//base", "//chromeos/components/sync_wifi:network_eligibility_checker", "//chromeos/dbus/hermes",
diff --git a/chromeos/services/network_config/cros_network_config.cc b/chromeos/services/network_config/cros_network_config.cc index a1dc435..38d6b2097 100644 --- a/chromeos/services/network_config/cros_network_config.cc +++ b/chromeos/services/network_config/cros_network_config.cc
@@ -6,6 +6,7 @@ #include <vector> +#include "ash/constants/ash_features.h" #include "base/containers/flat_map.h" #include "base/optional.h" #include "base/strings/string_util.h" @@ -512,7 +513,15 @@ result->mac_address = network_util::FormattedMacAddress(device->mac_address()); result->scanning = device->scanning(); - result->device_state = technology_state; + + // Before multi-SIM support was in place, the Cellular device would always be + // disabled anytime that a SIM was absent. Special-case this logic to ensure + // that users with the flag off will still see a disabled UI in this case. + if (device->IsSimAbsent() && !features::IsCellularActivationUiEnabled()) + result->device_state = mojom::DeviceStateType::kDisabled; + else + result->device_state = technology_state; + result->managed_network_available = !device->available_managed_network_path().empty(); result->sim_absent = device->IsSimAbsent();
diff --git a/chromeos/services/network_config/cros_network_config_unittest.cc b/chromeos/services/network_config/cros_network_config_unittest.cc index 24afa9ad..47008b9 100644 --- a/chromeos/services/network_config/cros_network_config_unittest.cc +++ b/chromeos/services/network_config/cros_network_config_unittest.cc
@@ -790,6 +790,20 @@ EXPECT_EQ(kTestProfileName, network->name); } +TEST_F(CrosNetworkConfigTest, SimAbsentMeansCellularIsDisabled) { + mojom::DeviceStatePropertiesPtr cellular = + GetDeviceStateFromList(mojom::NetworkType::kCellular); + EXPECT_EQ(mojom::DeviceStateType::kEnabled, cellular->device_state); + + helper().device_test()->SetDeviceProperty( + kCellularDevicePath, shill::kSIMPresentProperty, base::Value(false), + /*notify_changed=*/true); + base::RunLoop().RunUntilIdle(); + + cellular = GetDeviceStateFromList(mojom::NetworkType::kCellular); + EXPECT_EQ(mojom::DeviceStateType::kDisabled, cellular->device_state); +} + TEST_F(CrosNetworkConfigTest, GetDeviceStateList) { std::vector<mojom::DeviceStatePropertiesPtr> devices = GetDeviceStateList(); ASSERT_EQ(4u, devices.size());
diff --git a/components/BUILD.gn b/components/BUILD.gn index 0d385ac..249d57c 100644 --- a/components/BUILD.gn +++ b/components/BUILD.gn
@@ -626,6 +626,7 @@ "dom_distiller/content/browser/test/test_util.cc", "dom_distiller/content/browser/test/test_util.h", "metrics/content/subprocess_metrics_provider_browsertest.cc", + "optimization_guide/content/renderer/page_text_agent_browsertest.cc", "paint_preview/renderer/paint_preview_recorder_browsertest.cc", "security_state/content/content_utils_browsertest.cc", "ukm/content/source_url_recorder_browsertest.cc", @@ -660,6 +661,7 @@ "//components/dom_distiller/core:test_support", "//components/error_page/content/browser:browser_tests", "//components/metrics:content", + "//components/optimization_guide/content/renderer", "//components/paint_preview/renderer", "//components/password_manager/content/browser", "//components/performance_manager:browser_tests",
diff --git a/components/browser_ui/strings/android/browser_ui_strings.grd b/components/browser_ui/strings/android/browser_ui_strings.grd index ac88a5de..34343ac 100644 --- a/components/browser_ui/strings/android/browser_ui_strings.grd +++ b/components/browser_ui/strings/android/browser_ui_strings.grd
@@ -398,6 +398,9 @@ <message name="IDS_DOWNLOAD_NOTIFICATION_CANCEL_BUTTON" desc="Text on the button that cancels a download."> Cancel </message> + <message name="IDS_DOWNLOAD_NOTIFICATION_COMPLETED" desc="Download notification to be displayed when a download completes."> + Download complete + </message> <message name="IDS_DOWNLOAD_NOTIFICATION_COMPLETED_WITH_SIZE" desc="Download notification to be displayed when a download completes, includes the size of the download as well after a separator character."> Download complete <ph name="SEPARATOR">•</ph> <ph name="BYTES_DOWNLOADED">%1$s<ex>4.3 MB</ex></ph> </message>
diff --git a/components/browser_ui/util/DEPS b/components/browser_ui/util/DEPS index 735adf49..606d278a 100644 --- a/components/browser_ui/util/DEPS +++ b/components/browser_ui/util/DEPS
@@ -1,3 +1,4 @@ include_rules = [ "+components/embedder_support/android", + "+components/url_formatter/android", ]
diff --git a/components/browser_ui/util/android/BUILD.gn b/components/browser_ui/util/android/BUILD.gn index aeb9c62..bd140b4 100644 --- a/components/browser_ui/util/android/BUILD.gn +++ b/components/browser_ui/util/android/BUILD.gn
@@ -23,9 +23,11 @@ "//base:base_java", "//cc:cc_java", "//components/embedder_support/android:util_java", + "//components/url_formatter/android:url_formatter_java", "//third_party/androidx:androidx_annotation_annotation_java", "//third_party/androidx:androidx_collection_collection_java", "//third_party/androidx:androidx_core_core_java", + "//url:gurl_java", ] resources_package = "org.chromium.components.browser_ui.util" }
diff --git a/components/browser_ui/util/android/java/src/org/chromium/components/browser_ui/util/DownloadUtils.java b/components/browser_ui/util/android/java/src/org/chromium/components/browser_ui/util/DownloadUtils.java index af7d2ee0..f978f0b 100644 --- a/components/browser_ui/util/android/java/src/org/chromium/components/browser_ui/util/DownloadUtils.java +++ b/components/browser_ui/util/android/java/src/org/chromium/components/browser_ui/util/DownloadUtils.java
@@ -15,6 +15,10 @@ import org.chromium.base.ContextUtils; import org.chromium.base.ThreadUtils; import org.chromium.components.embedder_support.util.UrlConstants; +import org.chromium.components.embedder_support.util.UrlUtilities; +import org.chromium.components.url_formatter.SchemeDisplay; +import org.chromium.components.url_formatter.UrlFormatter; +import org.chromium.url.GURL; /** * A class containing some utility static methods. @@ -23,6 +27,10 @@ private static final int[] BYTES_STRINGS = { R.string.download_ui_kb, R.string.download_ui_mb, R.string.download_ui_gb}; + // Limit the origin length so that the eTLD+1 cannot be hidden. If the origin exceeds this + // length the eTLD+1 is extracted and shown. + private static final int MAX_ORIGIN_LENGTH = 40; + /** * Format the number of bytes into KB, MB, or GB and return the corresponding generated string. * @param context Context to use. @@ -104,4 +112,22 @@ } return originalUri; } + + /** + * Adjusts a URL for display to the user in the subtext of an Android notification. + * + * @param url The full URL. + * @param return The URL that should be displayed, or null if the input was invalid. + */ + public static String formatUrlForDisplayInNotification(GURL url) { + if (GURL.isEmptyOrInvalid(url)) return null; + + String formattedUrl = + UrlFormatter.formatUrlForSecurityDisplay(url, SchemeDisplay.OMIT_HTTP_AND_HTTPS); + if (formattedUrl.length() <= MAX_ORIGIN_LENGTH) return formattedUrl; + + // The origin is too long. Strip down to eTLD+1. + return UrlUtilities.getDomainAndRegistry( + url.getSpec(), false /* includePrivateRegistries */); + } }
diff --git a/components/crash/android/java/src/org/chromium/components/crash/browser/ProcessExitReasonFromSystem.java b/components/crash/android/java/src/org/chromium/components/crash/browser/ProcessExitReasonFromSystem.java index d4dae99c..e0d89962 100644 --- a/components/crash/android/java/src/org/chromium/components/crash/browser/ProcessExitReasonFromSystem.java +++ b/components/crash/android/java/src/org/chromium/components/crash/browser/ProcessExitReasonFromSystem.java
@@ -25,8 +25,13 @@ * ActivityManager, and record to UMA. */ public class ProcessExitReasonFromSystem { + /** + * Get the exit reason of the most recent chrome process that died and had |pid| as the process + * ID. Only available on R+ devices, returns -1 otherwise. + * @return ApplicationExitInfo.Reason + */ @TargetApi(Build.VERSION_CODES.R) - private static int getExitReason(int pid) { + public static int getExitReason(int pid) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) { return -1; } @@ -71,11 +76,18 @@ } @CalledByNative - public static void recordExitReasonToUma(int pid, String umaName) { - int system_reason = getExitReason(pid); + private static void recordExitReasonToUma(int pid, String umaName) { + recordAsEnumHistogram(umaName, getExitReason(pid)); + } + + /** + * Records the given |systemReason| (given by #getExitReason) to UMA with the given |umaName|. + * @see #getExitReason + */ + public static void recordAsEnumHistogram(String umaName, int systemReason) { @ExitReason int reason; - switch (system_reason) { + switch (systemReason) { case ApplicationExitInfo.REASON_ANR: reason = ExitReason.REASON_ANR; break;
diff --git a/components/full_restore/BUILD.gn b/components/full_restore/BUILD.gn index 0bc9c8df..37f33e1 100644 --- a/components/full_restore/BUILD.gn +++ b/components/full_restore/BUILD.gn
@@ -9,6 +9,8 @@ "app_launch_info.h", "app_restore_data.cc", "app_restore_data.h", + "arc_read_handler.cc", + "arc_read_handler.h", "arc_save_handler.cc", "arc_save_handler.h", "full_restore_file_handler.cc",
diff --git a/components/full_restore/arc_read_handler.cc b/components/full_restore/arc_read_handler.cc new file mode 100644 index 0000000..d8b1f98b6 --- /dev/null +++ b/components/full_restore/arc_read_handler.cc
@@ -0,0 +1,96 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/full_restore/arc_read_handler.h" + +#include "components/full_restore/full_restore_info.h" +#include "components/full_restore/full_restore_read_handler.h" +#include "components/full_restore/window_info.h" + +namespace full_restore { + +ArcReadHandler::ArcReadHandler(const base::FilePath& profile_path) + : profile_path_(profile_path) {} + +ArcReadHandler::~ArcReadHandler() = default; + +void ArcReadHandler::AddRestoreData(const std::string& app_id, + int32_t window_id) { + window_id_to_app_id_[window_id] = app_id; +} + +void ArcReadHandler::OnTaskCreated(const std::string& app_id, + int32_t task_id, + int32_t session_id) { + auto it = session_id_to_window_id_.find(session_id); + if (it == session_id_to_window_id_.end()) + return; + + int32_t restore_window_id = it->second; + session_id_to_window_id_.erase(it); + task_id_to_window_id_[task_id] = restore_window_id; +} + +void ArcReadHandler::OnTaskDestroyed(int32_t task_id) { + auto it = task_id_to_window_id_.find(task_id); + if (it == task_id_to_window_id_.end()) + return; + + int32_t window_id = it->second; + task_id_to_window_id_.erase(it); + + RemoveAppRestoreData(window_id); +} + +bool ArcReadHandler::HasRestoreData(int32_t window_id) { + return base::Contains(window_id_to_app_id_, window_id); +} + +int32_t ArcReadHandler::GetArcRestoreWindowId(int32_t task_id) { + auto it = task_id_to_window_id_.find(task_id); + if (it != task_id_to_window_id_.end()) + return it->second; + + // If |session_id_to_window_id_| is empty, that means there is no ARC apps + // launched. + if (session_id_to_window_id_.empty()) + return 0; + + // If |session_id_to_window_id_| is not empty, that means there are ARC + // apps launched. Returns -1 to add the ARC app window to the hidden + // container. + return kParentToHiddenContainer; +} + +int32_t ArcReadHandler::GetArcSessionId() { + if (session_id_ < kArcSessionIdOffsetForRestoredLaunching) { + LOG(WARNING) << "ARC session id is overflow: " << session_id_; + session_id_ = kArcSessionIdOffsetForRestoredLaunching; + } + + return ++session_id_; +} + +void ArcReadHandler::SetArcSessionIdForWindowId(int32_t session_id, + int32_t window_id) { + DCHECK_GT(session_id, full_restore::kArcSessionIdOffsetForRestoredLaunching); + session_id_to_window_id_[session_id] = window_id; +} + +void ArcReadHandler::RemoveAppRestoreData(int32_t window_id) { + if (window_id == 0 || window_id == kParentToHiddenContainer) + return; + + auto it = window_id_to_app_id_.find(window_id); + if (it == window_id_to_app_id_.end()) + return; + + const std::string& app_id = it->second; + FullRestoreReadHandler::GetInstance()->RemoveAppRestoreData( + profile_path_, app_id, window_id); + + window_id_to_app_id_.erase(it); +} + +} // namespace full_restore
diff --git a/components/full_restore/arc_read_handler.h b/components/full_restore/arc_read_handler.h new file mode 100644 index 0000000..6ed6889 --- /dev/null +++ b/components/full_restore/arc_read_handler.h
@@ -0,0 +1,76 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_FULL_RESTORE_ARC_READ_HANDLER_H_ +#define COMPONENTS_FULL_RESTORE_ARC_READ_HANDLER_H_ + +#include <map> + +#include "base/component_export.h" +#include "base/files/file_path.h" +#include "components/full_restore/full_restore_utils.h" + +namespace full_restore { + +// ArcReadHandler is a helper class for FullRestoreReadHandler to handle ARC app +// windows special cases, e.g. ARC task creation, ARC session id, etc. +class COMPONENT_EXPORT(FULL_RESTORE) ArcReadHandler { + public: + explicit ArcReadHandler(const base::FilePath& profile_path); + ArcReadHandler(const ArcReadHandler&) = delete; + ArcReadHandler& operator=(const ArcReadHandler&) = delete; + ~ArcReadHandler(); + + // Sets |app_id| and |window_id| to |window_id_to_app_id_| to record that + // there is a restore data for |app_id| and |window_id|. + void AddRestoreData(const std::string& app_id, int32_t window_id); + + // Invoked when the task is created for an ARC app. + void OnTaskCreated(const std::string& app_id, + int32_t task_id, + int32_t session_id); + + // Invoked when the task is destroyed for an ARC app. + void OnTaskDestroyed(int32_t task_id); + + // Returns true if there is restore data for |window_id|, otherwise returns + // false. + bool HasRestoreData(int32_t window_id); + + // Returns the restore window id for the ARC app's |task_id|. + int32_t GetArcRestoreWindowId(int32_t task_id); + + // Generates the ARC session id (1,000,000,001 - INT_MAX) for restored ARC + // apps. + int32_t GetArcSessionId(); + + // Sets |session_id| for |window_id| to |session_id_to_window_id_|. + // |session_id| is assigned when ARC apps are restored. + void SetArcSessionIdForWindowId(int32_t session_id, int32_t window_id); + + private: + friend class FullRestoreReadHandlerTestApi; + + // Removes AppRestoreData for |restore_window_id|. + void RemoveAppRestoreData(int32_t restore_window_id); + + // The user profile path for ARC app windows. + base::FilePath profile_path_; + + // The map from the window id to the app id for ARC app windows. The window id + // is saved in the window property |kRestoreWindowIdKey|. + std::map<int32_t, std::string> window_id_to_app_id_; + + int32_t session_id_ = full_restore::kArcSessionIdOffsetForRestoredLaunching; + + // The map from the arc session id to the window id. + std::map<int32_t, int32_t> session_id_to_window_id_; + + // The map from the arc task id to the window id. + std::map<int32_t, int32_t> task_id_to_window_id_; +}; + +} // namespace full_restore + +#endif // COMPONENTS_FULL_RESTORE_ARC_READ_HANDLER_H_
diff --git a/components/full_restore/arc_save_handler.cc b/components/full_restore/arc_save_handler.cc index d1c96d6..a776b41 100644 --- a/components/full_restore/arc_save_handler.cc +++ b/components/full_restore/arc_save_handler.cc
@@ -14,6 +14,15 @@ namespace full_restore { +namespace { + +// Repeat timer interval between each checking that whether a task is created +// for each app launching. +constexpr base::TimeDelta kCheckCycleInterval = + base::TimeDelta::FromSeconds(30); + +} // namespace + ArcSaveHandler::ArcSaveHandler(const base::FilePath& profile_path) : profile_path_(profile_path) {} @@ -25,7 +34,10 @@ // Save |app_launch_info| to |session_id_to_app_launch_info_|, and wait for // the ARC task to be created. int32_t session_id = app_launch_info->arc_session_id.value(); - session_id_to_app_launch_info_[session_id] = std::move(app_launch_info); + session_id_to_app_launch_info_[session_id] = + std::make_pair(std::move(app_launch_info), base::TimeTicks::Now()); + + MaybeStartCheckTimer(); } void ArcSaveHandler::ModifyWindowInfo(int task_id, @@ -74,8 +86,10 @@ task_id_to_app_id_[task_id] = app_id; - auto app_launch_info = std::move(it->second); + auto app_launch_info = std::move(it->second.first); session_id_to_app_launch_info_.erase(it); + if (session_id_to_app_launch_info_.empty()) + check_timer_.Stop(); app_launch_info->window_id = task_id; FullRestoreSaveHandler::GetInstance()->AddAppLaunchInfo( @@ -114,4 +128,28 @@ return ++session_id_; } +void ArcSaveHandler::MaybeStartCheckTimer() { + if (!check_timer_.IsRunning()) { + check_timer_.Start( + FROM_HERE, kCheckCycleInterval, + base::BindRepeating(&ArcSaveHandler::CheckTasksForAppLaunching, + weak_factory_.GetWeakPtr())); + } +} + +void ArcSaveHandler::CheckTasksForAppLaunching() { + std::set<int32_t> session_ids; + for (const auto& it : session_id_to_app_launch_info_) { + base::TimeDelta time_delta = base::TimeTicks::Now() - it.second.second; + if (time_delta > kCheckCycleInterval) + session_ids.insert(it.first); + } + + for (auto id : session_ids) + session_id_to_app_launch_info_.erase(id); + + if (session_id_to_app_launch_info_.empty()) + check_timer_.Stop(); +} + } // namespace full_restore
diff --git a/components/full_restore/arc_save_handler.h b/components/full_restore/arc_save_handler.h index a111031b..bfb928b 100644 --- a/components/full_restore/arc_save_handler.h +++ b/components/full_restore/arc_save_handler.h
@@ -12,6 +12,8 @@ #include "base/component_export.h" #include "base/files/file_path.h" +#include "base/memory/weak_ptr.h" +#include "base/timer/timer.h" namespace aura { class Window; @@ -20,7 +22,6 @@ namespace full_restore { struct AppLaunchInfo; -class FullRestoreSaveHandlerTestApi; struct WindowInfo; // ArcSaveHandler is a helper class for FullRestoreSaveHandler to handle ARC app @@ -28,6 +29,8 @@ class COMPONENT_EXPORT(FULL_RESTORE) ArcSaveHandler { public: using AppLaunchInfoPtr = std::unique_ptr<AppLaunchInfo>; + using SessionIdMap = + std::map<int32_t, std::pair<AppLaunchInfoPtr, base::TimeTicks>>; explicit ArcSaveHandler(const base::FilePath& profile_path); ArcSaveHandler(const ArcSaveHandler&) = delete; @@ -61,13 +64,21 @@ private: friend class FullRestoreSaveHandlerTestApi; + // Starts the timer to check whether a task is created for the app launching + // (if timer isn't already running). + void MaybeStartCheckTimer(); + + // Check whether a task is created for each app launching. If not, remove the + // app launching record. + void CheckTasksForAppLaunching(); + // The user profile path for ARC app. base::FilePath profile_path_; int32_t session_id_ = 0; // The map from the ARC session id to the app launch info. - std::map<int32_t, AppLaunchInfoPtr> session_id_to_app_launch_info_; + SessionIdMap session_id_to_app_launch_info_; // The map from the task id to the app id. The task id is saved in the window // property. This map is used to find the app id when save the window info. @@ -78,6 +89,13 @@ // windows, whose tasks have not been created. Once the task for the window is // created, the window is removed from |arc_window_candidates_|. std::set<aura::Window*> arc_window_candidates_; + + // Timer used to whether a task is created. App launching could have failed. + // If an app is launched without a task created, the launch record should be + // removed from |session_id_to_app_launch_info_|. + base::RepeatingTimer check_timer_; + + base::WeakPtrFactory<ArcSaveHandler> weak_factory_{this}; }; } // namespace full_restore
diff --git a/components/full_restore/full_restore_read_and_save_unittest.cc b/components/full_restore/full_restore_read_and_save_unittest.cc index d250312..5ffc88d 100644 --- a/components/full_restore/full_restore_read_and_save_unittest.cc +++ b/components/full_restore/full_restore_read_and_save_unittest.cc
@@ -45,6 +45,43 @@ } // namespace +class FullRestoreReadHandlerTestApi { + public: + explicit FullRestoreReadHandlerTestApi(FullRestoreReadHandler* read_handler) + : read_handler_(read_handler) {} + + FullRestoreReadHandlerTestApi(const FullRestoreReadHandlerTestApi&) = delete; + FullRestoreReadHandlerTestApi& operator=( + const FullRestoreReadHandlerTestApi&) = delete; + ~FullRestoreReadHandlerTestApi() = default; + + const ArcReadHandler* GetArcReadHander() const { + DCHECK(read_handler_); + return read_handler_->arc_read_handler_.get(); + } + + const std::map<int32_t, std::string>& GetArcWindowIdMap() const { + const auto* arc_read_handler = GetArcReadHander(); + DCHECK(arc_read_handler); + return arc_read_handler->window_id_to_app_id_; + } + + const std::map<int32_t, int32_t>& GetArcSessionIdMap() const { + const auto* arc_read_handler = GetArcReadHander(); + DCHECK(arc_read_handler); + return arc_read_handler->session_id_to_window_id_; + } + + const std::map<int32_t, int32_t>& GetArcTaskIdMap() const { + const auto* arc_read_handler = GetArcReadHander(); + DCHECK(arc_read_handler); + return arc_read_handler->task_id_to_window_id_; + } + + private: + FullRestoreReadHandler* read_handler_; +}; + class FullRestoreSaveHandlerTestApi { public: explicit FullRestoreSaveHandlerTestApi(FullRestoreSaveHandler* save_handler) @@ -55,30 +92,51 @@ const FullRestoreSaveHandlerTestApi&) = delete; ~FullRestoreSaveHandlerTestApi() = default; - const ArcSaveHandler* GetArcSaveHanderForTesting() const { + const ArcSaveHandler* GetArcSaveHander() const { DCHECK(save_handler_); return save_handler_->arc_save_handler_.get(); } - const std::map<int32_t, FullRestoreSaveHandler::AppLaunchInfoPtr>& - GetArcSessionIdMapForTesting() const { - DCHECK(save_handler_); - ArcSaveHandler* arc_save_handler = save_handler_->arc_save_handler_.get(); - + const ArcSaveHandler::SessionIdMap& GetArcSessionIdMap() const { + const auto* arc_save_handler = GetArcSaveHander(); DCHECK(arc_save_handler); return arc_save_handler->session_id_to_app_launch_info_; } - const std::map<int32_t, std::string>& GetArcTaskIdMapForTesting() const { - DCHECK(save_handler_); - ArcSaveHandler* arc_save_handler = save_handler_->arc_save_handler_.get(); - + const std::map<int32_t, std::string>& GetArcTaskIdMap() const { + const auto* arc_save_handler = GetArcSaveHander(); DCHECK(arc_save_handler); return arc_save_handler->task_id_to_app_id_; } + void ModifyLaunchTime(int32_t session_id) { + auto& session_id_to_app_launch_info = + arc_save_handler()->session_id_to_app_launch_info_; + auto it = session_id_to_app_launch_info.find(session_id); + if (it == session_id_to_app_launch_info.end()) + return; + + // If there is no task created for the session id in 30 seconds, the session + // id record is removed. So set the record time as 31 seconds ago, so that + // CheckTasksForAppLaunching can remove the session id record to simulate + // the task is not created for the session id. + it->second.second = it->second.second - base::TimeDelta::FromSeconds(31); + } + + base::RepeatingTimer* GetArcCheckTimer() { + return &arc_save_handler()->check_timer_; + } + + void CheckArcTasks() { arc_save_handler()->CheckTasksForAppLaunching(); } + private: - FullRestoreSaveHandler* save_handler_ = nullptr; + ArcSaveHandler* arc_save_handler() { + DCHECK(save_handler_); + DCHECK(save_handler_->arc_save_handler_.get()); + return save_handler_->arc_save_handler_.get(); + } + + FullRestoreSaveHandler* save_handler_; }; // Unit tests for restore data. @@ -283,10 +341,9 @@ // Add an ARC app launch info. AddArcAppLaunchInfo(GetPath()); - const ArcSaveHandler* arc_save_handler = - test_api.GetArcSaveHanderForTesting(); + const ArcSaveHandler* arc_save_handler = test_api.GetArcSaveHander(); ASSERT_TRUE(arc_save_handler); - const auto& arc_session_id_map = test_api.GetArcSessionIdMapForTesting(); + const auto& arc_session_id_map = test_api.GetArcSessionIdMap(); EXPECT_EQ(1u, arc_session_id_map.size()); auto session_it = arc_session_id_map.find(kArcSessionId1); EXPECT_TRUE(session_it != arc_session_id_map.end()); @@ -295,7 +352,7 @@ // cleared. save_handler->OnTaskCreated(kAppId, kArcTaskId1, kArcSessionId1); EXPECT_TRUE(arc_session_id_map.empty()); - const auto& task_id_map = test_api.GetArcTaskIdMapForTesting(); + const auto& task_id_map = test_api.GetArcTaskIdMap(); EXPECT_EQ(1u, task_id_map.size()); auto task_id = task_id_map.find(kArcTaskId1); EXPECT_TRUE(task_id != task_id_map.end()); @@ -315,7 +372,7 @@ EXPECT_TRUE(restore_data->app_id_to_launch_list().empty()); } -TEST_F(FullRestoreReadAndSaveTest, ArcWindowRestore) { +TEST_F(FullRestoreReadAndSaveTest, ArcLaunchWithoutTask) { FullRestoreSaveHandler* save_handler = FullRestoreSaveHandler::GetInstance(); FullRestoreSaveHandlerTestApi test_api(save_handler); @@ -324,16 +381,61 @@ // Add an ARC app launch info. AddArcAppLaunchInfo(GetPath()); - const ArcSaveHandler* arc_save_handler = - test_api.GetArcSaveHanderForTesting(); + + // Verify the ARC app launch info is saved to |arc_session_id_map|. + const auto& arc_session_id_map = test_api.GetArcSessionIdMap(); + EXPECT_EQ(1u, arc_session_id_map.size()); + auto session_it = arc_session_id_map.find(kArcSessionId1); + EXPECT_TRUE(session_it != arc_session_id_map.end()); + + // Verify the ARC check timer starts running. + base::RepeatingTimer* arc_check_timer = test_api.GetArcCheckTimer(); + EXPECT_TRUE(arc_check_timer->IsRunning()); + + // Simulate more than 30 seconds have passed, OnTaskCreated is not called, and + // the ARC check timer is expired to remove the ARC app launch info. + test_api.ModifyLaunchTime(kArcSessionId1); + test_api.CheckArcTasks(); + EXPECT_TRUE(arc_session_id_map.empty()); + EXPECT_TRUE(test_api.GetArcTaskIdMap().empty()); + EXPECT_FALSE(arc_check_timer->IsRunning()); + + // Verify the timer in FullRestoreSaveHandler is not running, because there is + // no app launching info to save. + EXPECT_FALSE(timer->IsRunning()); + task_environment().RunUntilIdle(); + + ReadFromFile(GetPath()); + + // Verify there is not restore data. + const auto* restore_data = GetRestoreData(GetPath()); + ASSERT_TRUE(restore_data); + EXPECT_TRUE(restore_data->app_id_to_launch_list().empty()); +} + +TEST_F(FullRestoreReadAndSaveTest, ArcWindowRestore) { + FullRestoreSaveHandler* save_handler = FullRestoreSaveHandler::GetInstance(); + FullRestoreSaveHandlerTestApi save_test_api(save_handler); + + save_handler->SetPrimaryProfilePath(GetPath()); + base::OneShotTimer* timer = save_handler->GetTimerForTesting(); + + // Add an ARC app launch info. + AddArcAppLaunchInfo(GetPath()); + const ArcSaveHandler* arc_save_handler = save_test_api.GetArcSaveHander(); ASSERT_TRUE(arc_save_handler); - EXPECT_EQ(1u, test_api.GetArcSessionIdMapForTesting().size()); + EXPECT_EQ(1u, save_test_api.GetArcSessionIdMap().size()); + + // Verify the ARC check timer starts running. + base::RepeatingTimer* arc_check_timer = save_test_api.GetArcCheckTimer(); + EXPECT_TRUE(arc_check_timer->IsRunning()); // Create a task. Since we have got the task, the arc session id map can be // cleared. save_handler->OnTaskCreated(kAppId, kArcTaskId1, kArcSessionId1); - EXPECT_TRUE(test_api.GetArcSessionIdMapForTesting().empty()); - EXPECT_EQ(1u, test_api.GetArcTaskIdMapForTesting().size()); + EXPECT_TRUE(save_test_api.GetArcSessionIdMap().empty()); + EXPECT_EQ(1u, save_test_api.GetArcTaskIdMap().size()); + EXPECT_FALSE(arc_check_timer->IsRunning()); // Modify the window info. CreateWindowInfo(kArcTaskId1, kActivationIndex1, ash::AppType::ARC_APP); @@ -346,6 +448,11 @@ const auto* restore_data = GetRestoreData(GetPath()); ASSERT_TRUE(restore_data); + FullRestoreReadHandler* read_handler = FullRestoreReadHandler::GetInstance(); + FullRestoreReadHandlerTestApi read_test_api(read_handler); + ASSERT_TRUE(read_test_api.GetArcReadHander()); + EXPECT_EQ(1u, read_test_api.GetArcWindowIdMap().size()); + // Verify the map from app ids to launch list: // std::map<app_id, std::map<window_id, std::unique_ptr<AppRestoreData>>> const auto& launch_list = restore_data->app_id_to_launch_list(); @@ -366,28 +473,30 @@ EXPECT_TRUE(data->activation_index.has_value()); EXPECT_EQ(kActivationIndex1, data->activation_index.value()); - // Simulate the ARC app launching, and set the arc session id |kArcSessionId2| - // for the window id |kId1|. - FullRestoreReadHandler* read_handler = FullRestoreReadHandler::GetInstance(); - read_handler->SetArcSessionIdForWindowId(kArcSessionId2, kId1); + // Simulate the ARC app launching, and set the arc session id kArcSessionId2 + // for the restore window id |kArcTaskId1|. + read_handler->SetArcSessionIdForWindowId(kArcSessionId2, kArcTaskId1); + EXPECT_EQ(1u, read_test_api.GetArcSessionIdMap().size()); // Call OnTaskCreated to simulate that the ARC app with |kAppId| has been - // launched, and the new task id |kArcTaskId| has been created with + // launched, and the new task id |kArcTaskId2| has been created with // |kArcSessionId2| returned. read_handler->OnTaskCreated(kAppId, kArcTaskId2, kArcSessionId2); + EXPECT_EQ(1u, read_test_api.GetArcTaskIdMap().size()); - // Since we have got the new task with |kArcSessionId2|, the map from the arc - // session id to the window id can be cleared. And verify that we can get the - // restore window id with the new |kArcTaskId2|. - EXPECT_TRUE(read_handler->GetArcSessionIdMapForTesting().empty()); - EXPECT_EQ(kId1, full_restore::GetArcRestoreWindowId(kArcTaskId2)); + // Since we have got the new task with |kArcSessionId2|, the arc session id + // map can be cleared. And verify that we can get the restore window id + // |kArcTaskId1| with the new |kArcTaskId2|. + EXPECT_TRUE(read_test_api.GetArcSessionIdMap().empty()); + EXPECT_EQ(kArcTaskId1, full_restore::GetArcRestoreWindowId(kArcTaskId2)); // Call OnTaskDestroyed to simulate the ARC app launching has been finished // for |kArcTaskId2|, and verify the task id map is now empty and a invalid // value is returned when trying to get the restore window id. read_handler->OnTaskDestroyed(kArcTaskId2); - EXPECT_EQ(-1, full_restore::GetArcRestoreWindowId(kArcTaskId2)); - EXPECT_TRUE(read_handler->GetArcTaskIdMapForTesting().empty()); + EXPECT_EQ(0, full_restore::GetArcRestoreWindowId(kArcTaskId2)); + EXPECT_TRUE(read_test_api.GetArcTaskIdMap().empty()); + EXPECT_TRUE(read_test_api.GetArcWindowIdMap().empty()); } } // namespace full_restore
diff --git a/components/full_restore/full_restore_read_handler.cc b/components/full_restore/full_restore_read_handler.cc index 29a2f7d..1b7cdce 100644 --- a/components/full_restore/full_restore_read_handler.cc +++ b/components/full_restore/full_restore_read_handler.cc
@@ -40,11 +40,15 @@ if (window->GetProperty(aura::client::kAppType) == static_cast<int>(ash::AppType::ARC_APP)) { - if (!base::Contains(window_id_to_app_restore_info_, window_id)) + // If there isn't restore data for ARC apps, we don't need to handle ARC app + // windows restoration. + if (!arc_read_handler_) return; - observed_windows_.AddObservation(window); - FullRestoreInfo::GetInstance()->OnWindowInitialized(window); + if (arc_read_handler_->HasRestoreData(window_id)) { + observed_windows_.AddObservation(window); + FullRestoreInfo::GetInstance()->OnWindowInitialized(window); + } return; } @@ -77,17 +81,13 @@ void FullRestoreReadHandler::OnTaskCreated(const std::string& app_id, int32_t task_id, int32_t session_id) { - auto it = arc_session_id_to_window_id_.find(session_id); - if (it == arc_session_id_to_window_id_.end()) - return; - - arc_task_id_to_app_id_window_id_[task_id] = - std::make_pair(app_id, it->second); - arc_session_id_to_window_id_.erase(it); + if (arc_read_handler_) + arc_read_handler_->OnTaskCreated(app_id, task_id, session_id); } void FullRestoreReadHandler::OnTaskDestroyed(int32_t task_id) { - arc_task_id_to_app_id_window_id_.erase(task_id); + if (arc_read_handler_) + arc_read_handler_->OnTaskDestroyed(task_id); } void FullRestoreReadHandler::ReadFromFile(const base::FilePath& profile_path, @@ -188,11 +188,10 @@ } int32_t FullRestoreReadHandler::GetArcRestoreWindowId(int32_t task_id) { - auto it = arc_task_id_to_app_id_window_id_.find(task_id); - if (it == arc_task_id_to_app_id_window_id_.end()) - return -1; + if (!arc_read_handler_) + return 0; - return it->second.second; + return arc_read_handler_->GetArcRestoreWindowId(task_id); } void FullRestoreReadHandler::ModifyWidgetParams( @@ -232,19 +231,14 @@ } int32_t FullRestoreReadHandler::GetArcSessionId() { - if (arc_session_id_ < kArcSessionIdOffsetForRestoredLaunching) { - LOG(WARNING) << "ARC session id is overflow: " << arc_session_id_; - arc_session_id_ = kArcSessionIdOffsetForRestoredLaunching; - } - - return ++arc_session_id_; + DCHECK(arc_read_handler_); + return arc_read_handler_->GetArcSessionId(); } void FullRestoreReadHandler::SetArcSessionIdForWindowId(int32_t arc_session_id, int32_t window_id) { - DCHECK_GT(arc_session_id, - full_restore::kArcSessionIdOffsetForRestoredLaunching); - arc_session_id_to_window_id_[arc_session_id] = window_id; + DCHECK(arc_read_handler_); + arc_read_handler_->SetArcSessionIdForWindowId(arc_session_id, window_id); } void FullRestoreReadHandler::OnGetRestoreData( @@ -256,10 +250,19 @@ for (auto it = restore_data->app_id_to_launch_list().begin(); it != restore_data->app_id_to_launch_list().end(); it++) { + const std::string& app_id = it->first; for (auto data_it = it->second.begin(); data_it != it->second.end(); data_it++) { - window_id_to_app_restore_info_[data_it->first] = - std::make_pair(profile_path, it->first); + int32_t window_id = data_it->first; + // Only ARC app launch parameters have event_flag. + if (data_it->second->event_flag.has_value()) { + if (!arc_read_handler_) + arc_read_handler_ = std::make_unique<ArcReadHandler>(profile_path); + arc_read_handler_->AddRestoreData(app_id, window_id); + } else { + window_id_to_app_restore_info_[window_id] = + std::make_pair(profile_path, app_id); + } } } }
diff --git a/components/full_restore/full_restore_read_handler.h b/components/full_restore/full_restore_read_handler.h index f5a029a..cb98fbd 100644 --- a/components/full_restore/full_restore_read_handler.h +++ b/components/full_restore/full_restore_read_handler.h
@@ -7,12 +7,14 @@ #include <map> #include <memory> +#include <utility> #include "base/callback.h" #include "base/component_export.h" #include "base/files/file_path.h" #include "base/memory/weak_ptr.h" #include "base/scoped_multi_source_observation.h" +#include "components/full_restore/arc_read_handler.h" #include "components/full_restore/full_restore_utils.h" #include "ui/aura/env_observer.h" #include "ui/aura/window.h" @@ -120,16 +122,9 @@ // |arc session id| is assigned when ARC apps are restored. void SetArcSessionIdForWindowId(int32_t arc_session_id, int32_t window_id); - const std::map<int32_t, int32_t>& GetArcSessionIdMapForTesting() const { - return arc_session_id_to_window_id_; - } - - const std::map<int32_t, std::pair<std::string, int32_t>>& - GetArcTaskIdMapForTesting() const { - return arc_task_id_to_app_id_window_id_; - } - private: + friend class FullRestoreReadHandlerTestApi; + // Invoked when reading the restore data from |profile_path| is finished, and // calls |callback| to notify that the reading operation is done. void OnGetRestoreData(const base::FilePath& profile_path, @@ -153,15 +148,7 @@ std::map<int32_t, std::pair<base::FilePath, std::string>> window_id_to_app_restore_info_; - int32_t arc_session_id_ = - full_restore::kArcSessionIdOffsetForRestoredLaunching; - - // The map from the arc session id to the window id. - std::map<int32_t, int32_t> arc_session_id_to_window_id_; - - // The map from the arc task id to the app id and the window id. - std::map<int32_t, std::pair<std::string, int32_t>> - arc_task_id_to_app_id_window_id_; + std::unique_ptr<ArcReadHandler> arc_read_handler_; base::ScopedMultiSourceObservation<aura::Window, aura::WindowObserver> observed_windows_{this};
diff --git a/components/full_restore/full_restore_save_handler.h b/components/full_restore/full_restore_save_handler.h index cdae069a..e16f40f 100644 --- a/components/full_restore/full_restore_save_handler.h +++ b/components/full_restore/full_restore_save_handler.h
@@ -29,7 +29,6 @@ struct AppLaunchInfo; class FullRestoreFileHandler; -class FullRestoreSaveHandlerTestApi; class RestoreData; struct WindowInfo;
diff --git a/components/full_restore/full_restore_utils.h b/components/full_restore/full_restore_utils.h index 98290a13..2e354a52 100644 --- a/components/full_restore/full_restore_utils.h +++ b/components/full_restore/full_restore_utils.h
@@ -35,6 +35,10 @@ // assigned for ARC session ids. constexpr int32_t kArcSessionIdOffsetForRestoredLaunching = 1000000000; +// If the ARC task is not created when the window is initialized, set the +// restore window id as -1, to add the ARC app window to the hidden container. +constexpr int32_t kParentToHiddenContainer = -1; + // A property key to indicate the id for the window to be saved in RestoreData. // For web apps, browser windows or Chrome app windows, this is the session id. // For ARC apps, this is the task id.
diff --git a/components/history/core/browser/history_types.h b/components/history/core/browser/history_types.h index 8dc11ef..6786a5f 100644 --- a/components/history/core/browser/history_types.h +++ b/components/history/core/browser/history_types.h
@@ -104,7 +104,7 @@ // (https://github.com/WICG/floc) is an API that intends to provide callers // with coarse-grained information about the user’s browsing interests. The // history URL visits is a main source of computation, but some visits are - // ineligible to be included, so we use this bit to represent its eligiblity. + // ineligible to be included, so we use this bit to represent its eligibility. // // Currently this bit is "true" if the IP of this url visit was publicly // routable, i.e. the IP is NOT within the ranges reserved for "private" @@ -129,7 +129,7 @@ return visit_time < other.visit_time; } - // We allow the implicit copy constuctor and operator=. + // We allow the implicit copy constructor and operator=. }; // We pass around vectors of visits a lot @@ -300,7 +300,7 @@ QueryURLResult& operator=(QueryURLResult&&) noexcept; ~QueryURLResult(); - // Indicates whether the call to HistoryBackend::QueryURL was successfull + // Indicates whether the call to HistoryBackend::QueryURL was successful // or not. If false, then both |row| and |visits| fields are undefined. bool success = false; URLRow row;
diff --git a/components/history/core/browser/url_row.h b/components/history/core/browser/url_row.h index 764de67..813ece09 100644 --- a/components/history/core/browser/url_row.h +++ b/components/history/core/browser/url_row.h
@@ -144,7 +144,7 @@ // is usually for subframes. bool hidden_ = false; - // We support the implicit copy constuctor and operator=. + // We support the implicit copy constructor and operator=. }; typedef std::vector<URLRow> URLRows;
diff --git a/components/metrics/metrics_log.cc b/components/metrics/metrics_log.cc index cd0c8cc..807f90c 100644 --- a/components/metrics/metrics_log.cc +++ b/components/metrics/metrics_log.cc
@@ -214,12 +214,7 @@ metrics::SystemProfileProto::Hardware* hardware = system_profile->mutable_hardware(); -#if !defined(OS_IOS) - // On iOS, OperatingSystemArchitecture() returns values like iPad4,4 which is - // not the actual CPU architecture. Don't set it until the API is fixed. See - // crbug.com/370104 for details. hardware->set_cpu_architecture(base::SysInfo::OperatingSystemArchitecture()); -#endif auto app_os_arch = base::SysInfo::ProcessCPUArchitecture(); if (!app_os_arch.empty()) hardware->set_app_cpu_architecture(app_os_arch);
diff --git a/components/metrics/metrics_log_unittest.cc b/components/metrics/metrics_log_unittest.cc index 8ecc01d..19462db6 100644 --- a/components/metrics/metrics_log_unittest.cc +++ b/components/metrics/metrics_log_unittest.cc
@@ -178,9 +178,7 @@ #endif metrics::SystemProfileProto::Hardware* hardware = system_profile->mutable_hardware(); -#if !defined(OS_IOS) hardware->set_cpu_architecture(base::SysInfo::OperatingSystemArchitecture()); -#endif auto app_os_arch = base::SysInfo::ProcessCPUArchitecture(); if (!app_os_arch.empty()) hardware->set_app_cpu_architecture(app_os_arch);
diff --git a/components/optimization_guide/content/browser/BUILD.gn b/components/optimization_guide/content/browser/BUILD.gn index 65aa5f4..82d63f3 100644 --- a/components/optimization_guide/content/browser/BUILD.gn +++ b/components/optimization_guide/content/browser/BUILD.gn
@@ -16,6 +16,8 @@ "page_content_annotations_service.h", "page_content_annotations_web_contents_helper.cc", "page_content_annotations_web_contents_helper.h", + "page_text_dump_result.cc", + "page_text_dump_result.h", "page_text_observer.cc", "page_text_observer.h", ] @@ -68,6 +70,7 @@ testonly = true sources = [ "page_content_annotations_web_contents_helper_unittest.cc", + "page_text_dump_result_unittest.cc", "page_text_observer_unittest.cc", ] if (build_with_tflite_lib) {
diff --git a/components/optimization_guide/content/browser/page_content_annotations_web_contents_helper.cc b/components/optimization_guide/content/browser/page_content_annotations_web_contents_helper.cc index 091bb9b..ce248d8e 100644 --- a/components/optimization_guide/content/browser/page_content_annotations_web_contents_helper.cc +++ b/components/optimization_guide/content/browser/page_content_annotations_web_contents_helper.cc
@@ -5,7 +5,6 @@ #include "components/optimization_guide/content/browser/page_content_annotations_web_contents_helper.h" #include "base/bind.h" -#include "base/strings/utf_string_conversions.h" #include "components/optimization_guide/content/browser/page_content_annotations_service.h" #include "components/optimization_guide/core/optimization_guide_features.h" #include "content/public/browser/navigation_handle.h" @@ -40,22 +39,19 @@ PageContentAnnotationsWebContentsHelper::MaybeRequestFrameTextDump( content::NavigationHandle* navigation_handle) { DCHECK(navigation_handle->HasCommitted()); + DCHECK(navigation_handle->IsInMainFrame()); if (!navigation_handle->GetURL().SchemeIsHTTPOrHTTPS()) return nullptr; - if (!navigation_handle->IsInMainFrame()) - return nullptr; - // TODO(crbug/1177102): Change above to also annotate content for subframes - // when API exposes whether it makes up most of the frame. - // TODO(crbug/1177102): Figure out how to deal with same document navigations. std::unique_ptr<PageTextObserver::ConsumerTextDumpRequest> request = std::make_unique<PageTextObserver::ConsumerTextDumpRequest>(); request->max_size = max_size_for_text_dump_; request->events = {mojom::TextDumpEvent::kFirstLayout}; - request->callback = base::BindRepeating( + request->dump_amp_subframes = true; + request->callback = base::BindOnce( &PageContentAnnotationsWebContentsHelper::OnTextDumpReceived, weak_ptr_factory_.GetWeakPtr(), PageContentAnnotationsService::CreateHistoryVisitFromWebContents( @@ -65,8 +61,20 @@ void PageContentAnnotationsWebContentsHelper::OnTextDumpReceived( const HistoryVisit& visit, - const std::u16string& text) { - page_content_annotations_service_->Annotate(visit, base::UTF16ToUTF8(text)); + const PageTextDumpResult& result) { + if (result.empty()) { + return; + } + + // If the page had AMP frames, then only use that content. Otherwise, use the + // mainframe. + if (result.GetAMPTextContent()) { + page_content_annotations_service_->Annotate(visit, + *result.GetAMPTextContent()); + return; + } + page_content_annotations_service_->Annotate( + visit, *result.GetMainFrameTextContent()); } WEB_CONTENTS_USER_DATA_KEY_IMPL(PageContentAnnotationsWebContentsHelper)
diff --git a/components/optimization_guide/content/browser/page_content_annotations_web_contents_helper.h b/components/optimization_guide/content/browser/page_content_annotations_web_contents_helper.h index 286d6ec..7911424d 100644 --- a/components/optimization_guide/content/browser/page_content_annotations_web_contents_helper.h +++ b/components/optimization_guide/content/browser/page_content_annotations_web_contents_helper.h
@@ -6,6 +6,7 @@ #define COMPONENTS_OPTIMIZATION_GUIDE_CONTENT_BROWSER_PAGE_CONTENT_ANNOTATIONS_WEB_CONTENTS_HELPER_H_ #include "base/memory/weak_ptr.h" +#include "components/optimization_guide/content/browser/page_text_dump_result.h" #include "components/optimization_guide/content/browser/page_text_observer.h" #include "content/public/browser/web_contents_user_data.h" @@ -49,7 +50,7 @@ // Callback invoked when a text dump has been received for the |visit|. void OnTextDumpReceived(const HistoryVisit& visit, - const std::u16string& test); + const PageTextDumpResult& result); // Not owned. Guaranteed to outlive |this|. content::WebContents* web_contents_;
diff --git a/components/optimization_guide/content/browser/page_content_annotations_web_contents_helper_unittest.cc b/components/optimization_guide/content/browser/page_content_annotations_web_contents_helper_unittest.cc index 3ccee54..d9792a8 100644 --- a/components/optimization_guide/content/browser/page_content_annotations_web_contents_helper_unittest.cc +++ b/components/optimization_guide/content/browser/page_content_annotations_web_contents_helper_unittest.cc
@@ -6,7 +6,9 @@ #include "base/strings/utf_string_conversions.h" #include "components/optimization_guide/content/browser/page_content_annotations_service.h" +#include "components/optimization_guide/content/browser/page_text_dump_result.h" #include "components/optimization_guide/content/browser/test_optimization_guide_decider.h" +#include "components/optimization_guide/core/optimization_guide_features.h" #include "content/public/test/mock_navigation_handle.h" #include "content/public/test/navigation_simulator.h" #include "content/public/test/test_renderer_host.h" @@ -91,19 +93,11 @@ TestPageTextObserver* page_text_observer() { return page_text_observer_; } std::unique_ptr<PageTextObserver::ConsumerTextDumpRequest> - RequestTextDumpForUrl(const GURL& url, bool is_main_frame) { - content::RenderFrameHost* frame = main_rfh(); - if (!is_main_frame) { - // Commit main frame, so we can attach the subframe. - content::NavigationSimulator::NavigateAndCommitFromBrowser( - web_contents(), GURL("http://test.com")); - frame = content::RenderFrameHostTester::For(main_rfh()) - ->AppendChild("subframe"); - } - content::MockNavigationHandle navigation_handle(url, frame); + RequestTextDumpForUrl(const GURL& url) { + content::MockNavigationHandle navigation_handle(url, main_rfh()); navigation_handle.set_url(url); // PageTextObserver is guaranteed to call MaybeRequestFrameTextDump after - // the navigation has been committeed. + // the navigation has been committed. navigation_handle.set_has_committed(true); return helper()->MaybeRequestFrameTextDump(&navigation_handle); } @@ -121,15 +115,7 @@ TEST_F(PageContentAnnotationsWebContentsHelperTest, DoesNotRequestForNonHttpHttps) { - EXPECT_EQ( - RequestTextDumpForUrl(GURL("chrome://new-tab"), /*is_main_frame=*/true), - nullptr); -} - -TEST_F(PageContentAnnotationsWebContentsHelperTest, DoesNotRequestForSubframe) { - EXPECT_EQ( - RequestTextDumpForUrl(GURL("http://test.com"), /*is_main_frame=*/false), - nullptr); + EXPECT_EQ(RequestTextDumpForUrl(GURL("chrome://new-tab")), nullptr); } TEST_F(PageContentAnnotationsWebContentsHelperTest, @@ -141,11 +127,23 @@ web_contents(), GURL("http://test.com")); std::unique_ptr<PageTextObserver::ConsumerTextDumpRequest> request = - RequestTextDumpForUrl(GURL("http://test.com"), /*is_main_frame=*/true); + RequestTextDumpForUrl(GURL("http://test.com")); ASSERT_TRUE(request); + ASSERT_TRUE(request->callback); + EXPECT_EQ(features::MaxSizeForPageContentTextDump(), request->max_size); + EXPECT_TRUE(request->dump_amp_subframes); + EXPECT_EQ(std::set<mojom::TextDumpEvent>{mojom::TextDumpEvent::kFirstLayout}, + request->events); // Invoke OnTextDumpReceived. - std::move(request->callback).Run(base::ASCIIToUTF16("some text")); + FrameTextDumpResult frame_result = + FrameTextDumpResult::Initialize(mojom::TextDumpEvent::kFirstLayout, + content::GlobalFrameRoutingId(), + /*amp_frame=*/false) + .CompleteWithContents(base::ASCIIToUTF16("some text")); + PageTextDumpResult result; + result.AddFrameTextDumpResult(frame_result); + std::move(request->callback).Run(std::move(result)); base::Optional<std::pair<HistoryVisit, std::string>> last_annotation_request = service()->last_annotation_request();
diff --git a/components/optimization_guide/content/browser/page_text_dump_result.cc b/components/optimization_guide/content/browser/page_text_dump_result.cc new file mode 100644 index 0000000..628438a --- /dev/null +++ b/components/optimization_guide/content/browser/page_text_dump_result.cc
@@ -0,0 +1,147 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/optimization_guide/content/browser/page_text_dump_result.h" + +#include <algorithm> + +#include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" + +namespace optimization_guide { + +namespace { + +std::string TextDumpEventToString(mojom::TextDumpEvent value) { + switch (value) { + case mojom::TextDumpEvent::kFirstLayout: + return "kFirstLayout"; + case mojom::TextDumpEvent::kFinishedLoad: + return "kFinishedLoad"; + } +} + +} // namespace + +PageTextDumpResult::PageTextDumpResult() = default; +PageTextDumpResult::PageTextDumpResult(const PageTextDumpResult&) = default; +PageTextDumpResult::~PageTextDumpResult() = default; + +void PageTextDumpResult::AddFrameTextDumpResult( + const FrameTextDumpResult& frame_result) { + DCHECK(frame_result.IsCompleted()); + frame_results_.emplace(frame_result); +} + +base::Optional<std::string> PageTextDumpResult::GetAMPTextContent() const { + if (empty()) { + return base::nullopt; + } + + // AMP frames are sorted in beginning, so if there are none then return null. + if (!frame_results_.begin()->amp_frame()) { + return base::nullopt; + } + + std::vector<std::string> amp_text; + for (const FrameTextDumpResult& frame_result : frame_results_) { + DCHECK(frame_result.utf8_contents()); + + if (!frame_result.amp_frame()) { + break; + } + + amp_text.push_back(*frame_result.utf8_contents()); + } + DCHECK(!amp_text.empty()); + + return base::JoinString(amp_text, " "); +} + +base::Optional<std::string> PageTextDumpResult::GetMainFrameTextContent() + const { + if (empty()) { + return base::nullopt; + } + + // Mainframes are sorted to the end. + if (frame_results_.rbegin()->amp_frame()) { + return base::nullopt; + } + + // There should only be one mainframe. + DCHECK(frame_results_.rbegin()->utf8_contents()); + return *frame_results_.rbegin()->utf8_contents(); +} + +base::Optional<std::string> PageTextDumpResult::GetAllFramesTextContent() + const { + if (empty()) { + return base::nullopt; + } + + std::vector<std::string> text; + for (const FrameTextDumpResult& frame_result : frame_results_) { + DCHECK(frame_result.utf8_contents()); + text.push_back(*frame_result.utf8_contents()); + } + DCHECK(!text.empty()); + + return base::JoinString(text, " "); +} + +FrameTextDumpResult::FrameTextDumpResult() = default; +FrameTextDumpResult::~FrameTextDumpResult() = default; +FrameTextDumpResult::FrameTextDumpResult(const FrameTextDumpResult&) = default; + +// static +FrameTextDumpResult FrameTextDumpResult::Initialize( + mojom::TextDumpEvent event, + content::GlobalFrameRoutingId rfh_id, + bool amp_frame) { + FrameTextDumpResult result; + result.event_ = event; + result.rfh_id_ = rfh_id; + result.amp_frame_ = amp_frame; + return result; +} + +FrameTextDumpResult FrameTextDumpResult::CompleteWithContents( + const std::u16string& contents) const { + DCHECK(!IsCompleted()); + DCHECK(!contents.empty()); + + FrameTextDumpResult copy = *this; + copy.contents_ = contents; + return copy; +} + +bool FrameTextDumpResult::IsCompleted() const { + return !!contents(); +} + +base::Optional<std::string> FrameTextDumpResult::utf8_contents() const { + if (!contents_) { + return base::nullopt; + } + return base::UTF16ToUTF8(*contents_); +} + +std::ostream& operator<<(std::ostream& os, const FrameTextDumpResult& frame) { + return os << base::StringPrintf( + "event:%s rfh_id:(%d,%d) amp_frame:%s contents:%s", + TextDumpEventToString(frame.event()).c_str(), + frame.rfh_id().child_id, frame.rfh_id().frame_routing_id, + frame.amp_frame() ? "true" : "false", + frame.utf8_contents().value_or("null").c_str()); +} + +std::ostream& operator<<(std::ostream& os, const PageTextDumpResult& page) { + for (const FrameTextDumpResult& frame : page.frame_results()) { + os << frame << "\n"; + } + return os; +} + +} // namespace optimization_guide
diff --git a/components/optimization_guide/content/browser/page_text_dump_result.h b/components/optimization_guide/content/browser/page_text_dump_result.h new file mode 100644 index 0000000..2381e8f --- /dev/null +++ b/components/optimization_guide/content/browser/page_text_dump_result.h
@@ -0,0 +1,144 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_OPTIMIZATION_GUIDE_CONTENT_BROWSER_PAGE_TEXT_DUMP_RESULT_H_ +#define COMPONENTS_OPTIMIZATION_GUIDE_CONTENT_BROWSER_PAGE_TEXT_DUMP_RESULT_H_ + +#include <set> +#include <string> + +#include "base/optional.h" +#include "components/optimization_guide/content/mojom/page_text_service.mojom.h" +#include "content/public/browser/global_routing_id.h" + +namespace optimization_guide { + +// This class contains the text dump from a single renderer and associated +// metadata. The lifecycle of this class is in two phases, preliminary and +// final. Preliminary is when the frame metadata is known, but the text dump has +// not been received yet. Once the text dump is received, then the dump is +// completed. +class FrameTextDumpResult { + public: + ~FrameTextDumpResult(); + FrameTextDumpResult(const FrameTextDumpResult&); + + // Creates a preliminary instance with the given metadata. + static FrameTextDumpResult Initialize(mojom::TextDumpEvent event, + content::GlobalFrameRoutingId rfh_id, + bool amp_frame); + + // Returns a copy of |this| that is completed with |contents|. This is only + // expected to be called once on Preliminary instances. + FrameTextDumpResult CompleteWithContents( + const std::u16string& contents) const; + + // Whether the class instance is completed yet. + bool IsCompleted() const; + + // The text dump contents. Set only for completed instances. + const base::Optional<std::u16string>& contents() const { return contents_; } + + // The text dump contents, decoded to UTF-8 as a best effort. Set only for + // completed instances. + base::Optional<std::string> utf8_contents() const; + + // The event at which the text dump is taken. Set for both preliminary and + // completed instances. + mojom::TextDumpEvent event() const { return event_; } + + // The unique identifier for the content::RenderFrameHost that the text dump + // was taken in. Set for both preliminary and completed instances. + content::GlobalFrameRoutingId rfh_id() const { return rfh_id_; } + + // Whether the frame the text dump is taken in an AMP frame. Set for both + // preliminary and completed instances. + bool amp_frame() const { return amp_frame_; } + + // These objects are sorted in the following manner: + // * AMP frames first - When there are AMP frames on a page, it is expected + // that they will contain the most content. + // * Longer contents first - Most consumers will only be interested in some of + // the page text. In this case, ensure that the biggest blob of text comes + // first since that is most likely to be the main content on the page. + // * Later events first - The later in the page's lifetime a text dump is + // taken, the more likely that it is complete. + // * Everything else is just done willy-nilly for completeness of equality + // checking. + inline bool operator<(const FrameTextDumpResult& rhs) const { + if (amp_frame() != rhs.amp_frame()) { + return amp_frame(); + } + + size_t lhs_size = contents() ? contents()->size() : 0; + size_t rhs_size = rhs.contents() ? rhs.contents()->size() : 0; + if (lhs_size != rhs_size) { + // Note the reverse ordering to put longer contents first. + return lhs_size > rhs_size; + } + + if (event() != rhs.event()) { + // Note the reverse ordering to put later events first. + return event() > rhs.event(); + } + + return std::tie(rfh_id_, contents_) < std::tie(rhs.rfh_id_, rhs.contents_); + } + + inline bool operator==(const FrameTextDumpResult& other) const { + return std::tie(event_, contents_, rfh_id_, amp_frame_) == + std::tie(other.event_, other.contents_, other.rfh_id_, + other.amp_frame_); + } + + private: + FrameTextDumpResult(); + + mojom::TextDumpEvent event_; + base::Optional<std::u16string> contents_; + content::GlobalFrameRoutingId rfh_id_; + bool amp_frame_ = false; +}; + +// Contains 0 or more FrameTextDumpResults from the same page load. +class PageTextDumpResult { + public: + PageTextDumpResult(); + PageTextDumpResult(const PageTextDumpResult&); + ~PageTextDumpResult(); + + // Adds another frame text dump to |this|. + void AddFrameTextDumpResult(const FrameTextDumpResult& frame_result); + + // Returns the concatenation of all AMP frames. nullopt if no AMP frames are + // present. + base::Optional<std::string> GetAMPTextContent() const; + + // Returns the concatenation of the mainframe. nullopt if not present. + base::Optional<std::string> GetMainFrameTextContent() const; + + // Returns the concatenation of all frames, AMP or main. nullopt if |empty()|. + base::Optional<std::string> GetAllFramesTextContent() const; + + bool empty() const { return frame_results_.empty(); } + + const std::set<FrameTextDumpResult>& frame_results() const { + return frame_results_; + } + + inline bool operator==(const PageTextDumpResult& other) const { + return frame_results_ == other.frame_results_; + } + + private: + std::set<FrameTextDumpResult> frame_results_; +}; + +// Useful for debugging. +std::ostream& operator<<(std::ostream& os, const FrameTextDumpResult& frame); +std::ostream& operator<<(std::ostream& os, const PageTextDumpResult& page); + +} // namespace optimization_guide + +#endif // COMPONENTS_OPTIMIZATION_GUIDE_CONTENT_BROWSER_PAGE_TEXT_DUMP_RESULT_H_
diff --git a/components/optimization_guide/content/browser/page_text_dump_result_unittest.cc b/components/optimization_guide/content/browser/page_text_dump_result_unittest.cc new file mode 100644 index 0000000..fb958c1 --- /dev/null +++ b/components/optimization_guide/content/browser/page_text_dump_result_unittest.cc
@@ -0,0 +1,177 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/optimization_guide/content/browser/page_text_dump_result.h" + +#include "base/strings/utf_string_conversions.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace optimization_guide { + +TEST(FrameTextDumpResultTest, Preliminary) { + content::GlobalFrameRoutingId id(1, 2); + FrameTextDumpResult frame_result = + FrameTextDumpResult::Initialize(mojom::TextDumpEvent::kFirstLayout, id, + /*amp_frame=*/false); + + EXPECT_FALSE(frame_result.IsCompleted()); + EXPECT_EQ(mojom::TextDumpEvent::kFirstLayout, frame_result.event()); + EXPECT_EQ(id, frame_result.rfh_id()); + EXPECT_FALSE(frame_result.amp_frame()); +} + +TEST(FrameTextDumpResultTest, Equality) { + FrameTextDumpResult starting_frame_result = + FrameTextDumpResult::Initialize(mojom::TextDumpEvent::kFirstLayout, + content::GlobalFrameRoutingId(1, 2), + /*amp_frame=*/false) + .CompleteWithContents(base::ASCIIToUTF16("abc")); + + FrameTextDumpResult different_event = + FrameTextDumpResult::Initialize(mojom::TextDumpEvent::kFinishedLoad, + content::GlobalFrameRoutingId(1, 2), + /*amp_frame=*/false) + .CompleteWithContents(base::ASCIIToUTF16("abc")); + + FrameTextDumpResult different_id = + FrameTextDumpResult::Initialize(mojom::TextDumpEvent::kFirstLayout, + content::GlobalFrameRoutingId(2, 1), + /*amp_frame=*/false) + .CompleteWithContents(base::ASCIIToUTF16("abc")); + + FrameTextDumpResult different_amp_frame = + FrameTextDumpResult::Initialize(mojom::TextDumpEvent::kFirstLayout, + content::GlobalFrameRoutingId(1, 2), + /*amp_frame=*/true) + .CompleteWithContents(base::ASCIIToUTF16("abc")); + + FrameTextDumpResult different_contents = + FrameTextDumpResult::Initialize(mojom::TextDumpEvent::kFirstLayout, + content::GlobalFrameRoutingId(1, 2), + /*amp_frame=*/false) + .CompleteWithContents(base::ASCIIToUTF16("abcd")); + + std::vector<FrameTextDumpResult> all_frame_results = { + starting_frame_result, different_event, different_id, + different_amp_frame, different_contents, + }; + for (size_t lhs = 0; lhs < all_frame_results.size() - 1; lhs++) { + for (size_t rhs = lhs + 1; rhs < all_frame_results.size(); rhs++) { + SCOPED_TRACE(base::StringPrintf("lhs: %zu, rhs: %zu", lhs, rhs)); + EXPECT_FALSE(all_frame_results[lhs] == all_frame_results[rhs]); + } + } +} + +TEST(FrameTextDumpResultTest, Ordering) { + FrameTextDumpResult starting_frame_result = + FrameTextDumpResult::Initialize(mojom::TextDumpEvent::kFirstLayout, + content::GlobalFrameRoutingId(1, 2), + /*amp_frame=*/false) + .CompleteWithContents(base::ASCIIToUTF16("abc")); + + FrameTextDumpResult later_event_frame_result = + FrameTextDumpResult::Initialize(mojom::TextDumpEvent::kFinishedLoad, + content::GlobalFrameRoutingId(1, 2), + /*amp_frame=*/false) + .CompleteWithContents(base::ASCIIToUTF16("abc")); + + FrameTextDumpResult longer_frame_result = + FrameTextDumpResult::Initialize(mojom::TextDumpEvent::kFirstLayout, + content::GlobalFrameRoutingId(1, 2), + /*amp_frame=*/false) + .CompleteWithContents(base::ASCIIToUTF16("abcd")); + + FrameTextDumpResult amp_frame_result = + FrameTextDumpResult::Initialize(mojom::TextDumpEvent::kFirstLayout, + content::GlobalFrameRoutingId(1, 2), + /*amp_frame=*/true) + .CompleteWithContents(base::ASCIIToUTF16("abc")); + + FrameTextDumpResult longer_amp_frame_result = + FrameTextDumpResult::Initialize(mojom::TextDumpEvent::kFirstLayout, + content::GlobalFrameRoutingId(1, 2), + /*amp_frame=*/true) + .CompleteWithContents(base::ASCIIToUTF16("abcd")); + + std::set<FrameTextDumpResult> ordered_set{ + starting_frame_result, later_event_frame_result, longer_frame_result, + amp_frame_result, longer_amp_frame_result}; + EXPECT_THAT(ordered_set, ::testing::ElementsAreArray({ + longer_amp_frame_result, + amp_frame_result, + longer_frame_result, + later_event_frame_result, + starting_frame_result, + })); +} + +TEST(PageTextDumpResultTest, Empty) { + PageTextDumpResult page_result; + EXPECT_TRUE(page_result.empty()); + EXPECT_EQ(base::nullopt, page_result.GetAMPTextContent()); + EXPECT_EQ(base::nullopt, page_result.GetMainFrameTextContent()); + EXPECT_EQ(base::nullopt, page_result.GetAllFramesTextContent()); +} + +TEST(PageTextDumpResultTest, OneAMP) { + PageTextDumpResult page_result; + page_result.AddFrameTextDumpResult( + FrameTextDumpResult::Initialize(mojom::TextDumpEvent::kFinishedLoad, + content::GlobalFrameRoutingId(2, 1), + /*amp_frame=*/true) + .CompleteWithContents(base::ASCIIToUTF16("amp frame"))); + + ASSERT_TRUE(page_result.GetAMPTextContent()); + EXPECT_EQ("amp frame", *page_result.GetAMPTextContent()); + + EXPECT_FALSE(page_result.GetMainFrameTextContent()); + + ASSERT_TRUE(page_result.GetAllFramesTextContent()); + EXPECT_EQ("amp frame", *page_result.GetAllFramesTextContent()); +} + +TEST(PageTextDumpResultTest, OneMainframe) { + PageTextDumpResult page_result; + page_result.AddFrameTextDumpResult( + FrameTextDumpResult::Initialize(mojom::TextDumpEvent::kFirstLayout, + content::GlobalFrameRoutingId(1, 2), + /*amp_frame=*/false) + .CompleteWithContents(base::ASCIIToUTF16("mainframe"))); + + EXPECT_FALSE(page_result.GetAMPTextContent()); + + ASSERT_TRUE(page_result.GetMainFrameTextContent()); + EXPECT_EQ("mainframe", *page_result.GetMainFrameTextContent()); + + ASSERT_TRUE(page_result.GetAllFramesTextContent()); + EXPECT_EQ("mainframe", *page_result.GetAllFramesTextContent()); +} + +TEST(PageTextDumpResultTest, OneAMPOneMF) { + PageTextDumpResult page_result; + page_result.AddFrameTextDumpResult( + FrameTextDumpResult::Initialize(mojom::TextDumpEvent::kFirstLayout, + content::GlobalFrameRoutingId(1, 2), + /*amp_frame=*/false) + .CompleteWithContents(base::ASCIIToUTF16("mainframe"))); + + page_result.AddFrameTextDumpResult( + FrameTextDumpResult::Initialize(mojom::TextDumpEvent::kFinishedLoad, + content::GlobalFrameRoutingId(2, 1), + /*amp_frame=*/true) + .CompleteWithContents(base::ASCIIToUTF16("amp frame"))); + + ASSERT_TRUE(page_result.GetAMPTextContent()); + EXPECT_EQ("amp frame", *page_result.GetAMPTextContent()); + + ASSERT_TRUE(page_result.GetMainFrameTextContent()); + EXPECT_EQ("mainframe", *page_result.GetMainFrameTextContent()); + + ASSERT_TRUE(page_result.GetAllFramesTextContent()); + EXPECT_EQ("amp frame mainframe", *page_result.GetAllFramesTextContent()); +} + +} // namespace optimization_guide
diff --git a/components/optimization_guide/content/browser/page_text_observer.cc b/components/optimization_guide/content/browser/page_text_observer.cc index 14e8126..2131e11b 100644 --- a/components/optimization_guide/content/browser/page_text_observer.cc +++ b/components/optimization_guide/content/browser/page_text_observer.cc
@@ -10,10 +10,14 @@ #include <vector> #include "base/bind.h" +#include "base/feature_list.h" #include "base/memory/scoped_refptr.h" #include "base/strings/strcat.h" #include "base/threading/sequenced_task_runner_handle.h" #include "base/time/time.h" +#include "components/optimization_guide/core/optimization_guide_features.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" @@ -35,9 +39,10 @@ // in stack. class PageTextChunkConsumer : public mojom::PageTextConsumer { public: - PageTextChunkConsumer(mojo::PendingReceiver<mojom::PageTextConsumer> receiver, - uint32_t max_size, - base::OnceCallback<void(std::u16string)> on_complete) + PageTextChunkConsumer( + mojo::PendingReceiver<mojom::PageTextConsumer> receiver, + uint32_t max_size, + base::OnceCallback<void(const std::u16string&)> on_complete) : remaining_size_(max_size), on_complete_(std::move(on_complete)), receiver_(this, std::move(receiver)) { @@ -88,7 +93,7 @@ // While |on_complete_| is non-null, the mojo pipe is also bound. Once the // |on_complete_| callback is run, this class is no longer active and can be // deleted (in stack with the callback). - base::OnceCallback<void(std::u16string)> on_complete_; + base::OnceCallback<void(const std::u16string&)> on_complete_; mojo::Receiver<mojom::PageTextConsumer> receiver_; // All chunks that have been read from the data pipe. These will be @@ -130,6 +135,7 @@ // along with copies of the scoped_refptr, making mojo the effective owner of // this class. Note that one or more requests have been made at this point and // this class will remain alive until they have all been completed and handled. +// The count of outgoing requests sent to a renderer is returned. // // (4) The PageTextConsumer will receive chunks of the dumped page text until // either (a) all chunks have been read, or (b) the max length is reached. When @@ -137,39 +143,71 @@ // back to RequestMediator in a callback. // // (5) The callback to RequestMediator is the end of the line for a text dump -// response as the original requests' callbacks are now passed the dumped -// string16. At this time, the self scoped_refptr will fall out of scope and be -// destroyed. If it was the last such pointer, then |this| will be destroyed. +// response as the |on_complete_| callback is run. At this time, the self +// scoped_refptr will fall out of scope and be destroyed. If it was the last +// such pointer, then |this| will be destroyed. class RequestMediator : public base::RefCounted<RequestMediator> { public: RequestMediator() = default; void AddConsumerRequest( - std::unique_ptr<PageTextObserver::ConsumerTextDumpRequest> request) { - DCHECK(request->callback); - DCHECK(!request->events.empty()); - DCHECK_GT(request->max_size, 0U); + const PageTextObserver::ConsumerTextDumpRequest& request) { + DCHECK(!request.events.empty()); + DCHECK_GT(request.max_size, 0U); - for (mojom::TextDumpEvent event : request->events) { + for (mojom::TextDumpEvent event : request.events) { if (max_size_by_event_.find(event) == max_size_by_event_.end()) { max_size_by_event_.emplace(event, 0U); } auto event_to_max_size_iter = max_size_by_event_.find(event); event_to_max_size_iter->second = - std::max(event_to_max_size_iter->second, request->max_size); + std::max(event_to_max_size_iter->second, request.max_size); } - - requests_.push_back(std::move(request)); } - void MakeSelfOwnedAndDispatchRequests( + void AddAMPRequest(const PageTextObserver::ConsumerTextDumpRequest& request) { + if (!request.dump_amp_subframes) { + return; + } + + auto iter = max_size_by_event_.find(mojom::TextDumpEvent::kFinishedLoad); + if (iter == max_size_by_event_.end()) { + max_size_by_event_.emplace(mojom::TextDumpEvent::kFinishedLoad, + request.max_size); + return; + } + + iter->second = std::max(iter->second, request.max_size); + } + + size_t MakeSelfOwnedAndDispatchRequests( scoped_refptr<RequestMediator> self, - mojo::AssociatedRemote<mojom::PageTextService> renderer_text_service) { + base::RepeatingCallback<void(base::Optional<FrameTextDumpResult>)> + on_frame_text_dump_complete, + content::RenderFrameHost* rfh) { DCHECK_EQ(self.get(), this); + if (max_size_by_event_.empty()) { + return 0; + } + + on_frame_text_dump_complete_ = std::move(on_frame_text_dump_complete); + + mojo::AssociatedRemote<mojom::PageTextService> renderer_text_service; + rfh->GetRemoteAssociatedInterfaces()->GetInterface(&renderer_text_service); + + bool is_subframe = rfh->GetMainFrame() != rfh; + auto rfh_id = rfh->GetGlobalFrameRoutingId(); + for (const auto& event_to_max_size_iter : max_size_by_event_) { mojo::PendingRemote<mojom::PageTextConsumer> consumer_remote; + FrameTextDumpResult preliminary_result = FrameTextDumpResult::Initialize( + event_to_max_size_iter.first, rfh_id, + // Note that subframes only take text dumps iff they are an AMP + // frame. If that even changes, this won't work anymore. + /*amp_frame=*/is_subframe); + std::unique_ptr<PageTextChunkConsumer> consumer = std::make_unique<PageTextChunkConsumer>( consumer_remote.InitWithNewPipeAndPassReceiver(), @@ -178,8 +216,7 @@ // passed to |consumer|. See comment at end of method for more // detail. base::BindOnce(&RequestMediator::OnPageTextAsString, - base::Unretained(this), self, - event_to_max_size_iter.first)); + base::Unretained(this), self, preliminary_result)); auto request = mojom::PageTextDumpRequest::New(); request->max_size = event_to_max_size_iter.second; @@ -195,6 +232,8 @@ // destroy |this| (if it was the last owning reference). consumers_.emplace(std::move(consumer)); } + + return max_size_by_event_.size(); } private: @@ -202,18 +241,23 @@ ~RequestMediator() = default; void OnPageTextAsString(scoped_refptr<RequestMediator> self, - mojom::TextDumpEvent event, - const std::u16string page_text) { - for (const auto& request : requests_) { - if (request->events.find(event) != request->events.end()) { - request->callback.Run(page_text); - } + const FrameTextDumpResult& preliminary_result, + const std::u16string& page_text) { + DCHECK(on_frame_text_dump_complete_); + + if (page_text.empty()) { + on_frame_text_dump_complete_.Run(base::nullopt); + return; } + + on_frame_text_dump_complete_.Run( + preliminary_result.CompleteWithContents(page_text)); } - // All text dumps requests. - std::vector<std::unique_ptr<PageTextObserver::ConsumerTextDumpRequest>> - requests_; + // Called whenever a text dump is completed for an event. This called as many + // times as events requested, which can be greater than 1. + base::RepeatingCallback<void(base::Optional<FrameTextDumpResult>)> + on_frame_text_dump_complete_; // All |PageTextChunkConsumer|'s that are owned by this. std::set<std::unique_ptr<PageTextChunkConsumer>> consumers_; @@ -239,13 +283,19 @@ return PageTextObserver::FromWebContents(web_contents); } -void PageTextObserver::DidFinishNavigation(content::NavigationHandle* handle) { - if (consumers_.empty()) { +void PageTextObserver::DidStartNavigation(content::NavigationHandle* handle) { + if (!handle->IsInMainFrame()) { return; } + requests_.clear(); + page_result_.reset(); + outstanding_requests_ = 0; + outstanding_requests_grace_timer_.reset(); +} + +void PageTextObserver::DidFinishNavigation(content::NavigationHandle* handle) { // Only main frames are supported for right now. - // TODO(crbug/1163244): Add subframe support. if (!handle->IsInMainFrame()) { return; } @@ -254,23 +304,97 @@ return; } - content::RenderFrameHost* render_frame_host = handle->GetRenderFrameHost(); + if (consumers_.empty()) { + return; + } scoped_refptr<RequestMediator> mediator = base::MakeRefCounted<RequestMediator>(); for (Consumer* consumer : consumers_) { auto request = consumer->MaybeRequestFrameTextDump(handle); - if (request) { - mediator->AddConsumerRequest(std::move(request)); + if (!request) { + continue; } + mediator->AddConsumerRequest(*request); + requests_.push_back(std::move(request)); } - mojo::AssociatedRemote<mojom::PageTextService> renderer_text_service; - render_frame_host->GetRemoteAssociatedInterfaces()->GetInterface( - &renderer_text_service); + outstanding_requests_ += mediator->MakeSelfOwnedAndDispatchRequests( + mediator, + base::BindRepeating(&PageTextObserver::OnFrameTextDumpCompleted, + weak_factory_.GetWeakPtr()), + handle->GetRenderFrameHost()); +} - mediator->MakeSelfOwnedAndDispatchRequests(mediator, - std::move(renderer_text_service)); +bool PageTextObserver::IsOOPIF(content::RenderFrameHost* rfh) const { + return rfh->GetProcess()->GetID() != + rfh->GetMainFrame()->GetProcess()->GetID(); +} + +void PageTextObserver::RenderFrameCreated(content::RenderFrameHost* rfh) { + if (!IsOOPIF(rfh)) { + return; + } + + scoped_refptr<RequestMediator> mediator = + base::MakeRefCounted<RequestMediator>(); + for (const auto& request : requests_) { + mediator->AddAMPRequest(*request); + } + + outstanding_requests_ += mediator->MakeSelfOwnedAndDispatchRequests( + mediator, + base::BindRepeating(&PageTextObserver::OnFrameTextDumpCompleted, + weak_factory_.GetWeakPtr()), + rfh); +} + +void PageTextObserver::OnFrameTextDumpCompleted( + base::Optional<FrameTextDumpResult> frame_result) { + // |frame_result| will be null in the event the RFH dies, in which case we can + // no longer expect the request to be fulfilled, so it should not be counted + // as outstanding anymore. + outstanding_requests_--; + + if (frame_result) { + if (!page_result_) { + page_result_ = std::make_unique<PageTextDumpResult>(); + } + page_result_->AddFrameTextDumpResult(*frame_result); + } + + if (!!outstanding_requests_grace_timer_ && outstanding_requests_ == 0) { + outstanding_requests_grace_timer_.reset(); + DispatchResponses(); + } +} + +void PageTextObserver::DidFinishLoad( + content::RenderFrameHost* render_frame_host, + const GURL& validated_url) { + if (outstanding_requests_ > 0) { + outstanding_requests_grace_timer_ = std::make_unique<base::OneShotTimer>(); + outstanding_requests_grace_timer_->Start( + FROM_HERE, features::PageTextExtractionOutstandingRequestsGracePeriod(), + base::BindOnce(&PageTextObserver::DispatchResponses, + base::Unretained(this))); + return; + } + DispatchResponses(); +} + +void PageTextObserver::DispatchResponses() { + outstanding_requests_grace_timer_.reset(); + + if (!page_result_) { + return; + } + + for (const auto& consumer_request : requests_) { + std::move(consumer_request->callback).Run(*page_result_); + } + requests_.clear(); + page_result_.reset(); } void PageTextObserver::AddConsumer(Consumer* consumer) {
diff --git a/components/optimization_guide/content/browser/page_text_observer.h b/components/optimization_guide/content/browser/page_text_observer.h index a4ba615..0cc6c1e15 100644 --- a/components/optimization_guide/content/browser/page_text_observer.h +++ b/components/optimization_guide/content/browser/page_text_observer.h
@@ -11,6 +11,8 @@ #include "base/callback.h" #include "base/memory/weak_ptr.h" +#include "base/timer/timer.h" +#include "components/optimization_guide/content/browser/page_text_dump_result.h" #include "components/optimization_guide/content/mojom/page_text_service.mojom.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" @@ -50,7 +52,7 @@ // The callback that is used to provide dumped page text. using TextDumpCallback = - base::RepeatingCallback<void(const std::u16string&)>; + base::OnceCallback<void(const PageTextDumpResult&)>; TextDumpCallback callback; // The max size of the text dump in bytes. Note that the actual size @@ -59,6 +61,12 @@ // pages with little text. uint32_t max_size = 0; + // Set when subframe text dumps should be taken on AMP subframes. A text + // dump of the mainframe will always also be taken. Consumer who set this + // should use |PageTextDumpResult::ConcatenateWithAMPHandling| on the + // |callback|. + bool dump_amp_subframes = false; + // All of the |TextDumpEvent|'s that have been requested. std::set<mojom::TextDumpEvent> events; }; @@ -79,7 +87,11 @@ virtual void RemoveConsumer(Consumer* consumer); // content::WebContentsObserver: + void DidStartNavigation(content::NavigationHandle* handle) override; void DidFinishNavigation(content::NavigationHandle* handle) override; + void RenderFrameCreated(content::RenderFrameHost* rfh) override; + void DidFinishLoad(content::RenderFrameHost* render_frame_host, + const GURL& validated_url) override; PageTextObserver(const PageTextObserver&) = delete; PageTextObserver& operator=(const PageTextObserver&) = delete; @@ -87,12 +99,32 @@ protected: explicit PageTextObserver(content::WebContents* web_contents); + // Virtual for testing. + virtual bool IsOOPIF(content::RenderFrameHost* rfh) const; + private: friend class content::WebContentsUserData<PageTextObserver>; + void OnFrameTextDumpCompleted( + base::Optional<FrameTextDumpResult> frame_result); + + void DispatchResponses(); + // All registered consumers. std::set<Consumer*> consumers_; + // A persisted set of consumer requests. + std::vector<std::unique_ptr<ConsumerTextDumpRequest>> requests_; + + std::unique_ptr<PageTextDumpResult> page_result_; + + // |outstanding_requests_grace_timer_| is set after |DidFinishLoad| if the + // number of |outstanding_requests_| is > 0. When the timer fires, the + // |page_result_| will be finialized and dispatched to consumers (in + // |DispatchResponses|). + std::unique_ptr<base::OneShotTimer> outstanding_requests_grace_timer_; + size_t outstanding_requests_ = 0; + base::WeakPtrFactory<PageTextObserver> weak_factory_{this}; WEB_CONTENTS_USER_DATA_KEY_DECL();
diff --git a/components/optimization_guide/content/browser/page_text_observer_unittest.cc b/components/optimization_guide/content/browser/page_text_observer_unittest.cc index 8f83e63..54ec3f8 100644 --- a/components/optimization_guide/content/browser/page_text_observer_unittest.cc +++ b/components/optimization_guide/content/browser/page_text_observer_unittest.cc
@@ -9,6 +9,8 @@ #include "base/bind.h" #include "base/callback.h" #include "base/optional.h" +#include "base/stl_util.h" +#include "base/strings/strcat.h" #include "base/strings/utf_string_conversions.h" #include "components/optimization_guide/content/mojom/page_text_service.mojom.h" #include "content/public/browser/navigation_handle.h" @@ -27,6 +29,14 @@ namespace { +FrameTextDumpResult MakeFrameDump(mojom::TextDumpEvent event, + content::GlobalFrameRoutingId rfh_id, + bool amp_frame, + const std::u16string& contents) { + return FrameTextDumpResult::Initialize(event, rfh_id, amp_frame) + .CompleteWithContents(contents); +} + class TestConsumer : public PageTextObserver::Consumer { public: TestConsumer() = default; @@ -35,16 +45,18 @@ void Reset() { was_called_ = false; } void PopulateRequest(uint32_t max_size, - const std::set<mojom::TextDumpEvent>& events) { + const std::set<mojom::TextDumpEvent>& events, + bool request_amp = false) { request_ = std::make_unique<PageTextObserver::ConsumerTextDumpRequest>(); request_->max_size = max_size; request_->events = events; - request_->callback = base::BindRepeating(&TestConsumer::OnGotTextDump, - base::Unretained(this)); + request_->callback = + base::BindOnce(&TestConsumer::OnGotTextDump, base::Unretained(this)); + request_->dump_amp_subframes = request_amp; } void WaitForPageText() { - if (text_) { + if (result_) { return; } @@ -55,7 +67,9 @@ bool was_called() const { return was_called_; } - const base::Optional<std::u16string>& text() const { return text_; } + base::Optional<PageTextDumpResult> result() { + return base::OptionalFromPtr(result_.get()); + } // PageTextObserver::Consumer: std::unique_ptr<PageTextObserver::ConsumerTextDumpRequest> @@ -65,20 +79,18 @@ } private: - void OnGotTextDump(const std::u16string& text) { - text_ = text; + void OnGotTextDump(const PageTextDumpResult& result) { + result_ = std::make_unique<PageTextDumpResult>(result); if (on_page_text_closure_) { std::move(on_page_text_closure_).Run(); } } bool was_called_ = false; - std::unique_ptr<PageTextObserver::ConsumerTextDumpRequest> request_; base::OnceClosure on_page_text_closure_; - - base::Optional<std::u16string> text_; + std::unique_ptr<PageTextDumpResult> result_; }; class FakePageTextService : public mojom::PageTextService { @@ -138,6 +150,36 @@ responses_; }; +class TestPageTextObserver : public PageTextObserver { + public: + explicit TestPageTextObserver(content::WebContents* web_contents) + : PageTextObserver(web_contents) {} + ~TestPageTextObserver() override = default; + + void SetIsOOPIF(content::RenderFrameHost* rfh, bool is_oopif) { + oopif_overrides_.erase(rfh); + oopif_overrides_.emplace(rfh, is_oopif); + } + + bool IsOOPIF(content::RenderFrameHost* rfh) const override { + auto iter = oopif_overrides_.find(rfh); + if (iter != oopif_overrides_.end()) { + return iter->second; + } + return false; + } + + void DidFinishLoad(content::RenderFrameHost* render_frame_host, + const GURL& validated_url) override { + // Intentionally do nothing so that subframes can be added in tests. + } + + void CallDidFinishLoad() { PageTextObserver::DidFinishLoad(nullptr, GURL()); } + + private: + std::map<content::RenderFrameHost*, bool> oopif_overrides_; +}; + } // namespace class PageTextObserverTest : public content::RenderViewHostTestHarness { @@ -148,13 +190,14 @@ // content::RenderViewHostTestHarness: void SetUp() override { content::RenderViewHostTestHarness::SetUp(); - PageTextObserver::CreateForWebContents(web_contents()); + observer_ = std::make_unique<TestPageTextObserver>(web_contents()); ASSERT_TRUE(observer()); } - PageTextObserver* observer() { - return PageTextObserver::FromWebContents(web_contents()); - } + TestPageTextObserver* observer() const { return observer_.get(); } + + private: + std::unique_ptr<TestPageTextObserver> observer_; }; TEST_F(PageTextObserverTest, ConsumerCalled) { @@ -181,6 +224,7 @@ content::NavigationSimulator::CreateRendererInitiated( GURL("http://test.com/#fragment"), main_rfh()) ->CommitSameDocument(); + observer()->CallDidFinishLoad(); EXPECT_TRUE(consumer.was_called()); } @@ -242,11 +286,18 @@ content::NavigationSimulator::NavigateAndCommitFromBrowser( web_contents(), GURL("http://test.com")); - EXPECT_TRUE(consumer.was_called()); + observer()->CallDidFinishLoad(); consumer.WaitForPageText(); - EXPECT_EQ(base::ASCIIToUTF16("abc"), *consumer.text()); + + ASSERT_TRUE(consumer.result()); + EXPECT_THAT(consumer.result()->frame_results(), + ::testing::UnorderedElementsAreArray({ + MakeFrameDump(mojom::TextDumpEvent::kFirstLayout, + main_rfh()->GetGlobalFrameRoutingId(), + /*amp_frame=*/false, base::ASCIIToUTF16("abc")), + })); EXPECT_THAT( fake_renderer_service.requests(), @@ -279,11 +330,18 @@ content::NavigationSimulator::NavigateAndCommitFromBrowser( web_contents(), GURL("http://test.com")); - EXPECT_TRUE(consumer.was_called()); + observer()->CallDidFinishLoad(); consumer.WaitForPageText(); - EXPECT_EQ(base::ASCIIToUTF16("abc"), *consumer.text()); + + ASSERT_TRUE(consumer.result()); + EXPECT_THAT(consumer.result()->frame_results(), + ::testing::UnorderedElementsAreArray({ + MakeFrameDump(mojom::TextDumpEvent::kFirstLayout, + main_rfh()->GetGlobalFrameRoutingId(), + /*amp_frame=*/false, base::ASCIIToUTF16("abc")), + })); EXPECT_THAT( fake_renderer_service.requests(), @@ -316,11 +374,19 @@ content::NavigationSimulator::NavigateAndCommitFromBrowser( web_contents(), GURL("http://test.com")); - EXPECT_TRUE(consumer.was_called()); + observer()->CallDidFinishLoad(); consumer.WaitForPageText(); - EXPECT_EQ(base::ASCIIToUTF16("abcd"), *consumer.text()); + + ASSERT_TRUE(consumer.result()); + EXPECT_THAT( + consumer.result()->frame_results(), + ::testing::UnorderedElementsAreArray({ + MakeFrameDump(mojom::TextDumpEvent::kFirstLayout, + main_rfh()->GetGlobalFrameRoutingId(), + /*amp_frame=*/false, base::ASCIIToUTF16("abcd")), + })); EXPECT_THAT( fake_renderer_service.requests(), @@ -352,11 +418,19 @@ content::NavigationSimulator::NavigateAndCommitFromBrowser( web_contents(), GURL("http://test.com")); - EXPECT_TRUE(consumer.was_called()); + observer()->CallDidFinishLoad(); consumer.WaitForPageText(); - EXPECT_EQ(base::ASCIIToUTF16("abcd"), *consumer.text()); + + ASSERT_TRUE(consumer.result()); + EXPECT_THAT( + consumer.result()->frame_results(), + ::testing::UnorderedElementsAreArray({ + MakeFrameDump(mojom::TextDumpEvent::kFirstLayout, + main_rfh()->GetGlobalFrameRoutingId(), + /*amp_frame=*/false, base::ASCIIToUTF16("abcd")), + })); EXPECT_THAT( fake_renderer_service.requests(), @@ -394,14 +468,27 @@ content::NavigationSimulator::NavigateAndCommitFromBrowser( web_contents(), GURL("http://test.com")); - EXPECT_TRUE(consumer1.was_called()); EXPECT_TRUE(consumer2.was_called()); + observer()->CallDidFinishLoad(); consumer1.WaitForPageText(); consumer2.WaitForPageText(); - EXPECT_EQ(base::ASCIIToUTF16("abc"), *consumer1.text()); - EXPECT_EQ(base::ASCIIToUTF16("abc"), *consumer2.text()); + + ASSERT_TRUE(consumer1.result()); + EXPECT_THAT(consumer1.result()->frame_results(), + ::testing::UnorderedElementsAreArray({ + MakeFrameDump(mojom::TextDumpEvent::kFirstLayout, + main_rfh()->GetGlobalFrameRoutingId(), + /*amp_frame=*/false, base::ASCIIToUTF16("abc")), + })); + ASSERT_TRUE(consumer2.result()); + EXPECT_THAT(consumer2.result()->frame_results(), + ::testing::UnorderedElementsAreArray({ + MakeFrameDump(mojom::TextDumpEvent::kFirstLayout, + main_rfh()->GetGlobalFrameRoutingId(), + /*amp_frame=*/false, base::ASCIIToUTF16("abc")), + })); EXPECT_THAT( fake_renderer_service.requests(), @@ -440,12 +527,20 @@ content::NavigationSimulator::NavigateAndCommitFromBrowser( web_contents(), GURL("http://test.com")); - EXPECT_TRUE(consumer1.was_called()); EXPECT_FALSE(consumer2.was_called()); + observer()->CallDidFinishLoad(); consumer1.WaitForPageText(); - EXPECT_EQ(base::ASCIIToUTF16("abc"), *consumer1.text()); + + ASSERT_TRUE(consumer1.result()); + EXPECT_THAT(consumer1.result()->frame_results(), + ::testing::UnorderedElementsAreArray({ + MakeFrameDump(mojom::TextDumpEvent::kFirstLayout, + main_rfh()->GetGlobalFrameRoutingId(), + /*amp_frame=*/false, base::ASCIIToUTF16("abc")), + })); + EXPECT_FALSE(consumer2.result()); EXPECT_THAT( fake_renderer_service.requests(), @@ -486,14 +581,24 @@ content::NavigationSimulator::NavigateAndCommitFromBrowser( web_contents(), GURL("http://test.com")); - EXPECT_TRUE(consumer1.was_called()); EXPECT_TRUE(consumer2.was_called()); + observer()->CallDidFinishLoad(); consumer1.WaitForPageText(); consumer2.WaitForPageText(); - EXPECT_EQ(base::ASCIIToUTF16("abc"), *consumer1.text()); - EXPECT_EQ(base::ASCIIToUTF16("xyz"), *consumer2.text()); + + ASSERT_TRUE(consumer1.result()); + EXPECT_THAT(consumer1.result()->frame_results(), + ::testing::UnorderedElementsAreArray({ + MakeFrameDump(mojom::TextDumpEvent::kFirstLayout, + main_rfh()->GetGlobalFrameRoutingId(), + /*amp_frame=*/false, base::ASCIIToUTF16("abc")), + MakeFrameDump(mojom::TextDumpEvent::kFinishedLoad, + main_rfh()->GetGlobalFrameRoutingId(), + /*amp_frame=*/false, base::ASCIIToUTF16("xyz")), + })); + EXPECT_EQ(consumer1.result(), consumer2.result()); EXPECT_THAT( fake_renderer_service.requests(), @@ -503,4 +608,214 @@ })); } +TEST_F(PageTextObserverTest, AMPRequestedOnOOPIF) { + TestConsumer consumer; + observer()->AddConsumer(&consumer); + + consumer.PopulateRequest( + /*max_size=*/1024, + /*events=*/{mojom::TextDumpEvent::kFirstLayout}, + /*request_amp=*/true); + + FakePageTextService fake_renderer_service; + fake_renderer_service.SetRemoteResponsesForEvent( + mojom::TextDumpEvent::kFirstLayout, { + base::ASCIIToUTF16("abc"), + base::ASCIIToUTF16("def"), + base::nullopt, + }); + + blink::AssociatedInterfaceProvider* remote_interfaces = + main_rfh()->GetRemoteAssociatedInterfaces(); + remote_interfaces->OverrideBinderForTesting( + mojom::PageTextService::Name_, + base::BindRepeating(&FakePageTextService::BindPendingReceiver, + base::Unretained(&fake_renderer_service))); + + content::NavigationSimulator::NavigateAndCommitFromBrowser( + web_contents(), GURL("http://test.com")); + EXPECT_TRUE(consumer.was_called()); + + // Add an OOPIF subframe. + content::RenderFrameHost* oopif_subframe = + content::RenderFrameHostTester::For(main_rfh())->AppendChild("subframe"); + observer()->SetIsOOPIF(oopif_subframe, true); + + FakePageTextService subframe_fake_renderer_service; + blink::AssociatedInterfaceProvider* subframe_remote_interfaces = + oopif_subframe->GetRemoteAssociatedInterfaces(); + subframe_remote_interfaces->OverrideBinderForTesting( + mojom::PageTextService::Name_, + base::BindRepeating(&FakePageTextService::BindPendingReceiver, + base::Unretained(&subframe_fake_renderer_service))); + subframe_fake_renderer_service.SetRemoteResponsesForEvent( + mojom::TextDumpEvent::kFinishedLoad, { + base::ASCIIToUTF16("amp"), + base::nullopt, + }); + + observer()->RenderFrameCreated(oopif_subframe); + observer()->CallDidFinishLoad(); + consumer.WaitForPageText(); + + EXPECT_THAT( + fake_renderer_service.requests(), + ::testing::UnorderedElementsAreArray({ + mojom::PageTextDumpRequest(1024U, mojom::TextDumpEvent::kFirstLayout), + })); + EXPECT_THAT(subframe_fake_renderer_service.requests(), + ::testing::UnorderedElementsAreArray({ + mojom::PageTextDumpRequest( + 1024U, mojom::TextDumpEvent::kFinishedLoad), + })); + + ASSERT_TRUE(consumer.result()); + EXPECT_THAT( + consumer.result()->frame_results(), + ::testing::UnorderedElementsAreArray({ + MakeFrameDump(mojom::TextDumpEvent::kFinishedLoad, + oopif_subframe->GetGlobalFrameRoutingId(), + /*amp_frame=*/true, base::ASCIIToUTF16("amp")), + MakeFrameDump(mojom::TextDumpEvent::kFirstLayout, + main_rfh()->GetGlobalFrameRoutingId(), + /*amp_frame=*/false, base::ASCIIToUTF16("abcdef")), + })); +} + +TEST_F(PageTextObserverTest, AMPNotRequestedOnOOPIF) { + TestConsumer consumer; + observer()->AddConsumer(&consumer); + + consumer.PopulateRequest( + /*max_size=*/1024, + /*events=*/{mojom::TextDumpEvent::kFirstLayout}, + /*request_amp=*/false); + + FakePageTextService fake_renderer_service; + fake_renderer_service.SetRemoteResponsesForEvent( + mojom::TextDumpEvent::kFirstLayout, { + base::ASCIIToUTF16("abc"), + base::ASCIIToUTF16("def"), + base::nullopt, + }); + + blink::AssociatedInterfaceProvider* remote_interfaces = + main_rfh()->GetRemoteAssociatedInterfaces(); + remote_interfaces->OverrideBinderForTesting( + mojom::PageTextService::Name_, + base::BindRepeating(&FakePageTextService::BindPendingReceiver, + base::Unretained(&fake_renderer_service))); + + content::NavigationSimulator::NavigateAndCommitFromBrowser( + web_contents(), GURL("http://test.com")); + EXPECT_TRUE(consumer.was_called()); + + // Add an OOPIF subframe. + content::RenderFrameHost* oopif_subframe = + content::RenderFrameHostTester::For(main_rfh())->AppendChild("subframe"); + observer()->SetIsOOPIF(oopif_subframe, true); + + FakePageTextService subframe_fake_renderer_service; + blink::AssociatedInterfaceProvider* subframe_remote_interfaces = + oopif_subframe->GetRemoteAssociatedInterfaces(); + subframe_remote_interfaces->OverrideBinderForTesting( + mojom::PageTextService::Name_, + base::BindRepeating(&FakePageTextService::BindPendingReceiver, + base::Unretained(&subframe_fake_renderer_service))); + subframe_fake_renderer_service.SetRemoteResponsesForEvent( + mojom::TextDumpEvent::kFinishedLoad, { + base::ASCIIToUTF16("\n"), + base::ASCIIToUTF16("amp"), + base::nullopt, + }); + + observer()->RenderFrameCreated(oopif_subframe); + observer()->CallDidFinishLoad(); + base::RunLoop().RunUntilIdle(); + + EXPECT_THAT( + fake_renderer_service.requests(), + ::testing::UnorderedElementsAreArray({ + mojom::PageTextDumpRequest(1024U, mojom::TextDumpEvent::kFirstLayout), + })); + EXPECT_TRUE(subframe_fake_renderer_service.requests().empty()); + + ASSERT_TRUE(consumer.result()); + EXPECT_THAT( + consumer.result()->frame_results(), + ::testing::UnorderedElementsAreArray({ + MakeFrameDump(mojom::TextDumpEvent::kFirstLayout, + main_rfh()->GetGlobalFrameRoutingId(), + /*amp_frame=*/false, base::ASCIIToUTF16("abcdef")), + })); +} + +TEST_F(PageTextObserverTest, AMPRequestedOnNonOOPIF) { + TestConsumer consumer; + observer()->AddConsumer(&consumer); + + consumer.PopulateRequest( + /*max_size=*/1024, + /*events=*/{mojom::TextDumpEvent::kFirstLayout}, + /*request_amp=*/true); + + FakePageTextService fake_renderer_service; + fake_renderer_service.SetRemoteResponsesForEvent( + mojom::TextDumpEvent::kFirstLayout, { + base::ASCIIToUTF16("abc"), + base::ASCIIToUTF16("def"), + base::nullopt, + }); + + blink::AssociatedInterfaceProvider* remote_interfaces = + main_rfh()->GetRemoteAssociatedInterfaces(); + remote_interfaces->OverrideBinderForTesting( + mojom::PageTextService::Name_, + base::BindRepeating(&FakePageTextService::BindPendingReceiver, + base::Unretained(&fake_renderer_service))); + + content::NavigationSimulator::NavigateAndCommitFromBrowser( + web_contents(), GURL("http://test.com")); + EXPECT_TRUE(consumer.was_called()); + + // Add a non-OOPIF subframe. + content::RenderFrameHost* subframe = + content::RenderFrameHostTester::For(main_rfh())->AppendChild("subframe"); + observer()->SetIsOOPIF(subframe, false); + + FakePageTextService subframe_fake_renderer_service; + blink::AssociatedInterfaceProvider* subframe_remote_interfaces = + subframe->GetRemoteAssociatedInterfaces(); + subframe_remote_interfaces->OverrideBinderForTesting( + mojom::PageTextService::Name_, + base::BindRepeating(&FakePageTextService::BindPendingReceiver, + base::Unretained(&subframe_fake_renderer_service))); + subframe_fake_renderer_service.SetRemoteResponsesForEvent( + mojom::TextDumpEvent::kFinishedLoad, { + base::ASCIIToUTF16("\n"), + base::ASCIIToUTF16("amp"), + base::nullopt, + }); + + observer()->RenderFrameCreated(subframe); + observer()->CallDidFinishLoad(); + base::RunLoop().RunUntilIdle(); + + EXPECT_THAT( + fake_renderer_service.requests(), + ::testing::UnorderedElementsAreArray({ + mojom::PageTextDumpRequest(1024U, mojom::TextDumpEvent::kFirstLayout), + })); + EXPECT_TRUE(subframe_fake_renderer_service.requests().empty()); + + ASSERT_TRUE(consumer.result()); + EXPECT_THAT( + consumer.result()->frame_results(), + ::testing::UnorderedElementsAreArray({ + MakeFrameDump(mojom::TextDumpEvent::kFirstLayout, + main_rfh()->GetGlobalFrameRoutingId(), + /*amp_frame=*/false, base::ASCIIToUTF16("abcdef")), + })); +} + } // namespace optimization_guide
diff --git a/components/optimization_guide/content/renderer/page_text_agent.cc b/components/optimization_guide/content/renderer/page_text_agent.cc index ce93532..6349c52 100644 --- a/components/optimization_guide/content/renderer/page_text_agent.cc +++ b/components/optimization_guide/content/renderer/page_text_agent.cc
@@ -7,6 +7,7 @@ #include "content/public/renderer/render_frame.h" #include "mojo/public/cpp/bindings/remote.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h" +#include "third_party/blink/public/web/web_frame_content_dumper.h" namespace optimization_guide { @@ -30,7 +31,8 @@ } // namespace PageTextAgent::PageTextAgent(content::RenderFrame* frame) - : content::RenderFrameObserverTracker<PageTextAgent>(frame) { + : content::RenderFrameObserver(frame), + content::RenderFrameObserverTracker<PageTextAgent>(frame) { if (!frame) { // For unittesting. return; @@ -49,6 +51,11 @@ PageTextAgent::MaybeRequestTextDumpOnLayoutEvent( blink::WebMeaningfulLayout event, uint32_t* max_size) { + // This code path is only supported for mainframes, when there is a frame. + if (render_frame() && !render_frame()->IsMainFrame()) { + return base::NullCallback(); + } + base::Optional<mojom::TextDumpEvent> mojo_event = LayoutEventAsMojoEvent(event); if (!mojo_event) { @@ -94,6 +101,54 @@ consumer->OnChunksEnd(); } +void PageTextAgent::DidFinishLoad() { + if (!render_frame()) { + return; + } + + // Only subframes should use this code path. + if (render_frame()->IsMainFrame()) { + return; + } + + // Only AMP subframes are supported. + if (!is_amp_page_) { + return; + } + + auto requests_iter = + requests_by_event_.find(mojom::TextDumpEvent::kFinishedLoad); + if (requests_iter == requests_by_event_.end()) { + return; + } + + mojo::PendingRemote<mojom::PageTextConsumer> pending_consumer = + std::move(requests_iter->second.second); + uint32_t max_size = requests_iter->second.first->max_size; + requests_by_event_.erase(mojom::TextDumpEvent::kFinishedLoad); + + std::u16string content = blink::WebFrameContentDumper::DumpFrameTreeAsText( + render_frame()->GetWebFrame(), max_size) + .Utf16(); + OnPageTextDump(std::move(pending_consumer), content); +} + +void PageTextAgent::DidStartNavigation( + const GURL& url, + base::Optional<blink::WebNavigationType> navigation_type) { + is_amp_page_ = false; + // Note that |requests_by_event_| should NOT be reset here. Requests and + // navigations from the browser race with each other, and the text dump + // request normally wins. We don't want to drop a request when its navigation + // is just about to start. +} + +void PageTextAgent::DidObserveLoadingBehavior( + blink::LoadingBehaviorFlag behavior) { + is_amp_page_ |= + behavior & blink::LoadingBehaviorFlag::kLoadingBehaviorAmpDocumentLoaded; +} + void PageTextAgent::RequestPageTextDump( mojom::PageTextDumpRequestPtr request, mojo::PendingRemote<mojom::PageTextConsumer> consumer) {
diff --git a/components/optimization_guide/content/renderer/page_text_agent.h b/components/optimization_guide/content/renderer/page_text_agent.h index 6b253851..b76e630 100644 --- a/components/optimization_guide/content/renderer/page_text_agent.h +++ b/components/optimization_guide/content/renderer/page_text_agent.h
@@ -14,6 +14,7 @@ #include "base/memory/weak_ptr.h" #include "base/optional.h" #include "components/optimization_guide/content/mojom/page_text_service.mojom.h" +#include "content/public/renderer/render_frame_observer.h" #include "content/public/renderer/render_frame_observer_tracker.h" #include "mojo/public/cpp/bindings/associated_receiver_set.h" #include "mojo/public/cpp/bindings/pending_remote.h" @@ -27,10 +28,11 @@ // PageTextAgent is the interface between ChromeRenderFrameObserver and // mojom::PageTextService. It currently supports requesting and getting text -// dumps during |content::RenderFrameObserver::DidMeaningfulLayout|, but more -// events will be added in the future. +// dumps during |content::RenderFrameObserver::DidMeaningfulLayout|, and +// |DidFinishLoad| for subframes. class PageTextAgent : public mojom::PageTextService, + public content::RenderFrameObserver, public content::RenderFrameObserverTracker<PageTextAgent> { public: explicit PageTextAgent(content::RenderFrame* frame); @@ -52,6 +54,14 @@ mojom::PageTextDumpRequestPtr request, mojo::PendingRemote<mojom::PageTextConsumer> consumer) override; + // content::RenderFrameObserver: + void OnDestruct() override {} + void DidObserveLoadingBehavior(blink::LoadingBehaviorFlag behavior) override; + void DidStartNavigation( + const GURL& url, + base::Optional<blink::WebNavigationType> navigation_type) override; + void DidFinishLoad() override; + PageTextAgent(const PageTextAgent&) = delete; PageTextAgent& operator=(const PageTextAgent&) = delete; @@ -69,6 +79,9 @@ mojo::PendingRemote<mojom::PageTextConsumer>>; std::map<mojom::TextDumpEvent, RequestAndConsumer> requests_by_event_; + // Set when an AMP page is detected from loading behavior flags. + bool is_amp_page_ = false; + mojo::AssociatedReceiverSet<mojom::PageTextService> receivers_; base::WeakPtrFactory<PageTextAgent> weak_factory_{this};
diff --git a/components/optimization_guide/content/renderer/page_text_agent_browsertest.cc b/components/optimization_guide/content/renderer/page_text_agent_browsertest.cc new file mode 100644 index 0000000..dfe551f --- /dev/null +++ b/components/optimization_guide/content/renderer/page_text_agent_browsertest.cc
@@ -0,0 +1,185 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/optimization_guide/content/renderer/page_text_agent.h" + +#include <limits> +#include <string> + +#include "base/bind.h" +#include "base/callback.h" +#include "base/optional.h" +#include "base/strings/strcat.h" +#include "base/strings/utf_string_conversions.h" +#include "content/public/renderer/render_frame.h" +#include "content/public/renderer/render_view.h" +#include "content/public/test/render_view_test.h" +#include "content/public/test/test_utils.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/web/web_local_frame.h" + +namespace optimization_guide { + +namespace { + +class TestConsumer : public mojom::PageTextConsumer { + public: + TestConsumer() = default; + ~TestConsumer() override = default; + + std::u16string text() const { return base::StrCat(chunks_); } + bool on_chunks_end_called() const { return on_chunks_end_called_; } + size_t num_chunks() const { return chunks_.size(); } + + void Bind(mojo::PendingReceiver<mojom::PageTextConsumer> pending_receiver) { + receiver_.Bind(std::move(pending_receiver)); + } + + // mojom::PageTextConsumer: + void OnTextDumpChunk(const std::u16string& chunk) override { + ASSERT_FALSE(on_chunks_end_called_); + chunks_.push_back(chunk); + } + + void OnChunksEnd() override { on_chunks_end_called_ = true; } + + private: + mojo::Receiver<mojom::PageTextConsumer> receiver_{this}; + std::vector<std::u16string> chunks_; + bool on_chunks_end_called_ = false; +}; + +} // namespace + +class PageTextAgentRenderViewTest : public content::RenderViewTest { + public: + PageTextAgentRenderViewTest() = default; + ~PageTextAgentRenderViewTest() override = default; +}; + +TEST_F(PageTextAgentRenderViewTest, AMPSubframeFirstLayout) { + // Create and get a subframe. + LoadHTML( + "<html><body>" + " <p>hello</p>" + " <iframe name=sub srcdoc=\"<p>world</p>\"></iframe>" + "</body></html>"); + content::RenderFrame* subframe = content::RenderFrame::FromWebFrame( + GetMainFrame()->FindFrameByName("sub")->ToWebLocalFrame()); + + PageTextAgent subframe_agent(subframe); + + // Send the request. + mojo::PendingRemote<mojom::PageTextConsumer> consumer_remote; + TestConsumer consumer; + consumer.Bind(consumer_remote.InitWithNewPipeAndPassReceiver()); + + auto request = mojom::PageTextDumpRequest::New(); + request->max_size = 1024; + request->event = mojom::TextDumpEvent::kFirstLayout; + subframe_agent.RequestPageTextDump(std::move(request), + std::move(consumer_remote)); + + // Simulate a page load. + subframe_agent.DidObserveLoadingBehavior( + blink::LoadingBehaviorFlag::kLoadingBehaviorAmpDocumentLoaded); + subframe_agent.DidFinishLoad(); + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(consumer.on_chunks_end_called()); +} + +TEST_F(PageTextAgentRenderViewTest, NotAMPSubframeLoadFinished) { + // Create and get a subframe. + LoadHTML( + "<html><body>" + " <p>hello</p>" + " <iframe name=sub srcdoc=\"<p>world</p>\"></iframe>" + "</body></html>"); + content::RenderFrame* subframe = content::RenderFrame::FromWebFrame( + GetMainFrame()->FindFrameByName("sub")->ToWebLocalFrame()); + + PageTextAgent subframe_agent(subframe); + + // Send the request. + mojo::PendingRemote<mojom::PageTextConsumer> consumer_remote; + TestConsumer consumer; + consumer.Bind(consumer_remote.InitWithNewPipeAndPassReceiver()); + + auto request = mojom::PageTextDumpRequest::New(); + request->max_size = 1024; + request->event = mojom::TextDumpEvent::kFinishedLoad; + subframe_agent.RequestPageTextDump(std::move(request), + std::move(consumer_remote)); + + // Simulate a page load. + subframe_agent.DidObserveLoadingBehavior( + blink::LoadingBehaviorFlag::kLoadingBehaviorNone); + subframe_agent.DidFinishLoad(); + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(consumer.on_chunks_end_called()); +} + +TEST_F(PageTextAgentRenderViewTest, MainFrame) { + // Create and get a subframe. + LoadHTML( + "<html><body>" + " <p>hello</p>" + "</body></html>"); + content::RenderFrame* mainframe = + content::RenderFrame::FromWebFrame(GetMainFrame()); + + PageTextAgent subframe_agent(mainframe); + + // Send the request. + mojo::PendingRemote<mojom::PageTextConsumer> consumer_remote; + TestConsumer consumer; + consumer.Bind(consumer_remote.InitWithNewPipeAndPassReceiver()); + + auto request = mojom::PageTextDumpRequest::New(); + request->max_size = 1024; + request->event = mojom::TextDumpEvent::kFinishedLoad; + subframe_agent.RequestPageTextDump(std::move(request), + std::move(consumer_remote)); + + // Simulate a page load. + subframe_agent.DidObserveLoadingBehavior( + blink::LoadingBehaviorFlag::kLoadingBehaviorAmpDocumentLoaded); + subframe_agent.DidFinishLoad(); + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(consumer.on_chunks_end_called()); +} + +TEST_F(PageTextAgentRenderViewTest, AMPSuccessCase) { + // Create and get a subframe. + LoadHTML( + "<html><body>" + " <p>hello</p>" + " <iframe name=sub srcdoc=\"<p>world</p>\"></iframe>" + "</body></html>"); + content::RenderFrame* subframe = content::RenderFrame::FromWebFrame( + GetMainFrame()->FindFrameByName("sub")->ToWebLocalFrame()); + + PageTextAgent subframe_agent(subframe); + + // Send the request. + mojo::PendingRemote<mojom::PageTextConsumer> consumer_remote; + TestConsumer consumer; + consumer.Bind(consumer_remote.InitWithNewPipeAndPassReceiver()); + + auto request = mojom::PageTextDumpRequest::New(); + request->max_size = 1024; + request->event = mojom::TextDumpEvent::kFinishedLoad; + subframe_agent.RequestPageTextDump(std::move(request), + std::move(consumer_remote)); + + // Simulate a page load. + subframe_agent.DidObserveLoadingBehavior( + blink::LoadingBehaviorFlag::kLoadingBehaviorAmpDocumentLoaded); + subframe_agent.DidFinishLoad(); + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(consumer.on_chunks_end_called()); + EXPECT_EQ(base::ASCIIToUTF16("world"), consumer.text()); +} + +} // namespace optimization_guide
diff --git a/components/optimization_guide/core/BUILD.gn b/components/optimization_guide/core/BUILD.gn index 58262f7..9f6ad51 100644 --- a/components/optimization_guide/core/BUILD.gn +++ b/components/optimization_guide/core/BUILD.gn
@@ -61,6 +61,7 @@ "prediction_model_file.h", "store_update_data.cc", "store_update_data.h", + "tab_url_provider.h", "top_host_provider.h", "url_pattern_with_wildcards.cc", "url_pattern_with_wildcards.h",
diff --git a/components/optimization_guide/core/hints_fetcher.cc b/components/optimization_guide/core/hints_fetcher.cc index 09cbfcc6..661cbd61 100644 --- a/components/optimization_guide/core/hints_fetcher.cc +++ b/components/optimization_guide/core/hints_fetcher.cc
@@ -437,7 +437,7 @@ base::Time host_valid_time = base::Time::FromDeltaSinceWindowsEpoch( base::TimeDelta::FromSecondsD(*value)); host_hints_due_for_refresh = - (host_valid_time - features::GetHintsFetchRefreshDuration() <= + (host_valid_time - features::GetHostHintsFetchRefreshDuration() <= time_clock_->Now()); } if (host_hints_due_for_refresh)
diff --git a/components/optimization_guide/core/hints_fetcher_unittest.cc b/components/optimization_guide/core/hints_fetcher_unittest.cc index bf009ad64..1c75ee18 100644 --- a/components/optimization_guide/core/hints_fetcher_unittest.cc +++ b/components/optimization_guide/core/hints_fetcher_unittest.cc
@@ -275,7 +275,7 @@ // Advancing the clock so that it's still one hour before the hints need to be // refreshed. test_clock.Advance(features::StoredFetchedHintsFreshnessDuration() - - features::GetHintsFetchRefreshDuration() - + features::GetHostHintsFetchRefreshDuration() - base::TimeDelta().FromHours(1)); EXPECT_FALSE(FetchHints({"foo.com"}, {} /* urls */));
diff --git a/components/optimization_guide/core/optimization_guide_features.cc b/components/optimization_guide/core/optimization_guide_features.cc index bdf801a8..6e52d0a 100644 --- a/components/optimization_guide/core/optimization_guide_features.cc +++ b/components/optimization_guide/core/optimization_guide_features.cc
@@ -62,7 +62,7 @@ "OptimizationTargetPrediction", base::FEATURE_ENABLED_BY_DEFAULT}; // Enables the downloading of models. -const base::Feature kOptimizationGuideModelDownloading{ +const base::Feature kOptimizationGuideModelDownloading { "OptimizationGuideModelDownloading", #if BUILDFLAG(BUILD_WITH_TFLITE_LIB) base::FEATURE_ENABLED_BY_DEFAULT @@ -75,6 +75,18 @@ const base::Feature kPageContentAnnotations{"PageContentAnnotations", base::FEATURE_DISABLED_BY_DEFAULT}; +// This feature flag does not turn off any behavior, it is only used for +// experiment parameters. +const base::Feature kPageTextExtraction{ + "OptimizationGuidePageContentExtraction", base::FEATURE_ENABLED_BY_DEFAULT}; + +// The default value here is a bit of a guess. +// TODO(crbug/1163244): This should be tuned once metrics are available. +base::TimeDelta PageTextExtractionOutstandingRequestsGracePeriod() { + return base::TimeDelta::FromMilliseconds(GetFieldTrialParamByFeatureAsInt( + kPageTextExtraction, "outstanding_requests_grace_period_ms", 1000)); +} + size_t MaxHintsFetcherTopHostBlocklistSize() { // The blocklist will be limited to the most engaged hosts and will hold twice // (2*N) as many hosts that the HintsFetcher request hints for. The extra N @@ -87,15 +99,6 @@ MaxHostsForOptimizationGuideServiceHintsFetch(); } -bool ShouldBatchUpdateHintsForTopHosts() { - if (base::FeatureList::IsEnabled(kRemoteOptimizationGuideFetching)) { - return GetFieldTrialParamByFeatureAsBool(kRemoteOptimizationGuideFetching, - "batch_update_hints_for_top_hosts", - true); - } - return false; -} - size_t MaxHostsForOptimizationGuideServiceHintsFetch() { return GetFieldTrialParamByFeatureAsInt( kRemoteOptimizationGuideFetching, @@ -219,12 +222,25 @@ return net::GetEffectiveConnectionTypeForName(param_value); } -base::TimeDelta GetHintsFetchRefreshDuration() { +base::TimeDelta GetHostHintsFetchRefreshDuration() { return base::TimeDelta::FromHours(GetFieldTrialParamByFeatureAsInt( kRemoteOptimizationGuideFetching, "hints_fetch_refresh_duration_in_hours", 72)); } +base::TimeDelta GetActiveTabsFetchRefreshDuration() { + return base::TimeDelta::FromHours(GetFieldTrialParamByFeatureAsInt( + kRemoteOptimizationGuideFetching, + "active_tabs_fetch_refresh_duration_in_hours", 1)); +} + +base::TimeDelta GetActiveTabsStalenessTolerance() { + // 90 days initially chosen since that's how long local history lasts for. + return base::TimeDelta::FromDays(GetFieldTrialParamByFeatureAsInt( + kRemoteOptimizationGuideFetching, + "active_tabs_staleness_tolerance_in_days", 90)); +} + size_t MaxConcurrentPageNavigationFetches() { // If overridden, this needs to be large enough where we do not thrash the // inflight page navigations since if we approach the limit here, we will
diff --git a/components/optimization_guide/core/optimization_guide_features.h b/components/optimization_guide/core/optimization_guide_features.h index 52aba79f..195202c 100644 --- a/components/optimization_guide/core/optimization_guide_features.h +++ b/components/optimization_guide/core/optimization_guide_features.h
@@ -27,6 +27,11 @@ extern const base::Feature kOptimizationTargetPrediction; extern const base::Feature kOptimizationGuideModelDownloading; extern const base::Feature kPageContentAnnotations; +extern const base::Feature kPageTextExtraction; + +// The grace period duration for how long to give outstanding page text dump +// requests to respond after DidFinishLoad. +base::TimeDelta PageTextExtractionOutstandingRequestsGracePeriod(); // The maximum number of hosts that can be stored in the // |kHintsFetcherTopHostBlocklist| dictionary pref when initialized. The top @@ -35,9 +40,6 @@ // requested until the user navigates to the host again. size_t MaxHintsFetcherTopHostBlocklistSize(); -// Whether hints for top hosts should be batch updated. -bool ShouldBatchUpdateHintsForTopHosts(); - // The maximum number of hosts allowed to be requested by the client to the // remote Optimzation Guide Service. size_t MaxHostsForOptimizationGuideServiceHintsFetch(); @@ -103,8 +105,16 @@ // Returns the duration of the time window before hints expiration during which // the hosts should be refreshed. Example: If the hints for a host expire at // time T, then they are eligible for refresh at T - -// GetHintsFetchRefreshDuration(). -base::TimeDelta GetHintsFetchRefreshDuration(); +// GetHostHintsFetchRefreshDuration(). +base::TimeDelta GetHostHintsFetchRefreshDuration(); + +// Returns the duration of the time window between fetches for hints for the +// URLs opened in active tabs. +base::TimeDelta GetActiveTabsFetchRefreshDuration(); + +// Returns the max duration since the time a tab has to be shown to be +// considered active for a hints refresh. +base::TimeDelta GetActiveTabsStalenessTolerance(); // Returns the max number of concurrent fetches to the remote Optimization Guide // Service that should be allowed.
diff --git a/components/optimization_guide/core/tab_url_provider.h b/components/optimization_guide/core/tab_url_provider.h new file mode 100644 index 0000000..992ae75 --- /dev/null +++ b/components/optimization_guide/core/tab_url_provider.h
@@ -0,0 +1,33 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_OPTIMIZATION_GUIDE_CORE_TAB_URL_PROVIDER_H_ +#define COMPONENTS_OPTIMIZATION_GUIDE_CORE_TAB_URL_PROVIDER_H_ + +#include <vector> + +#include "base/time/time.h" +#include "url/gurl.h" + +namespace optimization_guide { + +// A class to handle querying for the tab URLs for a user. +class TabUrlProvider { + public: + virtual ~TabUrlProvider() = default; + + // Returns URLS of tabs that are considered active for the user, as + // represented by |profile|. Tabs are considered active if they were last + // shown within |duration_since_last_shown|. The returned vector will be + // sorted by descending time since last shown. + virtual const std::vector<GURL> GetUrlsOfActiveTabs( + const base::TimeDelta& duration_since_last_shown) = 0; + + protected: + TabUrlProvider() = default; +}; + +} // namespace optimization_guide + +#endif // COMPONENTS_OPTIMIZATION_GUIDE_CORE_TAB_URL_PROVIDER_H_
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index aef01528..14c1263 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json
@@ -24024,7 +24024,7 @@ If the policy is enabled and set to one or more domains, no lookalike warnings pages will be shown when the user visits pages on that domain. - If the policy is disabled, not set, or set to an empty list, warnings may appear on any site the user visits. + If the policy is not set, or set to an empty list, warnings may appear on any site the user visits. A hostname can be allowed with a complete host match, or any domain match. For example, a URL like "https://foo.example.com/bar" may have warnings suppressed if this list includes either "foo.example.com" or "example.com".'''
diff --git a/components/renderer_context_menu/render_view_context_menu_base.cc b/components/renderer_context_menu/render_view_context_menu_base.cc index 50c634c..f269127 100644 --- a/components/renderer_context_menu/render_view_context_menu_base.cc +++ b/components/renderer_context_menu/render_view_context_menu_base.cc
@@ -301,6 +301,22 @@ toolkit_delegate_->RebuildMenu(); } +void RenderViewContextMenuBase::RemoveSeparatorBeforeMenuItem(int command_id) { + int index = menu_model_.GetIndexOfCommandId(command_id); + // Ignore if command not found (index == -1) or if it's the first menu item. + if (index <= 0) + return; + + ui::MenuModel::ItemType prev_type = menu_model_.GetTypeAt(index - 1); + if (prev_type != ui::MenuModel::ItemType::TYPE_SEPARATOR) + return; + + menu_model_.RemoveItemAt(index - 1); + + if (toolkit_delegate_) + toolkit_delegate_->RebuildMenu(); +} + RenderViewHost* RenderViewContextMenuBase::GetRenderViewHost() const { return source_web_contents_->GetMainFrame()->GetRenderViewHost(); }
diff --git a/components/renderer_context_menu/render_view_context_menu_base.h b/components/renderer_context_menu/render_view_context_menu_base.h index cfe99b0b..52002b1 100644 --- a/components/renderer_context_menu/render_view_context_menu_base.h +++ b/components/renderer_context_menu/render_view_context_menu_base.h
@@ -114,6 +114,7 @@ void UpdateMenuIcon(int command_id, const ui::ImageModel& icon) override; void RemoveMenuItem(int command_id) override; void RemoveAdjacentSeparators() override; + void RemoveSeparatorBeforeMenuItem(int command_id) override; content::RenderViewHost* GetRenderViewHost() const override; content::WebContents* GetWebContents() const override; content::BrowserContext* GetBrowserContext() const override;
diff --git a/components/renderer_context_menu/render_view_context_menu_proxy.h b/components/renderer_context_menu/render_view_context_menu_proxy.h index a5575ef..21045c9 100644 --- a/components/renderer_context_menu/render_view_context_menu_proxy.h +++ b/components/renderer_context_menu/render_view_context_menu_proxy.h
@@ -108,6 +108,9 @@ // Removes separators so that any adjacent duplicates are reduced to only 1. virtual void RemoveAdjacentSeparators() = 0; + // Removes separator (if any) before the specified context menu item. + virtual void RemoveSeparatorBeforeMenuItem(int command_id) = 0; + // Add spell check service item to the context menu. virtual void AddSpellCheckServiceItem(bool is_checked) = 0;
diff --git a/components/resources/BUILD.gn b/components/resources/BUILD.gn index a36546c..fb82ba643 100644 --- a/components/resources/BUILD.gn +++ b/components/resources/BUILD.gn
@@ -103,6 +103,11 @@ "credits", rebase_path(about_credits_file, root_build_dir), ] + + # Defined by downstream projects. + if (defined(extra_third_party_notice_dirs)) { + args += [ "--extra-third-party-dirs=$extra_third_party_notice_dirs" ] + } } if (is_android) {
diff --git a/components/spellcheck/browser/spell_check_host_impl.cc b/components/spellcheck/browser/spell_check_host_impl.cc index d5e6a5cc..581a48a 100644 --- a/components/spellcheck/browser/spell_check_host_impl.cc +++ b/components/spellcheck/browser/spell_check_host_impl.cc
@@ -69,15 +69,6 @@ } #if defined(OS_WIN) -void SpellCheckHostImpl::GetPerLanguageSuggestions( - const std::u16string& word, - GetPerLanguageSuggestionsCallback callback) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - // This API requires Chrome-only features. - std::move(callback).Run(std::vector<std::vector<std::u16string>>()); -} - void SpellCheckHostImpl::InitializeDictionaries( InitializeDictionariesCallback callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
diff --git a/components/spellcheck/browser/spell_check_host_impl.h b/components/spellcheck/browser/spell_check_host_impl.h index cc75b45..2d128920 100644 --- a/components/spellcheck/browser/spell_check_host_impl.h +++ b/components/spellcheck/browser/spell_check_host_impl.h
@@ -52,10 +52,6 @@ FillSuggestionListCallback callback) override; #if defined(OS_WIN) - void GetPerLanguageSuggestions( - const std::u16string& word, - GetPerLanguageSuggestionsCallback callback) override; - void InitializeDictionaries(InitializeDictionariesCallback callback) override; #endif // defined(OS_WIN) #endif // BUILDFLAG(USE_BROWSER_SPELLCHECKER) &&
diff --git a/components/spellcheck/browser/windows_spell_checker.cc b/components/spellcheck/browser/windows_spell_checker.cc index 1594934..4843319 100644 --- a/components/spellcheck/browser/windows_spell_checker.cc +++ b/components/spellcheck/browser/windows_spell_checker.cc
@@ -241,8 +241,18 @@ (action == CORRECTIVE_ACTION_GET_SUGGESTIONS || action == CORRECTIVE_ACTION_REPLACE)) { std::vector<std::u16string> suggestions; - FillSuggestionList(it->first, text.substr(start_index, error_length), - &suggestions); + if (!base::FeatureList::IsEnabled( + spellcheck::kWinRetrieveSuggestionsOnlyOnDemand)) { + // Perform the expensive operation of retrieving suggestions for all + // misspelled words while performing a text check. If + // kWinRetrieveSuggestionsOnlyOnDemand is set, suggestions will + // be retrieved on demand when the context menu is brought up with a + // misspelled word selected, and the spellcheck results returned by + // this method will have empty suggestion lists. + FillSuggestionList(it->first, + text.substr(start_index, error_length), + &suggestions); + } result_map[std::tuple<ULONG, ULONG>(start_index, error_length)] .push_back(suggestions);
diff --git a/components/spellcheck/browser/windows_spell_checker_unittest.cc b/components/spellcheck/browser/windows_spell_checker_unittest.cc index f3ef72ad..d80259b 100644 --- a/components/spellcheck/browser/windows_spell_checker_unittest.cc +++ b/components/spellcheck/browser/windows_spell_checker_unittest.cc
@@ -5,6 +5,7 @@ #include "components/spellcheck/browser/spellcheck_platform.h" #include <stddef.h> +#include <ostream> #include "base/bind.h" #include "base/containers/contains.h" @@ -28,11 +29,21 @@ namespace { +struct RequestTextCheckTestCase { + const char* text_to_check; + const char* expected_suggestion; +}; + +std::ostream& operator<<(std::ostream& out, + const RequestTextCheckTestCase& test_case) { + out << "text_to_check=" << test_case.text_to_check + << ", expected_suggestion=" << test_case.expected_suggestion; + return out; +} + class WindowsSpellCheckerTest : public testing::Test { public: WindowsSpellCheckerTest() { - feature_list_.InitAndEnableFeature(spellcheck::kWinUseBrowserSpellChecker); - // The WindowsSpellchecker object can be created even on Windows versions // that don't support platform spellchecking. However, the spellcheck // factory won't be instantiated and the result returned in the @@ -94,6 +105,15 @@ } protected: + void SetUp() override { + feature_list_.InitWithFeatures( + /*enabled_features=*/{spellcheck::kWinUseBrowserSpellChecker, + spellcheck::kWinRetrieveSuggestionsOnlyOnDemand}, + /*disabled_features=*/{}); + } + + void RunRequestTextCheckTest(const RequestTextCheckTestCase& test_case); + std::unique_ptr<WindowsSpellChecker> win_spell_checker_; bool callback_finished_ = false; @@ -109,47 +129,38 @@ base::test::TaskEnvironment::MainThreadType::UI}; }; -TEST_F(WindowsSpellCheckerTest, RequestTextCheck) { +void WindowsSpellCheckerTest::RunRequestTextCheckTest( + const RequestTextCheckTestCase& test_case) { ASSERT_EQ(set_language_result_, spellcheck::WindowsVersionSupportsSpellchecker()); - static const struct { - const char* text_to_check; - const char* expected_suggestion; - } kTestCases[] = { - {"absense", "absence"}, {"becomeing", "becoming"}, - {"cieling", "ceiling"}, {"definate", "definite"}, - {"eigth", "eight"}, {"exellent", "excellent"}, - {"finaly", "finally"}, {"garantee", "guarantee"}, - {"humerous", "humorous"}, {"imediately", "immediately"}, - {"jellous", "jealous"}, {"knowlege", "knowledge"}, - {"lenght", "length"}, {"manuever", "maneuver"}, - {"naturaly", "naturally"}, {"ommision", "omission"}, - }; + const std::u16string word(base::ASCIIToUTF16(test_case.text_to_check)); - for (size_t i = 0; i < base::size(kTestCases); ++i) { - const auto& test_case = kTestCases[i]; - const std::u16string word(base::ASCIIToUTF16(test_case.text_to_check)); + // Check if the suggested words occur. + win_spell_checker_->RequestTextCheck( + 1, word, + base::BindOnce(&WindowsSpellCheckerTest::TextCheckCompletionCallback, + base::Unretained(this))); + RunUntilResultReceived(); - // Check if the suggested words occur. - win_spell_checker_->RequestTextCheck( - 1, word, - base::BindOnce(&WindowsSpellCheckerTest::TextCheckCompletionCallback, - base::Unretained(this))); - RunUntilResultReceived(); + if (!spellcheck::WindowsVersionSupportsSpellchecker()) { + // On Windows versions that don't support platform spellchecking, the + // returned vector of results should be empty. + ASSERT_TRUE(spell_check_results_.empty()); + return; + } - if (!spellcheck::WindowsVersionSupportsSpellchecker()) { - // On Windows versions that don't support platform spellchecking, the - // returned vector of results should be empty. - ASSERT_TRUE(spell_check_results_.empty()); - continue; - } + ASSERT_EQ(1u, spell_check_results_.size()) + << "RequestTextCheck: Wrong number of results"; - ASSERT_EQ(1u, spell_check_results_.size()) - << "RequestTextCheckTests case " << i << ": Wrong number of results"; - - const std::vector<std::u16string>& suggestions = - spell_check_results_.front().replacements; + const std::vector<std::u16string>& suggestions = + spell_check_results_.front().replacements; + if (base::FeatureList::IsEnabled( + spellcheck::kWinRetrieveSuggestionsOnlyOnDemand)) { + // RequestTextCheck should return no suggestions. + ASSERT_TRUE(suggestions.empty()) + << "RequestTextCheck: No suggestions are expected"; + } else { const std::u16string suggested_word( base::ASCIIToUTF16(test_case.expected_suggestion)); auto position = @@ -158,11 +169,56 @@ return suggestion.compare(suggested_word) == 0; }); - ASSERT_NE(suggestions.end(), position) << "RequestTextCheckTests case " << i - << ": Expected suggestion not found"; + ASSERT_FALSE(position == suggestions.end()) + << "RequestTextCheck: Expected suggestion not found"; } } +static const RequestTextCheckTestCase kRequestTextCheckTestCases[] = { + {"absense", "absence"}, {"becomeing", "becoming"}, + {"cieling", "ceiling"}, {"definate", "definite"}, + {"eigth", "eight"}, {"exellent", "excellent"}, + {"finaly", "finally"}, {"garantee", "guarantee"}, + {"humerous", "humorous"}, {"imediately", "immediately"}, + {"jellous", "jealous"}, {"knowlege", "knowledge"}, + {"lenght", "length"}, {"manuever", "maneuver"}, + {"naturaly", "naturally"}, {"ommision", "omission"}, +}; + +class WindowsSpellCheckerRequestTextCheckTest + : public WindowsSpellCheckerTest, + public testing::WithParamInterface<RequestTextCheckTestCase> {}; + +INSTANTIATE_TEST_SUITE_P(TestCases, + WindowsSpellCheckerRequestTextCheckTest, + testing::ValuesIn(kRequestTextCheckTestCases)); + +TEST_P(WindowsSpellCheckerRequestTextCheckTest, RequestTextCheck) { + RunRequestTextCheckTest(GetParam()); +} + +class WindowsSpellCheckerRequestTextCheckWithSuggestionsTest + : public WindowsSpellCheckerRequestTextCheckTest { + protected: + void SetUp() override { + // Want to maintain test coverage for requesting suggestions on call to + // RequestTextCheck. + feature_list_.InitWithFeatures( + /*enabled_features=*/{spellcheck::kWinUseBrowserSpellChecker}, + /*disabled_features=*/{ + spellcheck::kWinRetrieveSuggestionsOnlyOnDemand}); + } +}; + +INSTANTIATE_TEST_SUITE_P(TestCases, + WindowsSpellCheckerRequestTextCheckWithSuggestionsTest, + testing::ValuesIn(kRequestTextCheckTestCases)); + +TEST_P(WindowsSpellCheckerRequestTextCheckWithSuggestionsTest, + RequestTextCheck) { + RunRequestTextCheckTest(GetParam()); +} + TEST_F(WindowsSpellCheckerTest, RetrieveSpellcheckLanguages) { // Test retrieval of real dictionary on system (useful for debug logging // other registered dictionaries).
diff --git a/components/spellcheck/common/spellcheck.mojom b/components/spellcheck/common/spellcheck.mojom index 21bce14..5116380 100644 --- a/components/spellcheck/common/spellcheck.mojom +++ b/components/spellcheck/common/spellcheck.mojom
@@ -75,12 +75,6 @@ FillSuggestionList(mojo_base.mojom.String16 word) => (array<mojo_base.mojom.String16> suggestions); - // Returns a list of suggestions for each spellcheck language for a given word - // with a platform-specific spell checker. - [EnableIf=is_win, Sync] - GetPerLanguageSuggestions(mojo_base.mojom.String16 word) => - (array<array<mojo_base.mojom.String16>> suggestions); - // Completes initialization of the spellcheck service by loading dictionaries. [EnableIf=is_win] InitializeDictionaries() =>
diff --git a/components/spellcheck/common/spellcheck_features.cc b/components/spellcheck/common/spellcheck_features.cc index ac010b7..99717a6 100644 --- a/components/spellcheck/common/spellcheck_features.cc +++ b/components/spellcheck/common/spellcheck_features.cc
@@ -31,6 +31,9 @@ const base::Feature kWinDelaySpellcheckServiceInit{ "WinDelaySpellcheckServiceInit", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kWinRetrieveSuggestionsOnlyOnDemand{ + "WinRetrieveSuggestionsOnlyOnDemand", base::FEATURE_ENABLED_BY_DEFAULT}; + bool WindowsVersionSupportsSpellchecker() { return base::win::GetVersion() > base::win::Version::WIN7 && base::win::GetVersion() < base::win::Version::WIN_LAST;
diff --git a/components/spellcheck/common/spellcheck_features.h b/components/spellcheck/common/spellcheck_features.h index 282bd74c..a40f1850 100644 --- a/components/spellcheck/common/spellcheck_features.h +++ b/components/spellcheck/common/spellcheck_features.h
@@ -38,6 +38,12 @@ // --disable-sync-types="Dictionary" extern const base::Feature kWinDelaySpellcheckServiceInit; +// When set, do not perform the expensive operation of retrieving suggestions +// for all misspelled words while performing a text check. Instead retrieve +// suggestions on demand when the context menu is brought up with a misspelled +// word selected. +extern const base::Feature kWinRetrieveSuggestionsOnlyOnDemand; + bool WindowsVersionSupportsSpellchecker(); #endif // defined(OS_WIN)
diff --git a/components/spellcheck/renderer/spellcheck_provider.cc b/components/spellcheck/renderer/spellcheck_provider.cc index 4ed5859..81f932b 100644 --- a/components/spellcheck/renderer/spellcheck_provider.cc +++ b/components/spellcheck/renderer/spellcheck_provider.cc
@@ -270,31 +270,17 @@ #if defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) base::TimeTicks suggestions_start = base::TimeTicks::Now(); #endif // defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) + // Retrieve suggestions from Hunspell. Windows platform spellchecker + // suggestions are retrieved in SpellingMenuObserver::InitMenu on the + // browser process side to avoid a blocking IPC. spellcheck::PerLanguageSuggestions per_language_suggestions; spellcheck_->SpellCheckWord(word.c_str(), kWordStart, word.size(), routing_id(), &offset, &length, &per_language_suggestions); #if defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) - if (spellcheck::UseBrowserSpellChecker() && - spellcheck_->EnabledLanguageCount() < spellcheck_->LanguageCount()) { - // Also fetch suggestions from the browser process (native spellchecker). - // This is a synchronous Mojo call, because this method must return - // synchronously. - spellcheck::PerLanguageSuggestions browser_suggestions; - GetSpellCheckHost().GetPerLanguageSuggestions(word, &browser_suggestions); - - per_language_suggestions.reserve(per_language_suggestions.size() + - browser_suggestions.size()); - per_language_suggestions.insert(per_language_suggestions.end(), - browser_suggestions.begin(), - browser_suggestions.end()); - spellcheck_renderer_metrics::RecordHybridSuggestionDuration( - base::TimeTicks::Now() - suggestions_start); - } else { - spellcheck_renderer_metrics::RecordHunspellSuggestionDuration( - base::TimeTicks::Now() - suggestions_start); - } + spellcheck_renderer_metrics::RecordHunspellSuggestionDuration( + base::TimeTicks::Now() - suggestions_start); #endif // defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) std::vector<std::u16string> suggestions;
diff --git a/components/spellcheck/renderer/spellcheck_provider_test.cc b/components/spellcheck/renderer/spellcheck_provider_test.cc index 4d25a89..e406f09 100644 --- a/components/spellcheck/renderer/spellcheck_provider_test.cc +++ b/components/spellcheck/renderer/spellcheck_provider_test.cc
@@ -186,12 +186,6 @@ } #if defined(OS_WIN) -void TestingSpellCheckProvider::GetPerLanguageSuggestions( - const std::u16string& word, - GetPerLanguageSuggestionsCallback callback) { - NOTREACHED(); -} - void TestingSpellCheckProvider::InitializeDictionaries( InitializeDictionariesCallback callback) { if (base::FeatureList::IsEnabled(
diff --git a/components/spellcheck/renderer/spellcheck_provider_test.h b/components/spellcheck/renderer/spellcheck_provider_test.h index 6868c032..493cbd1 100644 --- a/components/spellcheck/renderer/spellcheck_provider_test.h +++ b/components/spellcheck/renderer/spellcheck_provider_test.h
@@ -144,11 +144,7 @@ CheckSpellingCallback) override; void FillSuggestionList(const std::u16string&, FillSuggestionListCallback) override; - #if defined(OS_WIN) - void GetPerLanguageSuggestions( - const std::u16string& word, - GetPerLanguageSuggestionsCallback callback) override; void InitializeDictionaries(InitializeDictionariesCallback callback) override; #endif // defined(OS_WIN) #endif // BUILDFLAG(USE_BROWSER_SPELLCHECKER)
diff --git a/components/translate/content/renderer/translate_agent.h b/components/translate/content/renderer/translate_agent.h index b58459f..c06f675 100644 --- a/components/translate/content/renderer/translate_agent.h +++ b/components/translate/content/renderer/translate_agent.h
@@ -162,7 +162,7 @@ std::string source_lang_; std::string target_lang_; - // Time when a page langauge is determined. This is used to know a duration + // Time when a page language is determined. This is used to know a duration // time from showing infobar to requesting translation. base::TimeTicks language_determined_time_;
diff --git a/components/translate/core/browser/translate_manager.cc b/components/translate/core/browser/translate_manager.cc index aa2f22e..1f5c371 100644 --- a/components/translate/core/browser/translate_manager.cc +++ b/components/translate/core/browser/translate_manager.cc
@@ -178,7 +178,7 @@ // object. It should instead be passed around to code that uses it. InitTranslateEvent(page_language_code, target_lang, *translate_prefs); - // Logs the initial source and target langauges, as well as whether the + // Logs the initial source and target languages, as well as whether the // initial source language is in the user's content language. GetActiveTranslateMetricsLogger()->LogInitialSourceLanguage( page_language_code,
diff --git a/components/webapk/android/libs/client/src/org/chromium/components/webapk/lib/client/WebApkValidator.java b/components/webapk/android/libs/client/src/org/chromium/components/webapk/lib/client/WebApkValidator.java index 813219b..cd21da9 100644 --- a/components/webapk/android/libs/client/src/org/chromium/components/webapk/lib/client/WebApkValidator.java +++ b/components/webapk/android/libs/client/src/org/chromium/components/webapk/lib/client/WebApkValidator.java
@@ -211,13 +211,6 @@ @SuppressLint("PackageManagerGetSignatures") private static @ValidationResult int isValidWebApkInternal( Context context, String webappPackageName) { - if (sOverrideValidationForTesting) { - if (DEBUG) { - Log.d(TAG, "WebApk validation is disabled for testing."); - } - // Always return V1_WEB_APK in this case, because we only care if it's V1 WebAPK. - return ValidationResult.V1_WEB_APK; - } if (sExpectedSignature == null || sCommentSignedPublicKeyBytes == null) { Log.wtf(TAG, "WebApk validation failure - expected signature not set - " @@ -238,6 +231,13 @@ if (isNotWebApkQuick(packageInfo)) { return ValidationResult.FAILURE; } + if (sOverrideValidationForTesting) { + if (DEBUG) { + Log.d(TAG, "WebApk validation is disabled for testing."); + } + // Always return V1_WEB_APK in this case, because we only care if it's V1 WebAPK. + return ValidationResult.V1_WEB_APK; + } if (verifyV1WebApk(packageInfo, webappPackageName)) { return ValidationResult.V1_WEB_APK; }
diff --git a/components/webapk/android/libs/client/src/org/chromium/components/webapk/lib/client/WebApkValidatorTest.java b/components/webapk/android/libs/client/src/org/chromium/components/webapk/lib/client/WebApkValidatorTest.java index f379955..4c8ccbe 100644 --- a/components/webapk/android/libs/client/src/org/chromium/components/webapk/lib/client/WebApkValidatorTest.java +++ b/components/webapk/android/libs/client/src/org/chromium/components/webapk/lib/client/WebApkValidatorTest.java
@@ -78,6 +78,7 @@ public void setUp() { mPackageManager = Shadows.shadowOf(RuntimeEnvironment.application.getPackageManager()); WebApkValidator.init(EXPECTED_SIGNATURE, PUBLIC_KEY); + WebApkValidator.setDisableValidationForTesting(false); } /** @@ -467,6 +468,51 @@ RuntimeEnvironment.application, "https://evil.com/manifest.json")); } + /** + * Tests when override validation is set, {@link WebApkValidator.isValidWebApk} returns + * true with invalid signature. + */ + @Test + public void testIsValidWebApkWithOverridesSignature() { + mPackageManager.addPackage(newPackageInfoWithBrowserSignature( + WEBAPK_PACKAGE_NAME, new Signature(SIGNATURE_1), TEST_STARTURL, null)); + + assertFalse( + WebApkValidator.isValidWebApk(RuntimeEnvironment.application, WEBAPK_PACKAGE_NAME)); + + WebApkValidator.setDisableValidationForTesting(true); + assertTrue( + WebApkValidator.isValidWebApk(RuntimeEnvironment.application, WEBAPK_PACKAGE_NAME)); + } + + /** + * Tests when override validation is set, {@link WebApkValidator.isValidWebApk} returns false + * when no START_URL. + */ + @Test + public void testIsValidWebApkOverridesReturnsFalseNoStartUrl() { + PackageInfo webapkPackage = newPackageInfoWithBrowserSignature( + WEBAPK_PACKAGE_NAME, new Signature(EXPECTED_SIGNATURE), TEST_STARTURL, null); + webapkPackage.applicationInfo.metaData.remove(START_URL); + mPackageManager.addPackage(webapkPackage); + + WebApkValidator.setDisableValidationForTesting(true); + assertFalse( + WebApkValidator.isValidWebApk(RuntimeEnvironment.application, WEBAPK_PACKAGE_NAME)); + } + + /** + * Tests when override validation is set, {@link WebApkValidator.isValidWebApk} returns false + * when package is not installed. + */ + @Test + public void testIsValidWebApkOverridesPackageNotFound() { + WebApkValidator.setDisableValidationForTesting(true); + + assertFalse(WebApkValidator.isValidWebApk( + RuntimeEnvironment.application, INVALID_WEBAPK_PACKAGE_NAME)); + } + // Get the full test file path. private static String testFilePath(String fileName) { return TestDir.getTestFilePath(TEST_DATA_DIR + fileName);
diff --git a/content/browser/accessibility/browser_accessibility_android.cc b/content/browser/accessibility/browser_accessibility_android.cc index 3a6da58..5dfee16 100644 --- a/content/browser/accessibility/browser_accessibility_android.cc +++ b/content/browser/accessibility/browser_accessibility_android.cc
@@ -496,26 +496,22 @@ BrowserAccessibilityManagerAndroid* manager_android = static_cast<BrowserAccessibilityManagerAndroid*>(manager()); if (manager_android->prune_tree_for_screen_reader()) { - // Headings with text can drop their children. + // For some nodes, we will consider children before determining if the node + // is a leaf. For nodes with relevant children, we will return false here + // and allow the child nodes to be set as a leaf. + + // Headings with text can drop their children (with exceptions). std::u16string name = GetInnerText(); if (GetRole() == ax::mojom::Role::kHeading && !name.empty()) { - if (HasFocusableNonOptionChild()) { - return false; - } else { - return true; - } + return IsLeafConsideringChildren(); } - // Focusable nodes with text should not expose their children. + // Focusable nodes with text can drop their children (with exceptions). if (HasState(ax::mojom::State::kFocusable) && !name.empty()) { - if (HasFocusableNonOptionChild()) { - return false; - } else { - return true; - } + return IsLeafConsideringChildren(); } - // Nodes with only static text as children should not expose their children. + // Nodes with only static text can drop their children. if (HasOnlyTextChildren()) return true; } @@ -523,6 +519,47 @@ return false; } +bool BrowserAccessibilityAndroid::IsLeafConsideringChildren() const { + // This is called from IsLeaf, so don't call PlatformChildCount + // from within this! + + // Check for any children that should be exposed and return false if found (by + // returning false we are saying the parent node is NOT a leaf and this child + // node should instead be the leaf). + // + // If a node has a child that meets any of these criteria, it is NOT a leaf: + // + // * child is focusable, and NOT a menu option + // * child is a table, cell, or row + // + for (auto it = InternalChildrenBegin(); it != InternalChildrenEnd(); ++it) { + BrowserAccessibility* child = it.get(); + + if (child->HasState(ax::mojom::State::kFocusable) && + child->GetRole() != ax::mojom::Role::kMenuListOption) { + return false; + } + + if (child->GetRole() == ax::mojom::Role::kTable || + child->GetRole() == ax::mojom::Role::kCell || + child->GetRole() == ax::mojom::Role::kRow || + child->GetRole() == ax::mojom::Role::kLayoutTable || + child->GetRole() == ax::mojom::Role::kLayoutTableCell || + child->GetRole() == ax::mojom::Role::kLayoutTableRow) { + return false; + } + + // Check nested children and return false if any meet above criteria. + if (!static_cast<BrowserAccessibilityAndroid*>(child) + ->IsLeafConsideringChildren()) + return false; + } + + // If no such children were found, return true signaling the parent node can + // be the leaf node. + return true; +} + std::u16string BrowserAccessibilityAndroid::GetInnerText() const { if (ui::IsIframe(GetRole())) return std::u16string(); @@ -2112,21 +2149,6 @@ } } -bool BrowserAccessibilityAndroid::HasFocusableNonOptionChild() const { - // This is called from IsLeaf, so don't call PlatformChildCount - // from within this! - for (auto it = InternalChildrenBegin(); it != InternalChildrenEnd(); ++it) { - BrowserAccessibility* child = it.get(); - if (child->HasState(ax::mojom::State::kFocusable) && - child->GetRole() != ax::mojom::Role::kMenuListOption) - return true; - if (static_cast<BrowserAccessibilityAndroid*>(child) - ->HasFocusableNonOptionChild()) - return true; - } - return false; -} - std::u16string BrowserAccessibilityAndroid::GetTargetUrl() const { if (ui::IsImageOrVideo(GetRole()) || ui::IsLink(GetRole())) return GetString16Attribute(ax::mojom::StringAttribute::kUrl);
diff --git a/content/browser/accessibility/browser_accessibility_android.h b/content/browser/accessibility/browser_accessibility_android.h index 26ba139..33e14156 100644 --- a/content/browser/accessibility/browser_accessibility_android.h +++ b/content/browser/accessibility/browser_accessibility_android.h
@@ -79,7 +79,6 @@ bool HasAriaCurrent() const; - bool HasFocusableNonOptionChild() const; bool HasNonEmptyValue() const; bool HasCharacterLocations() const; @@ -88,6 +87,7 @@ const char* GetClassName() const; bool IsChildOfLeaf() const override; bool IsLeaf() const override; + bool IsLeafConsideringChildren() const; std::u16string GetInnerText() const override; std::u16string GetValueForControl() const override; std::u16string GetHint() const;
diff --git a/content/browser/accessibility/browser_accessibility_manager_unittest.cc b/content/browser/accessibility/browser_accessibility_manager_unittest.cc index 13f73f2a..cf6baa4 100644 --- a/content/browser/accessibility/browser_accessibility_manager_unittest.cc +++ b/content/browser/accessibility/browser_accessibility_manager_unittest.cc
@@ -1366,9 +1366,7 @@ ui::AXNodeData parent_childtree; parent_childtree.id = 3; - parent_childtree.AddStringAttribute( - ax::mojom::StringAttribute::kChildTreeId, - child_update.tree_data.tree_id.ToString()); + parent_childtree.AddChildTreeId(child_update.tree_data.tree_id); parent_childtree.SetName("parent_childtree"); parent_childtree.relative_bounds.bounds = gfx::RectF(100, 100, 100, 100);
diff --git a/content/browser/accessibility/browser_accessibility_manager_win_unittest.cc b/content/browser/accessibility/browser_accessibility_manager_win_unittest.cc index d3d1ed4..1af95d0 100644 --- a/content/browser/accessibility/browser_accessibility_manager_win_unittest.cc +++ b/content/browser/accessibility/browser_accessibility_manager_win_unittest.cc
@@ -114,9 +114,7 @@ ui::AXNodeData parent_tree_root; parent_tree_root.id = 1; parent_tree_root.role = ax::mojom::Role::kRootWebArea; - parent_tree_root.AddStringAttribute( - ax::mojom::StringAttribute::kChildTreeId, - child_tree_update.tree_data.tree_id.ToString()); + parent_tree_root.AddChildTreeId(child_tree_update.tree_data.tree_id); ui::AXTreeUpdate parent_tree_update = MakeAXTreeUpdate(parent_tree_root); child_tree_update.tree_data.parent_tree_id =
diff --git a/content/browser/accessibility/browser_accessibility_unittest.cc b/content/browser/accessibility/browser_accessibility_unittest.cc index 49061e3..ec4f6ba 100644 --- a/content/browser/accessibility/browser_accessibility_unittest.cc +++ b/content/browser/accessibility/browser_accessibility_unittest.cc
@@ -128,8 +128,7 @@ parent_tree_update.nodes[3].id = 4; parent_tree_update.nodes[4].id = 5; - parent_tree_update.nodes[4].AddStringAttribute( - ax::mojom::StringAttribute::kChildTreeId, child_tree_id.ToString()); + parent_tree_update.nodes[4].AddChildTreeId(child_tree_id); parent_tree_update.nodes[5].id = 6; parent_tree_update.nodes[5].child_ids = {9}; @@ -857,8 +856,7 @@ parent_tree_update.nodes[0].id = 1; parent_tree_update.nodes[0].role = ax::mojom::Role::kPortal; - parent_tree_update.nodes[0].AddStringAttribute( - ax::mojom::StringAttribute::kChildTreeId, child_tree_id.ToString()); + parent_tree_update.nodes[0].AddChildTreeId(child_tree_id); ui::AXTreeUpdate child_tree_update; child_tree_update.tree_data.tree_id = child_tree_id;
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc index 58efe94..8b275c7 100644 --- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc +++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -2721,6 +2721,11 @@ RunHtmlTest(AccessibilitySvgG_TestFile); } +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, + AccessibilityTabindexExposeChildren) { + RunHtmlTest(FILE_PATH_LITERAL("tabindex-expose-children.html")); +} + IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityTableRowAdd) { RunHtmlTest(FILE_PATH_LITERAL("table-row-add.html")); }
diff --git a/content/browser/devtools/protocol/page_handler.cc b/content/browser/devtools/protocol/page_handler.cc index 7d59a04..554b129 100644 --- a/content/browser/devtools/protocol/page_handler.cc +++ b/content/browser/devtools/protocol/page_handler.cc
@@ -505,15 +505,10 @@ params.frame_tree_node_id = frame_tree_node->frame_tree_node_id(); frame_tree_node->navigator().controller().LoadURLWithParams(params); - base::UnguessableToken frame_token = frame_tree_node->devtools_frame_token(); - auto navigate_callback = navigate_callbacks_.find(frame_token); - if (navigate_callback != navigate_callbacks_.end()) { - std::string error_string = net::ErrorToString(net::ERR_ABORTED); - navigate_callback->second->sendSuccess(out_frame_id, Maybe<std::string>(), - Maybe<std::string>(error_string)); - } if (frame_tree_node->navigation_request()) { - navigate_callbacks_[frame_token] = std::move(callback); + navigate_callbacks_[frame_tree_node->navigation_request() + ->devtools_navigation_token()] = + std::move(callback); } else { callback->sendSuccess(out_frame_id, Maybe<std::string>(), Maybe<std::string>()); @@ -521,20 +516,29 @@ } void PageHandler::NavigationReset(NavigationRequest* navigation_request) { - auto navigate_callback = navigate_callbacks_.find( - navigation_request->frame_tree_node()->devtools_frame_token()); + auto navigate_callback = + navigate_callbacks_.find(navigation_request->devtools_navigation_token()); if (navigate_callback == navigate_callbacks_.end()) return; std::string frame_id = navigation_request->frame_tree_node()->devtools_frame_token().ToString(); - bool success = navigation_request->GetNetErrorCode() == net::OK; - std::string error_string = - net::ErrorToString(navigation_request->GetNetErrorCode()); - navigate_callback->second->sendSuccess( - frame_id, - Maybe<std::string>( - navigation_request->devtools_navigation_token().ToString()), - success ? Maybe<std::string>() : Maybe<std::string>(error_string)); + // A new NavigationRequest may have been created before |navigation_request| + // started, in which case it is not marked as aborted. We report this as an + // abort to DevTools anyway. + if (!navigation_request->IsNavigationStarted()) { + navigate_callback->second->sendSuccess( + frame_id, Maybe<std::string>(), + Maybe<std::string>(net::ErrorToString(net::ERR_ABORTED))); + } else { + bool success = navigation_request->GetNetErrorCode() == net::OK; + std::string error_string = + net::ErrorToString(navigation_request->GetNetErrorCode()); + navigate_callback->second->sendSuccess( + frame_id, + Maybe<std::string>( + navigation_request->devtools_navigation_token().ToString()), + success ? Maybe<std::string>() : Maybe<std::string>(error_string)); + } navigate_callbacks_.erase(navigate_callback); }
diff --git a/content/browser/devtools/protocol/page_handler.h b/content/browser/devtools/protocol/page_handler.h index 789e05c..be667cb7 100644 --- a/content/browser/devtools/protocol/page_handler.h +++ b/content/browser/devtools/protocol/page_handler.h
@@ -244,6 +244,7 @@ base::ScopedObservation<RenderWidgetHost, RenderWidgetHostObserver> observation_{this}; JavaScriptDialogCallback pending_dialog_; + // Maps DevTools navigation tokens to pending NavigateCallbacks. base::flat_map<base::UnguessableToken, std::unique_ptr<NavigateCallback>> navigate_callbacks_; base::flat_set<download::DownloadItem*> pending_downloads_;
diff --git a/content/browser/prerender/prerender_browsertest.cc b/content/browser/prerender/prerender_browsertest.cc index c6f727c6..b8afe0946 100644 --- a/content/browser/prerender/prerender_browsertest.cc +++ b/content/browser/prerender/prerender_browsertest.cc
@@ -397,10 +397,19 @@ base::Lock lock_; }; +// TODO(crbug.com/1189150): Some MPArch fail on android-asan and therefore +// disabled. +#if defined(ADDRESS_SANITIZER) +INSTANTIATE_TEST_SUITE_P(All, + PrerenderBrowserTest, + testing::Values(kWebContents), + ToString); +#else INSTANTIATE_TEST_SUITE_P(All, PrerenderBrowserTest, testing::Values(kWebContents, kMPArch), ToString); +#endif IN_PROC_BROWSER_TEST_P(PrerenderBrowserTest, LinkRelPrerender) { const GURL kInitialUrl = GetUrl("/prerender/add_prerender.html");
diff --git a/content/browser/renderer_host/render_frame_host_manager.cc b/content/browser/renderer_host/render_frame_host_manager.cc index cd71394..54eaff5 100644 --- a/content/browser/renderer_host/render_frame_host_manager.cc +++ b/content/browser/renderer_host/render_frame_host_manager.cc
@@ -388,7 +388,7 @@ is_same_document_navigation, clear_proxies_on_commit); - // Make sure any dynamic changes to this frame's sandbox flags and feature + // Make sure any dynamic changes to this frame's sandbox flags and permissions // policy that were made prior to navigation take effect. This should only // happen for cross-document navigations. if (!is_same_document_navigation)
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc index 2ba54e4f..2ff6de6 100644 --- a/content/browser/security_exploit_browsertest.cc +++ b/content/browser/security_exploit_browsertest.cc
@@ -1535,7 +1535,7 @@ // Test that the browser correctly reports a bad message when a child frame // attempts to navigate with a Trust Tokens redemption operation associated with -// the navigation, but its parent lacks the trust-token-redemption Feature +// the navigation, but its parent lacks the trust-token-redemption Permissions // Policy feature. IN_PROC_BROWSER_TEST_F( SecurityExploitBrowserTestWithTrustTokensEnabled, @@ -1581,8 +1581,8 @@ // Test that the browser correctly reports a bad message when a child frame // attempts to navigate with a Trust Tokens signing operation associated with -// the navigation, but its parent lacks the trust-token-redemption (sic) Feature -// Policy feature. +// the navigation, but its parent lacks the trust-token-redemption (sic) +// Permissions Policy feature. IN_PROC_BROWSER_TEST_F( SecurityExploitBrowserTestWithTrustTokensEnabled, BrowserForbidsTrustTokenSigningWithoutPermissionsPolicy) {
diff --git a/content/browser/utility_sandbox_delegate_win.cc b/content/browser/utility_sandbox_delegate_win.cc index d0923bf..3147ebd 100644 --- a/content/browser/utility_sandbox_delegate_win.cc +++ b/content/browser/utility_sandbox_delegate_win.cc
@@ -62,6 +62,19 @@ // Sets the sandbox policy for the network service process. bool NetworkPreSpawnTarget(sandbox::TargetPolicy* policy) { + if (base::FeatureList::IsEnabled( + sandbox::policy::features::kNetworkServiceSandboxLPAC)) { + // LPAC sandbox is enabled, so do not use a restricted token. + if (sandbox::SBOX_ALL_OK != + policy->SetTokenLevel(sandbox::USER_UNPROTECTED, + sandbox::USER_UNPROTECTED)) { + return false; + } + // All other app container policies are set in + // SandboxWin::StartSandboxedProcess. + return true; + } + // USER_LIMITED is as tight as this sandbox can be, because // DNS running in-process is blocked by USER_RESTRICTED and // below as it can't connect to the service. @@ -115,6 +128,13 @@ bool UtilitySandboxedProcessLauncherDelegate::GetAppContainerId( std::string* appcontainer_id) { + if (sandbox_type_ == sandbox::policy::SandboxType::kNetwork) { + DCHECK(base::FeatureList::IsEnabled( + sandbox::policy::features::kNetworkServiceSandboxLPAC)); + *appcontainer_id = base::WideToUTF8(cmd_line_.GetProgram().value()); + return true; + } + if ((sandbox_type_ == sandbox::policy::SandboxType::kXrCompositing && base::FeatureList::IsEnabled(sandbox::policy::features::kXRSandbox)) || sandbox_type_ == sandbox::policy::SandboxType::kMediaFoundationCdm) { @@ -137,6 +157,11 @@ // Default policy is disabled for MF Cdm process to allow the application // of specific LPAC sandbox policies. return true; + case sandbox::policy::SandboxType::kNetwork: + // If LPAC is enabled for network sandbox then LPAC-specific policy is set + // elsewhere. + return base::FeatureList::IsEnabled( + sandbox::policy::features::kNetworkServiceSandboxLPAC); default: return false; } @@ -149,10 +174,8 @@ bool UtilitySandboxedProcessLauncherDelegate::PreSpawnTarget( sandbox::TargetPolicy* policy) { - if (sandbox_type_ == sandbox::policy::SandboxType::kNetwork) { - if (!NetworkPreSpawnTarget(policy)) - return false; - } + if (sandbox_type_ == sandbox::policy::SandboxType::kNetwork) + return NetworkPreSpawnTarget(policy); if (sandbox_type_ == sandbox::policy::SandboxType::kAudio) { if (!AudioPreSpawnTarget(policy))
diff --git a/content/browser/webrtc/webrtc_image_capture_browsertest.cc b/content/browser/webrtc/webrtc_image_capture_browsertest.cc index ce7f83f..6b32e9d 100644 --- a/content/browser/webrtc/webrtc_image_capture_browsertest.cc +++ b/content/browser/webrtc/webrtc_image_capture_browsertest.cc
@@ -23,15 +23,16 @@ namespace content { -// Disable FocusDistance test which fails with Logitec cameras. +// Disable FocusDistance test which fails with Logitech cameras. // TODO(crbug.com/957020): renable these tests when we have a way to detect // which device is connected and hence avoid running it if the camera is // Logitech. #define MAYBE_ManipulateFocusDistance DISABLED_ManipulateFocusDistance -#if defined(OS_ANDROID) // TODO(crbug.com/793859): Re-enable test on Android as soon as the cause for // the bug is understood and fixed. +// TODO(crbug.com/1187247): Flaky on Linux/Windows. +#if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_WIN) #define MAYBE_ManipulatePan DISABLED_ManipulatePan #define MAYBE_ManipulateZoom DISABLED_ManipulateZoom #else @@ -205,12 +206,24 @@ RunImageCaptureTestCase("testCreateAndGetPhotoSettingsSucceeds()")); } -IN_PROC_BROWSER_TEST_P(WebRtcImageCaptureSucceedsBrowserTest, TakePhoto) { +// TODO(crbug.com/1187247): Flaky on Linux/Windows. +#if defined(OS_LINUX) || defined(OS_WIN) +#define MAYBE_TakePhoto DISABLED_TakePhoto +#else +#define MAYBE_TakePhoto TakePhoto +#endif +IN_PROC_BROWSER_TEST_P(WebRtcImageCaptureSucceedsBrowserTest, MAYBE_TakePhoto) { embedded_test_server()->StartAcceptingConnections(); ASSERT_TRUE(RunImageCaptureTestCase("testCreateAndTakePhotoSucceeds()")); } -IN_PROC_BROWSER_TEST_P(WebRtcImageCaptureSucceedsBrowserTest, GrabFrame) { +// TODO(crbug.com/1187247): Flaky on Linux/Windows. +#if defined(OS_LINUX) || defined(OS_WIN) +#define MAYBE_GrabFrame DISABLED_GrabFrame +#else +#define MAYBE_GrabFrame GrabFrame +#endif +IN_PROC_BROWSER_TEST_P(WebRtcImageCaptureSucceedsBrowserTest, MAYBE_GrabFrame) { embedded_test_server()->StartAcceptingConnections(); ASSERT_TRUE(RunImageCaptureTestCase("testCreateAndGrabFrameSucceeds()")); }
diff --git a/content/public/android/java/src/org/chromium/content/browser/LauncherThread.java b/content/public/android/java/src/org/chromium/content/browser/LauncherThread.java index 8f9488b1..353e2797 100644 --- a/content/public/android/java/src/org/chromium/content/browser/LauncherThread.java +++ b/content/public/android/java/src/org/chromium/content/browser/LauncherThread.java
@@ -20,7 +20,7 @@ private static final JavaHandlerThread sThread = new JavaHandlerThread("Chrome_ProcessLauncherThread", Process.THREAD_PRIORITY_DEFAULT); private static final Handler sThreadHandler; - // Can be overritten in tests. + // Can be overwritten in tests. private static Handler sHandler; static { sThread.maybeStart();
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc index 290e65b..fb89f8a 100644 --- a/content/public/browser/content_browser_client.cc +++ b/content/public/browser/content_browser_client.cc
@@ -9,7 +9,7 @@ // declarations instead of including more headers. If that is infeasible, adjust // the limit. For more info, see // https://chromium.googlesource.com/chromium/src/+/HEAD/docs/wmax_tokens.md -#pragma clang max_tokens_here 853000 +#pragma clang max_tokens_here 850000 #include <utility>
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 967f7dd..60085dc0 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -972,7 +972,7 @@ base::FEATURE_DISABLED_BY_DEFAULT}; const base::Feature kMacV2GPUSandbox{"MacV2GPUSandbox", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT}; // Enables retrying to obtain list of available cameras on Macbooks after // restarting the video capture service if a previous attempt delivered zero
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index cac1c32..950b869 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -41,6 +41,7 @@ #include "base/threading/thread_restrictions.h" #include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/memory_dump_manager.h" +#include "base/trace_event/memory_pressure_level_proto.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/typed_macros.h" #include "base/values.h" @@ -90,7 +91,6 @@ #include "content/renderer/variations_render_thread_observer.h" #include "content/renderer/worker/embedded_shared_worker_stub.h" #include "content/renderer/worker/worker_thread_registry.h" -#include "components/viz/common/features.h" #include "device/gamepad/public/cpp/gamepads.h" #include "gin/public/debug.h" #include "gpu/GLES2/gl2extchromium.h" @@ -1740,8 +1740,9 @@ auto* event = ctx.event<perfetto::protos::pbzero::ChromeTrackEvent>(); auto* data = event->set_chrome_memory_pressure_notification(); - data->set_level(base::MemoryPressureListener::LevelAsTraceEnum( - memory_pressure_level)); + data->set_level( + base::trace_event::MemoryPressureLevelToTraceEnum( + memory_pressure_level)); }); if (blink_platform_impl_) blink::WebMemoryPressureListener::OnMemoryPressure(memory_pressure_level);
diff --git a/content/services/isolated_xr_device/xr_runtime_provider.cc b/content/services/isolated_xr_device/xr_runtime_provider.cc index 9bf67133..5c14def 100644 --- a/content/services/isolated_xr_device/xr_runtime_provider.cc +++ b/content/services/isolated_xr_device/xr_runtime_provider.cc
@@ -220,4 +220,4 @@ : device_service_host_(std::move(device_service_host)), io_task_runner_(std::move(io_task_runner)) {} -IsolatedXRRuntimeProvider::~IsolatedXRRuntimeProvider() = default; +IsolatedXRRuntimeProvider::~IsolatedXRRuntimeProvider() = default; \ No newline at end of file
diff --git a/content/services/isolated_xr_device/xr_runtime_provider.h b/content/services/isolated_xr_device/xr_runtime_provider.h index 3810e07..b29ecc7 100644 --- a/content/services/isolated_xr_device/xr_runtime_provider.h +++ b/content/services/isolated_xr_device/xr_runtime_provider.h
@@ -54,8 +54,20 @@ scoped_refptr<base::SingleThreadTaskRunner> task_runner); bool should_check_openxr_ = false; - std::unique_ptr<device::OpenXrDevice> openxr_device_; + + // We need to make sure openxr_device is destroyed before openxr_statics + // because there might be an active render-loop thread that is owned by + // openxr_device that has an active xr session, + // which get into a race condition if: + // - openxr_statics is destroyed due to a tab closing (or refresh), + // triggering xrDestroyInstance on the XrInstance owned by OpenXRStatics + // - At the same time, the session is being ended on the renderloop thread, + // and xrDestroySession could be running at the same time. + // Note that: Destructors for nonstatic member objects are called in the + // reverse order in which they appear in the class declaration. std::unique_ptr<device::OpenXrStatics> openxr_statics_; + std::unique_ptr<device::OpenXrDevice> openxr_device_; + std::unique_ptr<viz::Gpu> viz_gpu_; #endif
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index c5cb6e0..2df239a93 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -665,7 +665,7 @@ group("performance_web_engine_test_suite") { testonly = true data = [ - "//content/test/gpu/run_telemetry_test_fuchsia.py", + "//content/test/gpu/run_telemetry_benchmark_fuchsia.py", "//content/test/gpu/", ] data_deps = [
diff --git a/content/test/data/accessibility/html/tabindex-expose-children-expected-android.txt b/content/test/data/accessibility/html/tabindex-expose-children-expected-android.txt new file mode 100644 index 0000000..b40129f --- /dev/null +++ b/content/test/data/accessibility/html/tabindex-expose-children-expected-android.txt
@@ -0,0 +1,10 @@ +android.webkit.WebView focusable focused scrollable +++android.view.View +++++android.view.View +++++++android.view.View name='1.' +++++++android.view.View name='2.' +++android.view.View focusable name='3. 4.' +++++android.view.View +++++++android.view.View +++++++++android.view.View name='3.' +++++++++android.view.View name='4.' \ No newline at end of file
diff --git a/content/test/data/accessibility/html/tabindex-expose-children-expected-auralinux.txt b/content/test/data/accessibility/html/tabindex-expose-children-expected-auralinux.txt new file mode 100644 index 0000000..11267851 --- /dev/null +++ b/content/test/data/accessibility/html/tabindex-expose-children-expected-auralinux.txt
@@ -0,0 +1,14 @@ +[document web] +++[section] +++++[section] +++++++[section] name='1.' +++++++++[static] name='1.' +++++++[section] name='2.' +++++++++[static] name='2.' +++[section] name='3. 4.' +++++[section] +++++++[section] +++++++++[section] name='3.' +++++++++++[static] name='3.' +++++++++[section] name='4.' +++++++++++[static] name='4.' \ No newline at end of file
diff --git a/content/test/data/accessibility/html/tabindex-expose-children-expected-blink.txt b/content/test/data/accessibility/html/tabindex-expose-children-expected-blink.txt new file mode 100644 index 0000000..f3d129d --- /dev/null +++ b/content/test/data/accessibility/html/tabindex-expose-children-expected-blink.txt
@@ -0,0 +1,23 @@ +rootWebArea +++genericContainer ignored +++++genericContainer ignored +++++++genericContainer ignored +++++++++layoutTable +++++++++++genericContainer ignored +++++++++++++layoutTableRow +++++++++++++++layoutTableCell name='1.' +++++++++++++++++staticText name='1.' +++++++++++++++++++inlineTextBox name='1.' +++++++++++++++layoutTableCell name='2.' +++++++++++++++++staticText name='2.' +++++++++++++++++++inlineTextBox name='2.' +++++++genericContainer name='3. 4.' +++++++++layoutTable +++++++++++genericContainer ignored +++++++++++++layoutTableRow +++++++++++++++layoutTableCell name='3.' +++++++++++++++++staticText name='3.' +++++++++++++++++++inlineTextBox name='3.' +++++++++++++++layoutTableCell name='4.' +++++++++++++++++staticText name='4.' +++++++++++++++++++inlineTextBox name='4.' \ No newline at end of file
diff --git a/content/test/data/accessibility/html/tabindex-expose-children-expected-mac.txt b/content/test/data/accessibility/html/tabindex-expose-children-expected-mac.txt new file mode 100644 index 0000000..e0fb06d7 --- /dev/null +++ b/content/test/data/accessibility/html/tabindex-expose-children-expected-mac.txt
@@ -0,0 +1,14 @@ +AXWebArea +++AXGroup +++++AXGroup +++++++AXGroup AXTitle='1.' +++++++++AXStaticText AXValue='1.' +++++++AXGroup AXTitle='2.' +++++++++AXStaticText AXValue='2.' +++AXGroup AXDescription='3. 4.' +++++AXGroup +++++++AXGroup +++++++++AXGroup AXTitle='3.' +++++++++++AXStaticText AXValue='3.' +++++++++AXGroup AXTitle='4.' +++++++++++AXStaticText AXValue='4.' \ No newline at end of file
diff --git a/content/test/data/accessibility/html/tabindex-expose-children-expected-uia-win.txt b/content/test/data/accessibility/html/tabindex-expose-children-expected-uia-win.txt new file mode 100644 index 0000000..824ee840 --- /dev/null +++ b/content/test/data/accessibility/html/tabindex-expose-children-expected-uia-win.txt
@@ -0,0 +1,14 @@ +Document +++Table Grid.ColumnCount=2 Grid.RowCount=1 +++++DataItem IsControlElement=false +++++++DataItem Name='1.' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=0 GridItem.RowSpan=1 +++++++++Text Name='1.' IsControlElement=false +++++++DataItem Name='2.' GridItem.Column=1 GridItem.ColumnSpan=1 GridItem.Row=0 GridItem.RowSpan=1 +++++++++Text Name='2.' IsControlElement=false +++Group Name='3. 4.' +++++Table Grid.ColumnCount=2 Grid.RowCount=1 +++++++DataItem IsControlElement=false +++++++++DataItem Name='3.' GridItem.Column=0 GridItem.ColumnSpan=1 GridItem.Row=0 GridItem.RowSpan=1 +++++++++++Text Name='3.' IsControlElement=false +++++++++DataItem Name='4.' GridItem.Column=1 GridItem.ColumnSpan=1 GridItem.Row=0 GridItem.RowSpan=1 +++++++++++Text Name='4.' IsControlElement=false \ No newline at end of file
diff --git a/content/test/data/accessibility/html/tabindex-expose-children-expected-win.txt b/content/test/data/accessibility/html/tabindex-expose-children-expected-win.txt new file mode 100644 index 0000000..361d236 --- /dev/null +++ b/content/test/data/accessibility/html/tabindex-expose-children-expected-win.txt
@@ -0,0 +1,14 @@ +ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE +++ROLE_SYSTEM_TABLE layout-guess:true +++++ROLE_SYSTEM_ROW +++++++ROLE_SYSTEM_CELL name='1.' +++++++++ROLE_SYSTEM_STATICTEXT name='1.' +++++++ROLE_SYSTEM_CELL name='2.' +++++++++ROLE_SYSTEM_STATICTEXT name='2.' +++IA2_ROLE_SECTION name='3. 4.' FOCUSABLE +++++ROLE_SYSTEM_TABLE layout-guess:true +++++++ROLE_SYSTEM_ROW +++++++++ROLE_SYSTEM_CELL name='3.' +++++++++++ROLE_SYSTEM_STATICTEXT name='3.' +++++++++ROLE_SYSTEM_CELL name='4.' +++++++++++ROLE_SYSTEM_STATICTEXT name='4.' \ No newline at end of file
diff --git a/content/test/data/accessibility/html/tabindex-expose-children.html b/content/test/data/accessibility/html/tabindex-expose-children.html new file mode 100644 index 0000000..6fab16c --- /dev/null +++ b/content/test/data/accessibility/html/tabindex-expose-children.html
@@ -0,0 +1,21 @@ +<html> + <body> + <div> + <table> + <tr> + <td>1.</td> + <td>2.</td> + </tr> + </table> + </div> + + <div tabindex="0"> + <table> + <tr> + <td>3.</td> + <td>4.</td> + </tr> + </table> + </div> + </body> +</html>
diff --git a/content/test/data/gpu/vc/webgpu_video.js b/content/test/data/gpu/vc/webgpu_video.js index e7d45769c..c697a19 100644 --- a/content/test/data/gpu/vc/webgpu_video.js +++ b/content/test/data/gpu/vc/webgpu_video.js
@@ -339,32 +339,42 @@ ], }); - // The frameId is increased by one every time oneFrame() is called. - var frameId = 0; + // videos #0-#3 : 30 fps. + // videos #3-#15: 15 fps. + // videos #16+: 7 fps. + // Not every video frame is ready in rAF callback. Only draw videos that + // are ready. + var videoIsReady = new Array(videos.length); - // The videos are displayed at different frame rate with lower indices in - // videos updated faster than hight indices. - // For videos #0-#3, they are to be displayed at 30 fps. - // For videos #3-#15, they are to be displayed at 15 fps. - // For videos #16+, they are to be displayed at 7.5 fps. - // Since oneFrame() is called at 30 fps, the video textures #0-#3 are copied - // every frame, #4 -#15 are copied every other frame and #16+ are copied - // every 4 frames. - function GetNumOfVideosToCopyForCurrentFrame(frameId) { - switch (frameId % 4) { - case 0: - return videos.length; - case 1: - case 3: - return Math.min(4, videos.length); - case 2: - return Math.min(16, videos.length); - default: - console.error('Something wrong with frameId % 4'); - } + function UpdateIsVideoReady(video) { + videoIsReady[video.id] = true; + video.requestVideoFrameCallback(function () { + UpdateIsVideoReady(video); + }); } - const oneFrame = () => { + for (const video of videos) { + video.requestVideoFrameCallback(function () { + UpdateIsVideoReady(video); + }); + } + + // If rAF is running at 60 fps, skip every other frame so the demo is + // running at 30 fps. + // 30 fps is 33 milliseconds/frame. To prevent skipping frames accidentally + // when rAF is running near 30fps with small delta, use 32 ms instead of 33 ms + // for comparison. + const frameTime30Fps = 32; + let lastTimestamp = performance.now(); + + const oneFrame = (timestamp) => { + const elapsed = timestamp - lastTimestamp; + if (elapsed < frameTime30Fps) { + window.requestAnimationFrame(oneFrame); + return; + } + lastTimestamp = timestamp; + const swapChainTexture = swapChain.getCurrentTexture(); renderPassDescriptor.colorAttachments[0].attachment = swapChainTexture .createView(); @@ -376,24 +386,21 @@ passEncoder.setPipeline(pipeline); passEncoder.setVertexBuffer(0, verticesBuffer); - // These videos are displayed at different fps. Not every video needs to be - // updated in this frame. The videos at lower indices are updated faster - // (higher fps) than videos at higher indices. See comments of - // GetNumOfVideosToCopyForCurrentFrame() for how the videos with different - // fps are arranged. - const numVideosToCopy = GetNumOfVideosToCopyForCurrentFrame(frameId); - - Promise.all(videos.slice(0, numVideosToCopy). - map(video => createImageBitmap(video))).then((videoFrames) => { - for (let i = 0; i < numVideosToCopy; ++i) { - device.queue.copyImageBitmapToTexture( - { imageBitmap: videoFrames[i], origin: { x: 0, y: 0 } }, - { texture: videoTextures[i] }, - { - width: videos[i].videoWidth, height: videos[i].videoHeight, - depthOrArrayLayers: 1 - } - ); + Promise.all(videos.map(video => + (videoIsReady[video.id] ? createImageBitmap(video) : null))). + then((videoFrames) => { + for (let i = 0; i < videos.length; ++i) { + if (videoFrames[i] != undefined) { + device.queue.copyImageBitmapToTexture( + { imageBitmap: videoFrames[i], origin: { x: 0, y: 0 } }, + { texture: videoTextures[i] }, + { + width: videos[i].videoWidth, height: videos[i].videoHeight, + depthOrArrayLayers: 1 + } + ); + videoIsReady[i] = false; + } } for (let i = 0; i < videos.length; ++i) { @@ -411,33 +418,31 @@ passEncoder.endPass(); device.queue.submit([commandEncoder.finish()]); - frameId++; + window.requestAnimationFrame(oneFrame); }); } - const oneFrameWithImportTextureApi = () => { + const oneFrameWithImportTextureApi = (timestamp) => { + const elapsed = timestamp - lastTimestamp; + if (elapsed < frameTime30Fps) { + window.requestAnimationFrame(oneFrame); + return; + } + lastTimestamp = timestamp; + + for (let i = 0; i < videos.length; ++i) { + if (videoIsReady[i]) { + videoTextures[i].destroy(); + videoTextures[i] = device.experimentalImportTexture( + videos[i], GPUTextureUsage.SAMPLED); + videoIsReady[i] = false; + } + } + const swapChainTexture = swapChain.getCurrentTexture(); renderPassDescriptor.colorAttachments[0].attachment = swapChainTexture .createView(); - // These videos are displayed at different fps. Not every video needs to be - // updated in this frame. The videos at lower indices are updated faster - // than videos at higher indices. See GetNumOfVideosToCopyForCurrentFrame() - // for how the videos with different fps are arranged. - const numVideosToCopy = GetNumOfVideosToCopyForCurrentFrame(frameId); - - // Destroy the textures after submit to promptly recycle resources. - // The textures not being imported here this time are not to be destroyed. - // We still need to render those textures for this frame. - for (let i = 0; i < numVideosToCopy; ++i) { - videoTextures[i].destroy(); - } - - for (let i = 0; i < numVideosToCopy; ++i) { - videoTextures[i] = device.experimentalImportTexture( - videos[i], GPUTextureUsage.SAMPLED); - } - const commandEncoder = device.createCommandEncoder(); const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); @@ -472,13 +477,12 @@ passEncoder.endPass(); device.queue.submit([commandEncoder.finish()]); - frameId++; + window.requestAnimationFrame(oneFrameWithImportTextureApi); } - // Call oneFrame() every 33 milliseconds to simulate 30 fps. if (useImportTextureApi) { - setInterval(oneFrameWithImportTextureApi, 33); + window.requestAnimationFrame(oneFrameWithImportTextureApi); } else { - setInterval(oneFrame, 33); + window.requestAnimationFrame(oneFrame); } }
diff --git a/content/test/data/gpu/vc/webgpu_videos_mxn.html b/content/test/data/gpu/vc/webgpu_videos_mxn.html index eab8b37d..3ed98dd 100644 --- a/content/test/data/gpu/vc/webgpu_videos_mxn.html +++ b/content/test/data/gpu/vc/webgpu_videos_mxn.html
@@ -130,7 +130,7 @@ const videoCount = videoRows * videoColumns; for (let i = 0; i < videoCount + 1; i++) { const video = document.createElement('video'); - video.id = 'video_' + i; + video.id = i; video.loop = true; video.autoplay = true; video.muted = true;
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt index 3e44f1d8..ca72ac9e 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
@@ -120,8 +120,6 @@ crbug.com/angleproject/4807 [ win angle-d3d11 passthrough ] conformance2/glsl3/switch-case.html [ Failure ] crbug.com/1081973 conformance/buffers/buffer-data-and-buffer-sub-data.html [ Failure ] crbug.com/1082533 [ mac intel ] conformance/textures/misc/texture-copying-and-deletion.html [ Failure ] -crbug.com/1082533 [ win angle-vulkan passthrough ] conformance/textures/misc/texture-copying-and-deletion.html [ Failure ] -crbug.com/1018028 [ win angle-vulkan ] conformance/rendering/bind-framebuffer-flush-bug.html [ Failure ] crbug.com/angleproject/5038 conformance/extensions/ext-color-buffer-half-float.html [ Skip ] # TODO(crbug.com/1136231): Uncomment suppression for s3tc-and-rgtc.html below # under crbug.com/963205 once these two failures are fixed. @@ -133,7 +131,6 @@ # Failing on some platforms. crbug.com/1175371 [ android ] conformance/extensions/khr-parallel-shader-compile.html [ Failure ] -crbug.com/1175371 [ chromeos ] conformance/extensions/khr-parallel-shader-compile.html [ Failure ] crbug.com/1175371 [ linux ] conformance/extensions/khr-parallel-shader-compile.html [ Failure ] crbug.com/1175371 [ mac ] conformance/extensions/khr-parallel-shader-compile.html [ Failure ] crbug.com/1175371 [ win ] conformance/extensions/khr-parallel-shader-compile.html [ Failure ] @@ -143,23 +140,12 @@ crbug.com/953120 conformance/programs/program-handling.html [ Failure ] -crbug.com/949249 [ win passthrough angle-opengl nvidia ] conformance2/extensions/ovr_multiview2.html [ Failure ] crbug.com/949249 [ win passthrough angle-d3d11 ] conformance2/extensions/ovr_multiview2.html [ Failure ] crbug.com/949249 [ linux passthrough angle-opengl ] conformance2/extensions/ovr_multiview2.html [ Failure ] -# Failing new test -crbug.com/874620 [ linux nvidia ] conformance2/glsl3/const-struct-from-array-as-function-parameter.html [ Failure ] -crbug.com/874620 [ angle-opengl win nvidia ] conformance2/glsl3/const-struct-from-array-as-function-parameter.html [ Failure ] - # Too slow (take about one hour to run) crbug.com/619403 deqp/functional/gles3/builtinprecision/* [ Skip ] -# Failing on NVIDIA OpenGL, but fixed in latest driver -# TODO(http://crbug.com/887241): Upgrade the drivers on the bots. -crbug.com/772651 [ linux nvidia ] conformance/glsl/bugs/vector-scalar-arithmetic-inside-loop.html [ Failure ] -crbug.com/772651 [ android nvidia ] conformance/glsl/bugs/vector-scalar-arithmetic-inside-loop.html [ Failure ] -crbug.com/772651 [ nvidia ] conformance/glsl/bugs/vector-scalar-arithmetic-inside-loop-complex.html [ Failure ] - # This test needs to be rewritten to measure its expected # performance; it's currently too flaky even on release bots. crbug.com/735483 conformance/rendering/texture-switch-performance.html [ Skip ] @@ -169,33 +155,16 @@ # TODO(crbug.com/979444): once this is passing on the passthrough # command decoder on Android, simplify this expectation to just not # declare any OS. -crbug.com/979444 [ chromeos ] conformance/textures/misc/texture-corner-case-videos.html [ RetryOnFailure ] crbug.com/979444 [ linux ] conformance/textures/misc/texture-corner-case-videos.html [ RetryOnFailure ] crbug.com/979444 [ mac no-asan no-passthrough ] conformance/textures/misc/texture-corner-case-videos.html [ RetryOnFailure ] crbug.com/979444 [ win ] conformance/textures/misc/texture-corner-case-videos.html [ RetryOnFailure ] crbug.com/979444 [ android angle-disabled ] conformance/textures/misc/texture-corner-case-videos.html [ RetryOnFailure ] -# Nvidia bugs fixed in latest driver -# TODO(http://crbug.com/887241): Upgrade the drivers on the bots. -crbug.com/798117 [ angle-vulkan win nvidia ] conformance/glsl/bugs/assign-to-swizzled-twice-in-function.html [ Failure ] -crbug.com/798117 [ linux nvidia ] conformance/glsl/bugs/assign-to-swizzled-twice-in-function.html [ Failure ] -crbug.com/792210 [ nvidia ] conformance/glsl/bugs/in-parameter-passed-as-inout-argument-and-global.html [ Failure ] - # Flaky timeouts on Intel Windows, Linux and Mac crbug.com/1085222 [ win10 intel-0x3e92 ] deqp/functional/gles3/shaderoperator/binary_operator_* [ Failure ] -crbug.com/1085222 [ win10 intel-0x3e92 ] deqp/functional/gles3/shaderoperator/unary_operator_01.html [ Failure ] -crbug.com/1085222 [ win10 intel-0x3e92 ] deqp/functional/gles3/shaderoperator/unary_operator_02.html [ Failure ] crbug.com/1085222 [ win10 intel-0x5912 ] deqp/functional/gles3/shaderoperator/binary_operator_* [ Failure ] crbug.com/1085222 [ win10 intel-0x5912 ] deqp/functional/gles3/shaderoperator/unary_operator_01.html [ Failure ] crbug.com/1085222 [ win10 intel-0x5912 ] deqp/functional/gles3/shaderoperator/unary_operator_02.html [ Failure ] -crbug.com/1085222 [ linux intel-0x3e92 ] deqp/functional/gles3/shaderoperator/binary_operator_* [ RetryOnFailure ] -crbug.com/1085222 [ linux intel-0x3e92 ] deqp/functional/gles3/shadermatrix/sub_* [ RetryOnFailure ] -crbug.com/1085222 [ linux intel-0x3e92 ] deqp/functional/gles3/shadermatrix/mul_* [ RetryOnFailure ] -crbug.com/1085222 [ linux intel-0x3e92 ] deqp/functional/gles3/shadermatrix/add_* [ RetryOnFailure ] -crbug.com/1085222 [ linux intel-0x5912 ] deqp/functional/gles3/shaderoperator/binary_operator_* [ RetryOnFailure ] -crbug.com/1085222 [ linux intel-0x5912 ] deqp/functional/gles3/shadermatrix/sub_* [ RetryOnFailure ] -crbug.com/1085222 [ linux intel-0x5912 ] deqp/functional/gles3/shadermatrix/mul_* [ RetryOnFailure ] -crbug.com/1085222 [ linux intel-0x5912 ] deqp/functional/gles3/shadermatrix/add_* [ RetryOnFailure ] crbug.com/1085222 [ catalina intel-0xa2e ] deqp/functional/gles3/shaderoperator/binary_operator_* [ RetryOnFailure ] crbug.com/1085222 [ catalina intel-0xa2e ] deqp/functional/gles3/shaderoperator/unary_operator_* [ RetryOnFailure ] @@ -208,72 +177,22 @@ crbug.com/1127867 [ win angle-d3d11 ] conformance2/textures/image_data/tex-3d-rgb565-rgb-unsigned_byte.html [ RetryOnFailure ] # Intel flaky issues -crbug.com/1122744 [ win angle-d3d11 intel ] conformance/textures/misc/texparameter-test.html [ RetryOnFailure ] -crbug.com/912579 [ angle-opengl win passthrough intel ] conformance2/rendering/out-of-bounds-index-buffers-after-copying.html [ RetryOnFailure ] crbug.com/1114780 [ win intel ] deqp/functional/gles3/multisample.html [ Skip ] -crbug.com/1127867 [ win angle-d3d11 intel ] conformance2/textures/image_data/tex-3d-r16f-red-half_float.html [ RetryOnFailure ] # Flakily times out on driver 26.20.100.8141. -crbug.com/1093482 [ win10 intel-0x3e92 ] deqp/functional/gles3/shadermatrix/div_dynamic.html [ RetryOnFailure ] crbug.com/1093482 [ win10 intel-0x5912 ] deqp/functional/gles3/shadermatrix/div_dynamic.html [ RetryOnFailure ] crbug.com/1093482 [ win10 intel-0x3e92 ] deqp/functional/gles3/shadermatrix/sub_dynamic.html [ RetryOnFailure ] -crbug.com/1093482 [ win10 intel-0x5912 ] deqp/functional/gles3/shadermatrix/sub_dynamic.html [ RetryOnFailure ] - -# Intel failed issues -crbug.com/angleproject/2994 [ angle-opengl win passthrough intel ] conformance2/textures/misc/copy-texture-image-same-texture.html [ Failure ] -crbug.com/1042246 [ angle-opengl win passthrough intel ] conformance2/extensions/ext-texture-norm16.html [ Skip ] - -# Intel driver issues -crbug.com/795030 [ win intel angle-opengl passthrough intel_lt_27.20.100.8280 ] deqp/functional/gles3/shadercommonfunction.html [ Failure ] -crbug.com/602688 [ win intel angle-opengl passthrough intel_lt_26.20.100.7870 ] conformance2/glsl3/vector-dynamic-indexing.html [ Failure ] -crbug.com/1082565 [ win intel angle-opengl passthrough intel_lt_26.20.100.8141 ] conformance/canvas/webgl-to-2d-canvas.html [ Failure ] - -# This case causes no-over-optimization-on-uniform-array fail. -crbug.com/884210 [ angle-opengl win passthrough intel ] conformance/ogles/GL/gl_FragCoord/gl_FragCoord_001_to_003.html [ Skip ] - -crbug.com/602688 [ angle-opengl win passthrough intel intel_lt_25.20.100.6577 ] conformance/glsl/constructors/glsl-construct-mat2.html [ Failure ] -crbug.com/602688 [ angle-opengl win passthrough intel intel_lt_25.20.100.6577 ] conformance2/textures/misc/texture-npot.html [ Failure ] -crbug.com/854100 [ angle-opengl win passthrough intel intel_lt_25.20.100.6577 ] conformance/glsl/variables/gl-pointcoord.html [ Failure ] -crbug.com/957631 [ angle-opengl win passthrough intel intel_lt_25.20.100.6577 ] conformance2/rendering/element-index-uint.html [ Failure ] -crbug.com/angleproject/2880 [ angle-opengl win passthrough intel intel_lt_25.20.100.6577 ] deqp/functional/gles3/shaderbuiltinvar.html [ Failure ] - -# This is an OpenGL driver bug on Intel platform and it is fixed in -# Intel Driver 25.20.100.6444. -# Case no-over-optimization-on-uniform-array-08 always fail if run -# case gl-min-uniforms first. -# Temporarily skip these two cases now. -crbug.com/953243 [ angle-opengl win passthrough intel intel_lt_25.20.100.6444 ] conformance/limits/gl-min-uniforms.html [ Skip ] -crbug.com/953243 [ angle-opengl win passthrough intel intel_lt_25.20.100.6444 ] conformance/uniforms/no-over-optimization-on-uniform-array-08.html [ Skip ] - -# This is an OpenGL driver bug on Intel platform and it is fixed in -# Intel Driver 25.20.100.6444. -# Case no-over-optimization-on-uniform-array-09 always fail if run -# case biuDepthRange_001_to_002 first. -# Temporarily skip these two cases now because this issue blocks -# WEBGL_video_texture implementation. -crbug.com/907195 [ angle-opengl win passthrough intel intel_lt_25.20.100.6444 ] conformance/ogles/GL/biuDepthRange/biuDepthRange_001_to_002.html [ Skip ] -crbug.com/907195 [ angle-opengl win passthrough intel intel_lt_25.20.100.6444 ] conformance/uniforms/no-over-optimization-on-uniform-array-09.html [ Skip ] - -# TODO(crbug.com/1000354): Remove when angle workaround is applied to win angle-opengles -crbug.com/1000354 [ win angle-opengles ] conformance2/extensions/ext-texture-norm16.html [ Skip ] # Windows only. crbug.com/736926 [ win ] conformance2/textures/svg_image/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html [ RetryOnFailure ] -crbug.com/angleproject/3033 [ win no-passthrough ] conformance2/textures/misc/generate-mipmap-with-large-base-level.html [ Failure ] crbug.com/angleproject/1465 [ win angle-d3d11 ] conformance2/glsl3/tricky-loop-conditions.html [ Failure ] # Win / NVidia -crbug.com/679639 [ angle-d3d11 win nvidia ] conformance2/rendering/draw-with-integer-texture-base-level.html [ Failure ] -# Flake seen once. -crbug.com/691951 [ angle-d3d11 win nvidia ] deqp/functional/gles3/shaderoperator/binary_operator_11.html [ RetryOnFailure ] -crbug.com/735464 [ angle-d3d11 win nvidia ] deqp/functional/gles3/textureshadow/* [ RetryOnFailure ] -crbug.com/907544 [ angle-vulkan win passthrough nvidia ] conformance/uniforms/uniform-default-values.html [ RetryOnFailure ] # Related to either upgrade to Windows 10 1909 or driver 451.48 crbug.com/1106078 [ angle-d3d11 win nvidia-0x1cb3 ] deqp/functional/gles3/shadertexturefunction/texturesize.html [ Failure ] crbug.com/1106076 [ angle-d3d11 win nvidia-0x1cb3 ] conformance2/textures/misc/tex-3d-mipmap-levels-intel-bug.html [ Failure ] crbug.com/1106076 [ angle-d3d11 win nvidia-0x1cb3 ] conformance2/textures/misc/tex-mipmap-levels.html [ Failure ] # Win / NVIDIA Quadro P400 / D3D11 flaky failures -crbug.com/680754 [ angle-d3d11 win nvidia-0x1cb3 ] deqp/data/gles3/shaders/functions.html [ Failure ] crbug.com/921052 [ angle-d3d11 win nvidia-0x1cb3 ] deqp/functional/gles3/framebufferblit/depth_stencil.html [ Failure ] crbug.com/1054795 [ angle-d3d11 win7 nvidia-0x1cb3 ] deqp/functional/gles3/transformfeedback/basic_types_interleaved_triangles.html [ Failure ] crbug.com/1054795 [ angle-d3d11 win7 nvidia-0x1cb3 ] deqp/functional/gles3/transformfeedback/basic_types_separate_triangles.html [ Failure ] @@ -281,36 +200,16 @@ crbug.com/1054795 [ angle-d3d11 win7 nvidia-0x1cb3 ] deqp/functional/gles3/transformfeedback/random_separate_triangles.html [ Failure ] crbug.com/1054795 [ angle-d3d11 win7 nvidia-0x1cb3 ] deqp/functional/gles3/transformfeedback/interpolation_flat.html [ Failure ] crbug.com/966143 [ angle-d3d11 win7 nvidia-0x1cb3 ] conformance/attribs/gl-vertex-attrib-unconsumed-out-of-bounds.html [ RetryOnFailure ] -crbug.com/966143 [ angle-d3d11 win7 nvidia-0x1cb3 ] conformance/attribs/gl-vertex-attrib-zero-issues.html [ RetryOnFailure ] -crbug.com/728670 [ angle-d3d11 win nvidia-0x1cb3 ] conformance/extensions/oes-texture-half-float-with-video.html [ RetryOnFailure ] crbug.com/728670 [ angle-d3d11 win nvidia-0x1cb3 ] conformance/textures/image_bitmap_from_video/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html [ RetryOnFailure ] crbug.com/728670 [ angle-d3d11 win nvidia-0x1cb3 ] conformance/textures/image_bitmap_from_video/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html [ RetryOnFailure ] crbug.com/728670 [ angle-d3d11 win nvidia-0x1cb3 ] conformance2/textures/video/* [ RetryOnFailure ] crbug.com/728670 [ angle-d3d11 win nvidia-0x1cb3 ] conformance2/textures/image_bitmap_from_video/* [ RetryOnFailure ] # Win / NVIDIA GeForce GTX 1660 / D3D11 flaky failures -crbug.com/angleproject/4377 [ angle-d3d11 win nvidia-0x2184 ] conformance/attribs/gl-vertex-attrib-unconsumed-out-of-bounds.html [ RetryOnFailure ] -crbug.com/1057635 [ angle-d3d11 win nvidia-0x2184 ] deqp/functional/gles3/framebufferblit/depth_stencil.html [ RetryOnFailure ] crbug.com/1073613 [ angle-d3d11 win nvidia-0x2184 ] conformance2/textures/misc/tex-3d-mipmap-levels-intel-bug.html [ Failure ] crbug.com/1073613 [ angle-d3d11 win nvidia-0x2184 ] conformance2/textures/misc/tex-mipmap-levels.html [ Failure ] crbug.com/1073613 [ angle-d3d11 win nvidia-0x2184 ] deqp/functional/gles3/shadertexturefunction/texturesize.html [ Failure ] -# WIN / OpenGL / NVIDIA failures -# crbug.com/963205 [ win nvidia angle-opengl passthrough ] conformance/extensions/s3tc-and-rgtc.html [ RetryOnFailure ] -crbug.com/963205 [ win nvidia angle-opengl passthrough ] conformance/extensions/webgl-compressed-texture-s3tc-srgb.html [ RetryOnFailure ] -crbug.com/715001 [ angle-opengl win nvidia ] conformance/limits/gl-max-texture-dimensions.html [ Failure ] -crbug.com/703779 [ angle-opengl win nvidia ] conformance/textures/misc/texture-size.html [ Failure ] -crbug.com/921055 [ angle-opengl win passthrough nvidia-0x1cb3 ] conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb9_e5-rgb-float.html [ RetryOnFailure ] -crbug.com/905003 [ angle-opengl win passthrough nvidia ] conformance2/textures/misc/integer-cubemap-specification-order-bug.html [ Failure ] -crbug.com/887578 [ angle-opengl win passthrough nvidia ] deqp/data/gles3/shaders/conversions.html [ RetryOnFailure ] -crbug.com/965648 [ angle-opengl win passthrough nvidia-0x1cb3 ] deqp/functional/gles3/shaderstruct.html [ RetryOnFailure ] -crbug.com/822733 [ angle-opengl win nvidia-0x1cb3 ] deqp/functional/gles3/transformfeedback/* [ RetryOnFailure ] -crbug.com/1060024 [ angle-opengl win passthrough nvidia ] deqp/functional/gles3/shaderloop_do_while.html [ RetryOnFailure ] -crbug.com/1060024 [ angle-opengl win passthrough nvidia ] deqp/functional/gles3/shaderloop_for.html [ RetryOnFailure ] -crbug.com/1060024 [ angle-opengl win passthrough nvidia ] deqp/functional/gles3/shaderloop_while.html [ RetryOnFailure ] -crbug.com/angleproject/4555 [ win angle-opengl passthrough nvidia ] conformance/misc/type-conversion-test.html [ Skip ] - - # Win / AMD # Recently many tests have become flaky on this configuration, returning @@ -325,24 +224,10 @@ crbug.com/844483 [ angle-d3d11 win amd ] conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb9_e5-rgb-half_float.html [ Skip ] crbug.com/844483 [ angle-d3d11 win amd ] deqp/functional/gles3/texturefiltering/2d_array_combinations_05.html [ Skip ] crbug.com/483282 [ angle-d3d11 win amd ] conformance2/rendering/blitframebuffer-stencil-only.html [ Failure ] -crbug.com/828984 [ angle-d3d11 win amd ] deqp/functional/gles3/draw/draw_arrays_instanced.html [ RetryOnFailure ] -crbug.com/828984 [ angle-d3d11 win amd ] deqp/functional/gles3/draw/draw_elements.html [ RetryOnFailure ] -crbug.com/828984 [ angle-d3d11 win amd ] deqp/functional/gles3/draw/draw_range_elements.html [ RetryOnFailure ] -crbug.com/828984 [ angle-d3d11 win amd ] deqp/functional/gles3/draw/random.html [ RetryOnFailure ] -crbug.com/828984 [ angle-d3d11 win amd ] deqp/functional/gles3/samplerobject.html [ RetryOnFailure ] -crbug.com/828984 [ angle-d3d11 win amd ] deqp/functional/gles3/textureshadow/2d_array_nearest_mipmap_linear_less.html [ RetryOnFailure ] -crbug.com/828984 [ angle-d3d11 win amd ] conformance/glsl/bugs/logic-inside-block-without-braces.html [ RetryOnFailure ] -crbug.com/828984 [ angle-d3d11 win amd ] conformance/glsl/functions/glsl-function-mod-float.html [ RetryOnFailure ] crbug.com/828984 [ angle-d3d11 win amd ] conformance/renderbuffers/depth-renderbuffer-initialization.html [ RetryOnFailure ] -crbug.com/828984 [ angle-d3d11 win amd ] conformance/renderbuffers/renderbuffer-initialization.html [ RetryOnFailure ] -crbug.com/828984 [ angle-d3d11 win amd ] conformance2/glsl3/vector-dynamic-indexing.html [ RetryOnFailure ] crbug.com/828984 [ angle-d3d11 win amd ] conformance2/textures/canvas_sub_rectangle/tex-2d-rgb9_e5-rgb-half_float.html [ RetryOnFailure ] crbug.com/828984 [ angle-d3d11 win amd ] conformance2/textures/canvas_sub_rectangle/tex-2d-rgb9_e5-rgb-float.html [ RetryOnFailure ] -crbug.com/828984 [ angle-d3d11 win amd ] conformance2/textures/canvas_sub_rectangle/tex-2d-rgb32f-rgb-float.html [ RetryOnFailure ] crbug.com/844483 [ angle-d3d11 win amd ] conformance2/textures/canvas_sub_rectangle/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html [ RetryOnFailure ] -crbug.com/828984 [ angle-d3d11 win amd ] conformance2/textures/misc/copy-texture-image-webgl-specific.html [ RetryOnFailure ] -crbug.com/878780 [ win amd ] conformance2/textures/webgl_canvas/* [ RetryOnFailure ] -crbug.com/992457 [ win amd ] conformance2/textures/canvas_sub_rectangle/tex-2d-srgb8-rgb-unsigned_byte.html [ RetryOnFailure ] # Recent AMD drivers seem to have a regression with 3D textures. # (Some of these tests seem to occasionally pass unexpectedly.) @@ -357,16 +242,10 @@ crbug.com/angleproject/2424 [ angle-d3d11 win amd ] deqp/functional/gles3/texturespecification/basic_texsubimage3d_* [ Failure ] crbug.com/angleproject/2424 [ angle-d3d11 win amd ] deqp/functional/gles3/texturespecification/teximage3d_pbo_3d* [ Failure ] crbug.com/angleproject/2424 [ angle-d3d11 win amd ] deqp/functional/gles3/texturespecification/teximage3d_unpack_params.html [ Failure ] -crbug.com/angleproject/2424 [ angle-d3d11 win amd ] deqp/functional/gles3/texturespecification/texsubimage3d_unpack_params.html [ Failure ] # AMD texture handling has become flaky. crbug.com/1110951 [ angle-d3d11 win amd ] conformance/textures/misc/texture-sub-image-cube-maps.html [ RetryOnFailure ] -# Have seen this time out. Think it may be because it's currently -# the first test that runs in the shard, and the browser might not -# be coming up correctly. -crbug.com/687374 [ win amd-0x6613 ] deqp/functional/gles3/multisample.html [ RetryOnFailure ] - # Failing on AMD RX 5500 XT crbug.com/1152597 [ win amd-0x7340 angle-d3d11 ] conformance/renderbuffers/framebuffer-state-restoration.html [ Failure ] crbug.com/1152599 [ win amd-0x7340 angle-d3d11 ] conformance/rendering/polygon-offset.html [ Failure ] @@ -382,7 +261,6 @@ # D3D11 / AMD RX 5500 XT / Passthrough command decoder crbug.com/1159539 [ win amd-0x7340 angle-d3d11 passthrough ] deqp/functional/gles3/fbodepthbuffer.html [ RetryOnFailure ] crbug.com/1159539 [ win amd-0x7340 angle-d3d11 passthrough ] deqp/functional/gles3/fborender/resize_03.html [ RetryOnFailure ] -crbug.com/1159539 [ win amd-0x7340 angle-d3d11 passthrough ] deqp/functional/gles3/fborender/recreate_color_00.html [ RetryOnFailure ] crbug.com/1159539 [ win amd-0x7340 angle-d3d11 passthrough ] deqp/functional/gles3/fborender/recreate_color_01.html [ RetryOnFailure ] crbug.com/1159539 [ win amd-0x7340 angle-d3d11 passthrough ] deqp/functional/gles3/fborender/recreate_color_04.html [ RetryOnFailure ] crbug.com/1159539 [ win amd-0x7340 angle-d3d11 passthrough ] deqp/functional/gles3/fborender/recreate_color_05.html [ RetryOnFailure ] @@ -390,10 +268,6 @@ # Flaky on AMD Win7 crbug.com/989050 [ angle-d3d11 win7 amd ] conformance2/textures/misc/tex-unpack-params-imagedata.html [ RetryOnFailure ] -# Passthrough command decoder / OpenGL / Windows -crbug.com/835364 [ angle-opengl win passthrough nvidia ] deqp/functional/gles3/fbocompleteness.html [ Failure ] -crbug.com/835364 [ angle-opengl win passthrough ] conformance/renderbuffers/depth-renderbuffer-initialization.html [ RetryOnFailure ] - # Passthrough command decoder / Linux / OpenGL / NVIDIA crbug.com/766918 [ angle-opengl linux passthrough nvidia ] conformance2/textures/image_bitmap_from_video/* [ RetryOnFailure ] crbug.com/965648 [ angle-opengl linux passthrough nvidia ] deqp/functional/gles3/shaderstruct.html [ RetryOnFailure ] @@ -408,28 +282,11 @@ # Flakes heavily on many OpenGL configurations crbug.com/832238 [ mac angle-disabled ] conformance2/transform_feedback/too-small-buffers.html [ Failure ] -# Regressions in 10.12.4. -crbug.com/705865 [ sierra intel ] conformance2/textures/misc/tex-base-level-bug.html [ Failure ] -crbug.com/705865 [ sierra intel no-passthrough ] conformance2/textures/misc/tex-mipmap-levels.html [ Failure ] - -# Regressions in 10.13 -crbug.com/774826 [ highsierra intel-0xa2e no-passthrough ] deqp/functional/gles3/fbocolorbuffer/tex2d_00.html [ Failure ] -crbug.com/774826 [ mojave intel-0xa2e no-passthrough ] deqp/functional/gles3/fbocolorbuffer/tex2d_00.html [ Failure ] -crbug.com/774826 [ highsierra intel-0xa2e no-passthrough ] deqp/functional/gles3/fboinvalidate/format_00.html [ Failure ] -crbug.com/774826 [ mojave intel-0xa2e no-passthrough ] deqp/functional/gles3/fboinvalidate/format_00.html [ Failure ] -crbug.com/774826 [ highsierra intel-0xa2e no-passthrough ] deqp/functional/gles3/framebufferblit/default_framebuffer_05.html [ Failure ] -crbug.com/774826 [ mojave intel-0xa2e no-passthrough ] deqp/functional/gles3/framebufferblit/default_framebuffer_05.html [ Failure ] -crbug.com/774827 [ highsierra nvidia-0xfe9 ] conformance2/glsl3/array-assign.html [ Failure ] -crbug.com/774827 [ mojave nvidia-0xfe9 ] conformance2/glsl3/array-assign.html [ Failure ] -crbug.com/774827 [ highsierra nvidia-0xfe9 ] deqp/functional/gles3/fborender/resize_03.html [ Failure ] +# Regressed in 10.13, still fails in 10.14 crbug.com/774827 [ mojave nvidia-0xfe9 ] deqp/functional/gles3/fborender/resize_03.html [ Failure ] -crbug.com/774827 [ highsierra nvidia-0xfe9 ] deqp/functional/gles3/shaderindexing/mat_00.html [ Failure ] crbug.com/774827 [ mojave nvidia-0xfe9 ] deqp/functional/gles3/shaderindexing/mat_00.html [ Failure ] -crbug.com/774827 [ highsierra nvidia-0xfe9 ] deqp/functional/gles3/shaderindexing/mat_02.html [ Failure ] crbug.com/774827 [ mojave nvidia-0xfe9 ] deqp/functional/gles3/shaderindexing/mat_02.html [ Failure ] -crbug.com/774827 [ highsierra nvidia-0xfe9 ] deqp/functional/gles3/texturespecification/teximage2d_pbo_cube_00.html [ Failure ] crbug.com/774827 [ mojave nvidia-0xfe9 ] deqp/functional/gles3/texturespecification/teximage2d_pbo_cube_00.html [ Failure ] -crbug.com/905003 [ sierra intel-0xa2e ] conformance2/textures/misc/integer-cubemap-specification-order-bug.html [ Failure ] # Fails on multiple GPU types. crbug.com/844311 [ mac ] conformance/glsl/misc/fragcolor-fragdata-invariant.html [ Failure ] @@ -447,19 +304,11 @@ crbug.com/728271 [ mac nvidia-0xfe9 ] deqp/functional/gles3/shaderindexing/tmp.html [ Failure ] crbug.com/641209 [ mac nvidia-0xfe9 ] deqp/functional/gles3/fbomultisample* [ Failure ] crbug.com/483282 [ mac nvidia-0xfe9 ] deqp/functional/gles3/framebufferblit/default_framebuffer_04.html [ Failure ] -crbug.com/483282 [ mac nvidia-0xfe9 ] conformance/attribs/gl-disabled-vertex-attrib.html [ Failure ] -crbug.com/483282 [ mac nvidia-0xfe9 ] conformance/extensions/webgl-compressed-texture-size-limit.html [ RetryOnFailure ] crbug.com/996344 [ mac nvidia-0xfe9 ] conformance/glsl/bugs/vector-scalar-arithmetic-inside-loop.html [ Failure ] -crbug.com/483282 [ mac nvidia-0xfe9 ] conformance/programs/gl-bind-attrib-location-long-names-test.html [ Failure ] -crbug.com/483282 [ mac nvidia-0xfe9 ] conformance/programs/gl-bind-attrib-location-test.html [ Failure ] -crbug.com/483282 [ mac nvidia-0xfe9 no-passthrough ] conformance2/glsl3/loops-with-side-effects.html [ Failure ] -crbug.com/981122 [ mac nvidia-0xfe9 ] conformance2/rendering/framebuffer-completeness-draw-framebuffer.html [ RetryOnFailure ] crbug.com/996344 [ mac nvidia-0xfe9 ] conformance2/textures/misc/tex-base-level-bug.html [ Failure ] crbug.com/483282 [ angle-disabled mac nvidia-0xfe9 ] conformance2/textures/misc/tex-input-validation.html [ Failure ] crbug.com/996344 [ mac nvidia-0xfe9 no-passthrough ] conformance2/textures/misc/tex-mipmap-levels.html [ Failure ] -crbug.com/682834 [ mac nvidia-0xfe9 ] conformance2/textures/image_bitmap_from_video/tex-2d-rgba16f-rgba-half_float.html [ RetryOnFailure ] crbug.com/784817 [ mac nvidia-0xfe9 ] conformance/glsl/bugs/init-array-with-loop.html [ Failure ] -crbug.com/716652 [ sierra nvidia-0xfe9 ] deqp/functional/gles3/draw/random.html [ Failure ] crbug.com/483282 [ mac nvidia-0xfe9 ] deqp/functional/gles3/framebufferblit/conversion_04.html [ Failure ] crbug.com/483282 [ mac nvidia-0xfe9 ] deqp/functional/gles3/framebufferblit/conversion_07.html [ Failure ] crbug.com/483282 [ mac nvidia-0xfe9 no-passthrough ] deqp/functional/gles3/framebufferblit/conversion_08.html [ Failure ] @@ -473,23 +322,6 @@ crbug.com/483282 [ mac nvidia-0xfe9 ] deqp/functional/gles3/framebufferblit/conversion_32.html [ Failure ] crbug.com/483282 [ mac nvidia-0xfe9 ] deqp/functional/gles3/framebufferblit/conversion_34.html [ Failure ] crbug.com/483282 [ mac nvidia-0xfe9 ] deqp/functional/gles3/pixelbufferobject.html [ Failure ] -crbug.com/483282 [ mac nvidia-0xfe9 ] deqp/functional/gles3/negativevertexarrayapi.html [ Failure ] -crbug.com/483282 [ mac nvidia-0xfe9 ] deqp/functional/gles3/shaderindexing/varying.html [ Failure ] -crbug.com/614174 [ mac nvidia-0xfe9 ] deqp/functional/gles3/texturespecification/teximage2d_pbo_2d_00.html [ Failure ] -crbug.com/614174 [ mac nvidia-0xfe9 ] deqp/functional/gles3/texturespecification/teximage2d_pbo_2d_01.html [ Failure ] -crbug.com/614174 [ mac nvidia-0xfe9 ] deqp/functional/gles3/texturespecification/texsubimage2d_pbo_2d_00.html [ Failure ] -crbug.com/614174 [ mac nvidia-0xfe9 ] deqp/functional/gles3/texturespecification/texsubimage2d_pbo_2d_01.html [ Failure ] -crbug.com/614174 [ mac nvidia-0xfe9 ] deqp/functional/gles3/texturespecification/texsubimage2d_pbo_cube_00.html [ Failure ] -crbug.com/614174 [ mac nvidia-0xfe9 ] deqp/functional/gles3/texturespecification/texsubimage2d_pbo_cube_01.html [ Failure ] -crbug.com/614174 [ mac nvidia-0xfe9 ] deqp/functional/gles3/texturespecification/texsubimage2d_pbo_cube_02.html [ Failure ] -crbug.com/614174 [ mac nvidia-0xfe9 ] deqp/functional/gles3/texturespecification/texsubimage2d_pbo_cube_03.html [ Failure ] -crbug.com/614174 [ mac nvidia-0xfe9 ] deqp/functional/gles3/texturespecification/texsubimage2d_pbo_cube_04.html [ Failure ] -crbug.com/614174 [ mac nvidia-0xfe9 ] deqp/functional/gles3/texturespecification/teximage3d_pbo_2d_array_00.html [ Failure ] -crbug.com/614174 [ mac nvidia-0xfe9 ] deqp/functional/gles3/texturespecification/teximage3d_pbo_2d_array_01.html [ Failure ] -crbug.com/614174 [ mac nvidia-0xfe9 ] deqp/functional/gles3/texturespecification/teximage3d_pbo_3d_00.html [ Failure ] -crbug.com/614174 [ mac nvidia-0xfe9 ] deqp/functional/gles3/texturespecification/teximage3d_pbo_3d_01.html [ Failure ] -crbug.com/614174 [ mac nvidia-0xfe9 ] deqp/functional/gles3/texturespecification/texsubimage3d_pbo_3d_00.html [ Failure ] -crbug.com/614174 [ mac nvidia-0xfe9 ] deqp/functional/gles3/texturespecification/texsubimage3d_pbo_3d_01.html [ Failure ] crbug.com/483282 [ mac nvidia-0xfe9 ] deqp/functional/gles3/fragmentoutput/array.fixed.html [ Failure ] crbug.com/483282 [ mac nvidia-0xfe9 ] deqp/functional/gles3/fragmentoutput/basic.fixed.html [ Failure ] crbug.com/483282 [ mac nvidia-0xfe9 ] deqp/functional/gles3/fragmentoutput/random_00.html [ Failure ] @@ -501,42 +333,24 @@ crbug.com/483282 [ mac nvidia-0xfe9 ] deqp/functional/gles3/fbocolorbuffer/tex3d_05.html [ Failure ] crbug.com/483282 [ mac nvidia-0xfe9 ] deqp/functional/gles3/fbocolorbuffer/texcube_05.html [ Failure ] crbug.com/483282 [ mac nvidia-0xfe9 ] deqp/functional/gles3/fbocolorbuffer/blend.html [ Failure ] -crbug.com/483282 [ mac nvidia-0xfe9 ] deqp/functional/gles3/draw/draw_arrays.html [ Failure ] -crbug.com/483282 [ mac nvidia-0xfe9 ] deqp/functional/gles3/draw/draw_arrays_instanced.html [ Failure ] -crbug.com/483282 [ mac nvidia-0xfe9 ] deqp/functional/gles3/draw/draw_elements.html [ Failure ] -crbug.com/483282 [ mac nvidia-0xfe9 ] deqp/functional/gles3/draw/draw_elements_instanced.html [ Failure ] -crbug.com/483282 [ mac nvidia-0xfe9 ] deqp/functional/gles3/draw/draw_range_elements.html [ Failure ] crbug.com/483282 [ mac nvidia-0xfe9 no-passthrough ] deqp/functional/gles3/fboinvalidate/format_02.html [ Failure ] crbug.com/483282 [ mac nvidia-0xfe9 ] deqp/functional/gles3/negativeshaderapi.html [ Failure ] -crbug.com/483282 [ mac nvidia-0xfe9 ] deqp/functional/gles3/vertexarrays/multiple_attributes.output.html [ RetryOnFailure ] -crbug.com/984588 [ mac nvidia-0xfe9 ] deqp/functional/gles3/framebufferblit/conversion_06.html [ Failure ] -crbug.com/984588 [ mac nvidia-0xfe9 ] deqp/functional/gles3/framebufferblit/conversion_21.html [ Failure ] -crbug.com/984588 [ mac nvidia-0xfe9 ] deqp/functional/gles3/framebufferblit/conversion_26.html [ Failure ] crbug.com/654187 [ mac nvidia-0xfe9 ] deqp/functional/gles3/framebufferblit/conversion_28.html [ Failure ] crbug.com/654187 [ mac nvidia-0xfe9 ] deqp/functional/gles3/framebufferblit/conversion_30.html [ Failure ] crbug.com/654187 [ mac nvidia-0xfe9 no-passthrough ] deqp/functional/gles3/framebufferblit/conversion_31.html [ Failure ] crbug.com/654187 [ mac nvidia-0xfe9 ] deqp/functional/gles3/framebufferblit/conversion_33.html [ Failure ] crbug.com/795052 [ mac nvidia-0xfe9 ] conformance2/uniforms/draw-with-uniform-blocks.html [ Failure ] -crbug.com/911772 [ mac nvidia-0xfe9 ] conformance2/glsl3/compound-assignment-type-combination.html [ RetryOnFailure ] -crbug.com/911772 [ mac nvidia-0xfe9 ] conformance2/query/occlusion-query.html [ RetryOnFailure ] -crbug.com/911772 [ mac nvidia-0xfe9 ] conformance2/state/gl-object-get-calls.html [ RetryOnFailure ] -crbug.com/911772 [ mac nvidia-0xfe9 ] conformance2/textures/canvas/tex-3d-r16f-red-half_float.html [ RetryOnFailure ] crbug.com/929398 [ mac nvidia-0xfe9 no-passthrough ] conformance2/glsl3/tricky-loop-conditions.html [ Failure ] -crbug.com/952282 [ mac nvidia-0xfe9 ] conformance2/rendering/framebuffer-unsupported.html [ RetryOnFailure ] -crbug.com/965209 [ mac nvidia-0xfe9 ] conformance2/samplers/multi-context-sampler-test.html [ RetryOnFailure ] crbug.com/756537 [ mac nvidia ] deqp/functional/gles3/shaderoperator/* [ Failure ] -crbug.com/907599 [ mac nvidia debug ] conformance/textures/video/tex-2d-rgb-rgb-unsigned_short_5_6_5.html [ RetryOnFailure ] -crbug.com/1022831 [ mac nvidia-0xfe9 ] deqp/functional/gles3/vertexarrays/single_attribute.usage.stream_draw.html [ RetryOnFailure ] -crbug.com/1022831 [ mac nvidia-0xfe9 ] deqp/functional/gles3/vertexarrays/single_attribute.usage.dynamic_copy.html [ RetryOnFailure ] -crbug.com/1022831 [ mac nvidia-0xfe9 ] deqp/functional/gles3/shaderloop_while.html [ RetryOnFailure ] crbug.com/1027534 [ mac nvidia-0xfe9 ] conformance2/rendering/uniform-block-buffer-size.html [ Failure ] -crbug.com/1027776 [ mac nvidia-0xfe9 ] deqp/data/gles3/shaders/conversions.html [ Failure ] crbug.com/1027776 [ mac nvidia-0xfe9 ] conformance2/rendering/framebuffer-texture-level1.html [ Failure ] crbug.com/1037650 [ mac nvidia-0xfe9 ] conformance2/textures/canvas_sub_rectangle/* [ RetryOnFailure ] crbug.com/1073538 [ mac nvidia-0xfe9 ] deqp/functional/gles3/shadermatrix/div_dynamic.html [ RetryOnFailure ] crbug.com/1086194 [ mac nvidia-0xfe9 ] conformance/textures/canvas_sub_rectangle/* [ RetryOnFailure ] crbug.com/1136231 [ mac nvidia-0xfe9 ] conformance/extensions/s3tc-and-rgtc.html [ Failure ] +crbug.com/772651 [ mac nvidia ] conformance/glsl/bugs/vector-scalar-arithmetic-inside-loop-complex.html [ Failure ] + # Mac AMD # AMD Radeon HD 8870M (1002:6821) # TODO(kbr): uncomment the following two exepectations after test @@ -580,15 +394,11 @@ crbug.com/1027605 [ mac amd-0x6821 no-passthrough ] deqp/functional/gles3/transformfeedback/random_separate_lines.html [ RetryOnFailure ] crbug.com/1027605 [ mac amd-0x6821 no-passthrough ] deqp/functional/gles3/transformfeedback/random_separate_points.html [ RetryOnFailure ] crbug.com/1027605 [ mac amd-0x6821 no-passthrough ] deqp/functional/gles3/transformfeedback/random_separate_triangles.html [ RetryOnFailure ] -crbug.com/751254 [ mac amd ] deqp/functional/gles3/shaderindexing/mat_00.html [ RetryOnFailure ] crbug.com/636648 [ mac amd ] deqp/functional/gles3/shaderindexing/mat_01.html [ RetryOnFailure ] -crbug.com/644360 [ mac amd ] deqp/functional/gles3/shaderindexing/mat_02.html [ RetryOnFailure ] crbug.com/659871 [ mac amd ] deqp/functional/gles3/shaderindexing/tmp.html [ RetryOnFailure ] crbug.com/642822 [ mac amd ] conformance2/rendering/clipping-wide-points.html [ Failure ] -crbug.com/1005593 [ mac amd ] deqp/functional/gles3/shaderstruct.html [ RetryOnFailure ] -crbug.com/1026588 [ mac amd ] deqp/functional/gles3/shaderoperator/sequence.html [ RetryOnFailure ] # Mac Intel crbug.com/886970 [ mac intel-0xa2e ] conformance/rendering/canvas-alpha-bug.html [ Failure ] @@ -604,73 +414,30 @@ crbug.com/658724 [ mac intel ] deqp/functional/gles3/framebufferblit/rect_03.html [ Failure ] crbug.com/658724 [ mac intel ] deqp/functional/gles3/framebufferblit/rect_04.html [ Failure ] crbug.com/658657 [ mac intel ] deqp/functional/gles3/texturespecification/random_teximage2d_2d.html [ Failure ] -crbug.com/1026588 [ mac intel ] deqp/functional/gles3/shaderoperator/sequence.html [ RetryOnFailure ] -crbug.com/905004 [ mac intel ] deqp/functional/gles3/shadertexturefunction/texturelod.html [ Failure ] -crbug.com/905004 [ mac intel ] deqp/functional/gles3/shadertexturefunction/texturegrad.html [ Failure ] -crbug.com/905004 [ mac intel ] deqp/functional/gles3/shadertexturefunction/textureprojgrad.html [ Failure ] -crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html [ Failure ] -crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html [ Failure ] -crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-r8ui-red_integer-unsigned_byte.html [ Failure ] -crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/image_bitmap_from_image_bitmap/tex-2d-rg8ui-rg_integer-unsigned_byte.html [ Failure ] -crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/svg_image/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html [ Failure ] -crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/svg_image/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html [ Failure ] -crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/svg_image/tex-2d-r8ui-red_integer-unsigned_byte.html [ Failure ] -crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/svg_image/tex-2d-rg8ui-rg_integer-unsigned_byte.html [ Failure ] -crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/canvas/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html [ Failure ] crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/canvas/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html [ Failure ] -crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/canvas/tex-2d-r8ui-red_integer-unsigned_byte.html [ Failure ] crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/canvas/tex-2d-rg8ui-rg_integer-unsigned_byte.html [ Failure ] -crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/image_bitmap_from_image/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html [ Failure ] -crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/image_bitmap_from_image/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html [ Failure ] -crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/image_bitmap_from_image/tex-2d-r8ui-red_integer-unsigned_byte.html [ Failure ] -crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/image_bitmap_from_image/tex-2d-rg8ui-rg_integer-unsigned_byte.html [ Failure ] -crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/image_bitmap_from_blob/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html [ Failure ] -crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/image_bitmap_from_blob/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html [ Failure ] -crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/image_bitmap_from_blob/tex-2d-r8ui-red_integer-unsigned_byte.html [ Failure ] -crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/image_bitmap_from_blob/tex-2d-rg8ui-rg_integer-unsigned_byte.html [ Failure ] crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/image_bitmap_from_video/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html [ Failure ] crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/image_bitmap_from_video/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html [ Failure ] crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/image_bitmap_from_video/tex-2d-r8ui-red_integer-unsigned_byte.html [ Failure ] crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/image_bitmap_from_video/tex-2d-rg8ui-rg_integer-unsigned_byte.html [ Failure ] -crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/image/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html [ Failure ] -crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/image/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html [ Failure ] -crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/image/tex-2d-r8ui-red_integer-unsigned_byte.html [ Failure ] -crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/image/tex-2d-rg8ui-rg_integer-unsigned_byte.html [ Failure ] -crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/webgl_canvas/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html [ Failure ] crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/webgl_canvas/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html [ Failure ] crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/webgl_canvas/tex-2d-r8ui-red_integer-unsigned_byte.html [ Failure ] crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/webgl_canvas/tex-2d-rg8ui-rg_integer-unsigned_byte.html [ Failure ] -crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/image_bitmap_from_image_data/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html [ Failure ] -crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/image_bitmap_from_image_data/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html [ Failure ] -crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/image_bitmap_from_image_data/tex-2d-r8ui-red_integer-unsigned_byte.html [ Failure ] -crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/image_bitmap_from_image_data/tex-2d-rg8ui-rg_integer-unsigned_byte.html [ Failure ] crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/video/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html [ Failure ] crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/video/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html [ Failure ] crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/video/tex-2d-r8ui-red_integer-unsigned_byte.html [ Failure ] crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/video/tex-2d-rg8ui-rg_integer-unsigned_byte.html [ Failure ] -crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/canvas_sub_rectangle/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html [ Failure ] crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/canvas_sub_rectangle/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html [ Failure ] crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/canvas_sub_rectangle/tex-2d-r8ui-red_integer-unsigned_byte.html [ Failure ] crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/canvas_sub_rectangle/tex-2d-rg8ui-rg_integer-unsigned_byte.html [ Failure ] -crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/image_data/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html [ Failure ] -crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/image_data/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html [ Failure ] -crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/image_data/tex-2d-r8ui-red_integer-unsigned_byte.html [ Failure ] -crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/image_data/tex-2d-rg8ui-rg_integer-unsigned_byte.html [ Failure ] -crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/image_bitmap_from_canvas/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html [ Failure ] crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/image_bitmap_from_canvas/tex-2d-rgba8ui-rgba_integer-unsigned_byte.html [ Failure ] -crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/image_bitmap_from_canvas/tex-2d-r8ui-red_integer-unsigned_byte.html [ Failure ] crbug.com/665197 [ mac intel-0xa2e ] conformance2/textures/image_bitmap_from_canvas/tex-2d-rg8ui-rg_integer-unsigned_byte.html [ Failure ] -crbug.com/658930 [ mac intel ] conformance2/textures/misc/integer-cubemap-texture-sampling.html [ Failure ] crbug.com/782317 [ mac intel ] conformance/rendering/rendering-stencil-large-viewport.html [ Failure ] crbug.com/1039465 [ mac intel ] conformance/textures/canvas/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html [ RetryOnFailure ] crbug.com/1018028 [ mac intel ] conformance/rendering/bind-framebuffer-flush-bug.html [ Failure ] crbug.com/1082455 [ mac intel ] conformance2/renderbuffers/multisampled-depth-renderbuffer-initialization.html [ Failure ] crbug.com/1144207 [ mac intel-0x3e9b angle-disabled ] conformance/extensions/webgl-multi-draw.html [ Failure ] -# Mac Intel No-Passthrough -crbug.com/1042011 [ mac intel-0xa2e no-passthrough ] conformance2/textures/canvas_sub_rectangle/tex-3d-r11f_g11f_b10f-rgb-half_float.html [ RetryOnFailure ] - - # Mac Passthrough crbug.com/angleproject/5223 [ mac passthrough ] conformance2/textures/misc/tex-mipmap-levels.html [ Failure ] @@ -684,7 +451,6 @@ crbug.com/982294 [ mac passthrough amd ] deqp/functional/gles3/transformfeedback/random_interleaved_points.html [ Failure ] crbug.com/982294 [ mac passthrough amd ] deqp/functional/gles3/transformfeedback/random_interleaved_triangles.html [ Failure ] - # Mac Passthrough / NVIDIA crbug.com/982294 [ mac passthrough nvidia ] conformance/renderbuffers/framebuffer-object-attachment.html [ Failure ] crbug.com/982294 [ mac passthrough nvidia ] conformance/textures/misc/tex-input-validation.html [ Failure ] @@ -729,14 +495,6 @@ crbug.com/1092734 [ mac passthrough intel ] conformance2/textures/webgl_canvas/tex-2d-rgba4-rgba-unsigned_short_4_4_4_4.html [ Failure ] crbug.com/1092734 [ mac passthrough intel ] conformance2/textures/webgl_canvas/tex-2d-rgba8-rgba-unsigned_byte.html [ Failure ] -# Mac ASAN flakes -crbug.com/1059760 [ mac asan ] conformance/textures/image_bitmap_from_video/* [ RetryOnFailure ] -crbug.com/1059760 [ mac asan no-passthrough ] conformance/textures/misc/texture-corner-case-videos.html [ RetryOnFailure ] -crbug.com/1059760 [ mac asan ] conformance/textures/video/* [ RetryOnFailure ] -crbug.com/1059760 [ mac asan ] conformance2/textures/image_bitmap_from_video/* [ RetryOnFailure ] -crbug.com/1059760 [ mac asan ] conformance2/textures/misc/tex-image-with-bad-args-from-dom-elements.html [ RetryOnFailure ] -crbug.com/1059760 [ mac asan ] conformance2/textures/video/* [ RetryOnFailure ] - # Mac ASAN slow tests crbug.com/1113404 [ mac asan ] deqp/functional/gles3/multisample.html [ Skip ] @@ -777,25 +535,16 @@ crbug.com/1130112 [ mac apple-apple-m1 ] deqp/functional/gles3/texturefiltering/cube_combinations_04.html [ Failure ] crbug.com/1130112 [ mac apple-apple-m1 ] deqp/functional/gles3/texturefiltering/cube_sizes_03.html [ Failure ] crbug.com/1130112 [ mac apple-apple-m1 ] deqp/functional/gles3/texturefiltering/cube_sizes_04.html [ Failure ] -crbug.com/1130114 [ mac apple-apple-m1 ] conformance2/extensions/ext-color-buffer-float.html [ Failure ] -crbug.com/1130117 [ mac apple-apple-m1 ] deqp/functional/gles3/fbomultisample.2_samples.html [ Failure ] -crbug.com/1130117 [ mac apple-apple-m1 ] deqp/functional/gles3/fbomultisample.4_samples.html [ Failure ] crbug.com/1130117 [ mac apple-apple-m1 no-asan ] deqp/functional/gles3/multisample.html [ Failure ] crbug.com/1130118 [ mac apple-apple-m1 ] conformance2/rendering/blitframebuffer-filter-srgb.html [ Failure ] crbug.com/1130118 [ mac apple-apple-m1 ] deqp/functional/gles3/framebufferblit/rect_03.html [ Failure ] crbug.com/1130118 [ mac apple-apple-m1 ] deqp/functional/gles3/framebufferblit/rect_04.html [ Failure ] -crbug.com/1130118 [ mac apple-apple-m1 ] deqp/functional/gles3/framebufferblit/default_framebuffer_00.html [ Failure ] crbug.com/1130119 [ mac apple-apple-m1 ] conformance2/glsl3/vector-dynamic-indexing.html [ Failure ] crbug.com/1130119 [ mac apple-apple-m1 ] conformance2/textures/misc/tex-base-level-bug.html [ Failure ] -crbug.com/1130119 [ mac apple-apple-m1 ] conformance2/textures/webgl_canvas/tex-3d-r32f-red-float.html [ RetryOnFailure ] crbug.com/1130119 [ mac apple-apple-m1 ] conformance2/rendering/framebuffer-completeness-unaffected.html [ Failure ] crbug.com/1130119 [ mac apple-apple-m1 passthrough angle-opengl ] conformance2/rendering/framebuffer-render-to-layer.html [ Failure ] crbug.com/1130119 [ mac apple-apple-m1 ] deqp/functional/gles3/fbocompleteness.html [ Failure ] -crbug.com/1130119 [ mac apple-apple-m1 ] deqp/functional/gles3/fbodepthbuffer.html [ Failure ] crbug.com/1130119 [ mac apple-apple-m1 ] deqp/functional/gles3/shadertexturefunction/texturegrad.html [ Failure ] -crbug.com/1130119 [ mac apple-apple-m1 ] deqp/functional/gles3/textureshadow/cube_linear_mipmap_linear_greater.html [ RetryOnFailure ] -crbug.com/1130119 [ mac apple-apple-m1 ] deqp/functional/gles3/textureshadow/cube_linear_mipmap_linear_less.html [ RetryOnFailure ] -crbug.com/1130119 [ mac apple-apple-m1 ] deqp/functional/gles3/texturespecification/texstorage2d_format_size.html [ RetryOnFailure ] crbug.com/1130703 [ mac apple-apple-m1 no-passthrough ] conformance/textures/misc/texture-copying-and-deletion.html [ Failure ] crbug.com/1130703 [ mac apple-apple-m1 no-passthrough ] conformance/textures/misc/texture-copying-feedback-loops.html [ Failure ] crbug.com/1130708 [ mac apple-apple-m1 no-passthrough ] conformance2/textures/canvas/tex-2d-rgb5_a1-rgba-unsigned_byte.html [ Failure ] @@ -818,55 +567,17 @@ # Mesa issues # Driver tag doesn't work on the passthrough command decoder because the detected driver version is ANGLE's version. -crbug.com/1127180 [ linux intel no-passthrough mesa_ge_20.1 ] deqp/functional/gles3/shaderindexing/tmp.html [ Failure ] -crbug.com/1127180 [ linux intel no-passthrough mesa_ge_20.1 ] deqp/data/gles3/shaders/functions.html [ Failure ] -crbug.com/1084864 [ linux intel angle-opengl passthrough ] conformance2/rendering/blitframebuffer-filter-outofbounds.html [ Failure ] crbug.com/1081978 [ linux intel angle-opengl passthrough ] conformance2/textures/misc/tex-3d-size-limit.html [ Failure ] crbug.com/angleproject/4242 [ linux intel angle-opengl passthrough ] conformance2/glsl3/matrix-row-major-dynamic-indexing.html [ Failure ] crbug.com/angleproject/4242 [ linux intel no-passthrough mesa_lt_19.1 ] conformance2/glsl3/matrix-row-major-dynamic-indexing.html [ Failure ] -# Linux only. -crbug.com/905006 [ linux nvidia ] conformance2/glsl3/vector-dynamic-indexing-nv-driver-bug.html [ Failure ] - # Linux NVIDIA -# This test is flaky both with and without ANGLE. -crbug.com/709351 [ linux nvidia ] conformance2/glsl3/vector-dynamic-indexing-swizzled-lvalue.html [ Failure ] crbug.com/905003 [ linux nvidia ] conformance2/textures/misc/integer-cubemap-specification-order-bug.html [ Failure ] -crbug.com/680278 [ angle-opengl linux nvidia ] conformance2/rendering/framebuffer-texture-level1.html [ Failure ] -# Observed flaky on Swarmed bots. Some of these were directly -# observed, some not. We can't afford any flakes on the tryservers -# so mark them all flaky. -crbug.com/780706 [ linux nvidia-0x1cb3 ] deqp/functional/gles3/transformfeedback/array_interleaved_lines.html [ RetryOnFailure ] -crbug.com/780706 [ linux nvidia-0x1cb3 ] deqp/functional/gles3/transformfeedback/array_interleaved_points.html [ RetryOnFailure ] -crbug.com/780706 [ linux nvidia-0x1cb3 ] deqp/functional/gles3/transformfeedback/array_interleaved_triangles.html [ RetryOnFailure ] -crbug.com/780706 [ linux nvidia-0x1cb3 ] deqp/functional/gles3/transformfeedback/array_separate_lines.html [ RetryOnFailure ] -crbug.com/780706 [ linux nvidia-0x1cb3 ] deqp/functional/gles3/transformfeedback/array_separate_points.html [ RetryOnFailure ] -crbug.com/780706 [ linux nvidia-0x1cb3 ] deqp/functional/gles3/transformfeedback/array_separate_triangles.html [ RetryOnFailure ] -crbug.com/780706 [ linux nvidia-0x1cb3 ] deqp/functional/gles3/transformfeedback/basic_types_interleaved_lines.html [ RetryOnFailure ] -crbug.com/780706 [ linux nvidia-0x1cb3 ] deqp/functional/gles3/transformfeedback/basic_types_interleaved_points.html [ RetryOnFailure ] -crbug.com/780706 [ linux nvidia-0x1cb3 ] deqp/functional/gles3/transformfeedback/basic_types_interleaved_triangles.html [ RetryOnFailure ] -crbug.com/780706 [ linux nvidia-0x1cb3 ] deqp/functional/gles3/transformfeedback/basic_types_separate_lines.html [ RetryOnFailure ] -crbug.com/780706 [ linux nvidia-0x1cb3 ] deqp/functional/gles3/transformfeedback/basic_types_separate_points.html [ RetryOnFailure ] -crbug.com/780706 [ linux nvidia-0x1cb3 ] deqp/functional/gles3/transformfeedback/basic_types_separate_triangles.html [ RetryOnFailure ] -crbug.com/780706 [ linux nvidia-0x1cb3 ] deqp/functional/gles3/transformfeedback/interpolation_centroid.html [ RetryOnFailure ] -crbug.com/780706 [ linux nvidia-0x1cb3 ] deqp/functional/gles3/transformfeedback/interpolation_flat.html [ RetryOnFailure ] -crbug.com/780706 [ linux nvidia-0x1cb3 ] deqp/functional/gles3/transformfeedback/interpolation_smooth.html [ RetryOnFailure ] -crbug.com/780706 [ linux nvidia-0x1cb3 ] deqp/functional/gles3/transformfeedback/point_size.html [ RetryOnFailure ] -crbug.com/780706 [ linux nvidia-0x1cb3 ] deqp/functional/gles3/transformfeedback/position.html [ RetryOnFailure ] -crbug.com/780706 [ linux nvidia-0x1cb3 ] deqp/functional/gles3/transformfeedback/random_interleaved_lines.html [ RetryOnFailure ] -crbug.com/780706 [ linux nvidia-0x1cb3 ] deqp/functional/gles3/transformfeedback/random_interleaved_points.html [ RetryOnFailure ] -crbug.com/780706 [ linux nvidia-0x1cb3 ] deqp/functional/gles3/transformfeedback/random_interleaved_triangles.html [ RetryOnFailure ] -crbug.com/780706 [ linux nvidia-0x1cb3 ] deqp/functional/gles3/transformfeedback/random_separate_lines.html [ RetryOnFailure ] -crbug.com/780706 [ linux nvidia-0x1cb3 ] deqp/functional/gles3/transformfeedback/random_separate_points.html [ RetryOnFailure ] -crbug.com/780706 [ linux nvidia-0x1cb3 ] deqp/functional/gles3/transformfeedback/random_separate_triangles.html [ RetryOnFailure ] crbug.com/906846 [ linux nvidia ] conformance2/rendering/canvas-resizing-with-pbo-bound.html [ RetryOnFailure ] # Linux NVIDIA Quadro P400, OpenGL backend -crbug.com/715001 [ linux nvidia-0x1cb3 ] conformance/limits/gl-max-texture-dimensions.html [ Failure ] -crbug.com/703779 [ angle-opengl linux nvidia-0x1cb3 ] conformance/textures/misc/texture-size.html [ Failure ] crbug.com/703779 [ angle-opengl linux nvidia-0x1cb3 ] conformance/extensions/webgl-compressed-texture-size-limit.html [ Failure ] -crbug.com/703779 [ angle-opengl linux nvidia-0x1cb3 ] conformance/textures/misc/texture-size-limit.html [ Failure ] crbug.com/703779 [ angle-opengl linux nvidia-0x1cb3 ] deqp/functional/gles3/fbocompleteness.html [ Failure ] # Linux / OpenGL / NVIDIA failures @@ -876,49 +587,10 @@ crbug.com/1115314 [ linux nvidia-0x2184 angle-opengl passthrough ] deqp/functional/gles3/fbocompleteness.html [ Failure ] # Linux AMD only. -# It looks like AMD shader compiler rejects many valid ES3 semantics. -crbug.com/766776 [ linux amd ] conformance2/attribs/gl-vertex-attrib-normalized-int.html [ Failure ] -crbug.com/981070 [ linux amd ] conformance2/glsl3/matrix-row-major.html [ Failure ] -crbug.com/709351 [ linux amd ] conformance2/glsl3/vector-dynamic-indexing-swizzled-lvalue.html [ Failure ] -crbug.com/483282 [ linux amd ] deqp/data/gles3/shaders/conversions.html [ Failure ] crbug.com/483282 [ linux amd ] deqp/data/gles3/shaders/arrays.html [ Skip ] crbug.com/483282 [ linux amd ] deqp/data/gles3/shaders/qualification_order.html [ Skip ] -crbug.com/483282 [ linux amd ] deqp/functional/gles3/samplerobject.html [ Failure ] -crbug.com/483282 [ linux amd ] deqp/functional/gles3/shaderprecision_int.html [ Failure ] -crbug.com/694877 [ linux amd ] deqp/functional/gles3/vertexarrays/single_attribute.first.html [ Failure ] -crbug.com/483282 [ linux amd ] deqp/functional/gles3/negativetextureapi.html [ Failure ] crbug.com/483282 [ linux amd ] deqp/functional/gles3/transformfeedback/array_separate* [ Failure ] -crbug.com/634525 [ linux amd ] conformance2/rendering/blitframebuffer-filter-srgb.html [ Failure ] -crbug.com/662644 [ linux amd ] conformance2/rendering/blitframebuffer-outside-readbuffer.html [ Failure ] -crbug.com/483282 [ linux amd ] conformance2/textures/misc/tex-mipmap-levels.html [ Failure ] -crbug.com/899754 [ linux amd ] conformance2/vertex_arrays/vertex-array-object-and-disabled-attributes.html [ Failure ] -crbug.com/911216 [ linux no-passthrough amd ] conformance2/textures/misc/copy-texture-image-same-texture.html [ Failure ] -crbug.com/483282 [ linux amd ] deqp/functional/gles3/texturespecification/teximage2d_depth_pbo.html [ Failure ] -crbug.com/483282 [ linux amd ] deqp/functional/gles3/draw/random.html [ Failure ] -crbug.com/483282 [ linux amd ] deqp/functional/gles3/fbomultisample* [ Failure ] -crbug.com/483282 [ linux amd ] deqp/functional/gles3/framebufferblit/conversion_07.html [ Failure ] -crbug.com/658832 [ linux amd ] deqp/functional/gles3/framebufferblit/default_framebuffer_00.html [ Failure ] crbug.com/483282 [ linux amd ] conformance2/glsl3/vector-dynamic-indexing.html [ Failure ] -crbug.com/483282 [ angle-disabled linux amd ] conformance2/reading/read-pixels-pack-parameters.html [ Failure ] -crbug.com/483282 [ angle-disabled linux amd ] conformance2/textures/misc/tex-unpack-params.html [ Failure ] -crbug.com/662644 [ linux amd ] conformance2/rendering/clipping-wide-points.html [ Failure ] - -# TODO(kbr): re-enable after next conformance roll. crbug.com/736499 -# crbug.com/633022 [ linux amd ] conformance2/extensions/ext-color-buffer-float.html [ Failure ] -crbug.com/655147 [ linux no-passthrough amd ] conformance2/rendering/blitframebuffer-filter-outofbounds.html [ Failure ] -crbug.com/705865 [ linux amd ] conformance2/textures/misc/tex-base-level-bug.html [ Failure ] -crbug.com/705865 [ linux amd ] conformance2/textures/image/tex-2d-r11f_g11f_b10f-rgb-float.html [ Failure ] - -# Uniform buffer related failures -crbug.com/483282 [ linux amd ] deqp/functional/gles3/uniformbuffers/random.html [ Failure ] -crbug.com/angleproject/5014 [ linux amd ] conformance2/uniforms/uniform-blocks-with-arrays.html [ Failure ] -crbug.com/809595 [ angle-disabled linux amd ] conformance2/uniforms/simple-buffer-change.html [ Failure ] - -# Linux AMD R7 240 -crbug.com/696345 [ angle-disabled linux amd-0x6613 ] conformance2/transform_feedback/switching-objects.html [ Failure ] -crbug.com/913301 [ linux amd-0x6613 ] conformance2/textures/misc/generate-mipmap-with-large-base-level.html [ Failure ] -crbug.com/809237 [ linux amd-0x6613 ] conformance2/uniforms/incompatible-texture-type-for-sampler.html [ Skip ] -crbug.com/1018028 [ linux amd-0x6613 ] conformance/rendering/bind-framebuffer-flush-bug.html [ Failure ] # Linux AMD RX 5500 XT crbug.com/1147232 [ linux amd-0x7340 no-passthrough ] conformance/textures/misc/texture-size-limit.html [ Skip ] @@ -937,18 +609,12 @@ [ android qualcomm ] WebglExtension_WEBGL_compressed_texture_s3tc [ Skip ] [ android qualcomm ] WebglExtension_WEBGL_compressed_texture_s3tc_srgb [ Skip ] -# Was too difficult to suppress these failures on individual bots. -crbug.com/1165751 [ android-lollipop ] conformance/glsl/bugs/vector-matrix-constructor-scalarization.html [ Failure ] -crbug.com/1165751 [ android-marshmallow ] conformance/glsl/bugs/vector-matrix-constructor-scalarization.html [ Failure ] -crbug.com/1165751 [ android-nougat ] conformance/glsl/bugs/vector-matrix-constructor-scalarization.html [ Failure ] - # Video tests are flaky. Sometimes the video is black. crbug.com/948894 [ android ] conformance/textures/video/* [ RetryOnFailure ] crbug.com/948894 [ android ] conformance/textures/image_bitmap_from_video/* [ RetryOnFailure ] crbug.com/948894 [ android ] conformance2/textures/video/* [ RetryOnFailure ] crbug.com/948894 [ android ] conformance2/textures/image_bitmap_from_video/* [ RetryOnFailure ] -crbug.com/1081973 [ android ] conformance2/textures/misc/compressed-tex-image.html [ Failure ] crbug.com/angleproject/4417 [ android ] conformance2/rendering/framebuffer-render-to-layer.html [ Failure ] # Video uploads to some texture formats new in WebGL 2.0 are @@ -974,33 +640,17 @@ crbug.com/1008535 [ android android-pixel-2 passthrough ] conformance2/textures/misc/tex-image-with-bad-args-from-dom-elements.html [ Skip ] crbug.com/1000354 [ android android-pixel-2 passthrough ] conformance2/reading/read-pixels-from-fbo-test.html [ Failure ] crbug.com/951628 [ android android-pixel-2 passthrough ] conformance/rendering/blending.html [ Failure ] -crbug.com/981216 [ android android-pixel-2 ] deqp/functional/gles3/fbocolorbuffer/tex2d_01.html [ RetryOnFailure ] -crbug.com/1022410 [ android qualcomm ] conformance2/transform_feedback/switching-objects.html [ RetryOnFailure ] crbug.com/1027125 [ android qualcomm ] deqp/functional/gles3/negativetextureapi.html [ Failure ] crbug.com/1092734 [ android android-pixel-2 passthrough ] conformance2/textures/webgl_canvas/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html [ Failure ] crbug.com/1092734 [ android android-pixel-2 passthrough ] conformance2/textures/webgl_canvas/tex-2d-rgb565-rgb-unsigned_byte.html [ Failure ] -crbug.com/1126631 [ android android-pixel-2 passthrough ] conformance2/textures/webgl_canvas/tex-2d-rgba8-rgba-unsigned_byte.html [ RetryOnFailure ] crbug.com/1126631 [ android android-pixel-2 passthrough ] conformance2/textures/webgl_canvas/tex-3d-r11f_g11f_b10f-rgb-half_float.html [ RetryOnFailure ] -crbug.com/1126631 [ android android-pixel-2 passthrough ] conformance2/textures/webgl_canvas/tex-2d-rgb9_e5-rgb-half_float.html [ RetryOnFailure ] -crbug.com/1126631 [ android android-pixel-2 passthrough ] conformance2/textures/webgl_canvas/tex-2d-r11f_g11f_b10f-rgb-unsigned_int_10f_11f_11f_rev.html [ RetryOnFailure ] -crbug.com/1126631 [ android android-pixel-2 passthrough ] conformance/textures/webgl_canvas/tex-2d-luminance-luminance-unsigned_byte.html [ RetryOnFailure ] crbug.com/1143323 [ android android-pixel-2 passthrough ] conformance/rendering/draw-arrays-out-of-bounds.html [ Failure ] -crbug.com/1154706 [ android android-pixel-2 no-passthrough ] conformance/ogles/GL/clamp/clamp_001_to_006.html [ RetryOnFailure ] # This test is failing on Android Pixel 2 and 3 (Qualcomm) # Seems to be an OpenGL ES bug. crbug.com/695742 [ android qualcomm angle-disabled ] deqp/functional/gles3/multisample.html [ RetryOnFailure ] -# This test is flaky but can fail three times in a row so it must be -# marked as Fail instead of Flaky. -crbug.com/946177 [ android qualcomm ] deqp/functional/gles3/shaderbuiltinvar.html [ Failure ] - -# Nvidia (Shield TV) failures -crbug.com/906752 [ android nvidia ] conformance2/glsl3/array-complex-indexing.html [ Failure ] -crbug.com/874620 [ android nvidia ] conformance2/glsl3/const-struct-from-array-as-function-parameter.html [ Failure ] -crbug.com/905006 [ android nvidia ] conformance2/glsl3/vector-dynamic-indexing-nv-driver-bug.html [ Failure ] - # Pixel 4 crbug.com/1175226 [ android android-pixel-4 angle-opengles passthrough ] conformance/rendering/blending.html [ Failure ] crbug.com/1175229 [ android android-pixel-4 angle-opengles passthrough ] conformance2/textures/webgl_canvas/tex-2d-rgb565-rgb-unsigned_byte.html [ Failure ] @@ -1027,24 +677,13 @@ # command decoder, simplify the RetryOnFailure expectation at the top # of this file to just not declare any OS. crbug.com/979444 [ android angle-opengles ] conformance/textures/misc/texture-corner-case-videos.html [ Failure ] -crbug.com/906724 [ android angle-opengles ] conformance/textures/video/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html [ Failure ] -crbug.com/906724 [ android angle-opengles ] conformance/textures/video/tex-2d-luminance-luminance-unsigned_byte.html [ Failure ] crbug.com/angleproject/3684 [ android angle-opengles ] conformance2/renderbuffers/multisample-with-full-sample-counts.html [ Failure ] -crbug.com/967410 [ android angle-opengles ] conformance2/textures/video/tex-2d-rgb16f-rgb-half_float.html [ Failure ] -crbug.com/967410 [ android angle-opengles ] conformance2/textures/video/tex-2d-rgb9_e5-rgb-half_float.html [ Failure ] -crbug.com/967410 [ android angle-opengles ] conformance2/textures/video/tex-2d-srgb8-rgb-unsigned_byte.html [ Failure ] -crbug.com/967410 [ android angle-opengles ] conformance2/textures/video/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html [ Failure ] crbug.com/967410 [ android angle-opengles ] conformance2/textures/misc/npot-video-sizing.html [ Failure ] crbug.com/angleproject/3685 [ android angle-opengles ] conformance2/transform_feedback/simultaneous_binding.html [ Failure ] crbug.com/angleproject/3686 [ android angle-opengles ] deqp/functional/gles3/multisample.html [ Failure ] -crbug.com/angleproject/3753 [ android angle-opengles ] conformance/textures/misc/texture-upload-size.html [ Failure ] crbug.com/1037958 [ mac amd-0x679e ] conformance2/transform_feedback/switching-objects.html [ RetryOnFailure ] -crbug.com/1103370 [ android angle-opengles no-passthrough qualcomm ] deqp/functional/gles3/fborender/recreate_color_03.html [ RetryOnFailure ] - -# Too flaky on vaidating command decoder to mark RetryOnFailure. -crbug.com/1082003 [ android angle-opengles no-passthrough qualcomm ] deqp/functional/gles3/fragdepth.html [ Failure ] # Conflicting expectations to test that the # "Expectations have no collisions" unittest works.
diff --git a/extensions/browser/event_router.h b/extensions/browser/event_router.h index a289fc4..073e11d 100644 --- a/extensions/browser/event_router.h +++ b/extensions/browser/event_router.h
@@ -164,8 +164,8 @@ EventListenerMap& listeners() { return listeners_; } // Registers an observer to be notified when an event listener for - // |event_name| is added or removed. There can currently be only one observer - // for each distinct |event_name|. + // |event_name| is added or removed. There can currently be multiple + // observers for each distinct |event_name|. void RegisterObserver(Observer* observer, const std::string& event_name); // Unregisters an observer from all events.
diff --git a/extensions/common/api/bluetooth_socket.idl b/extensions/common/api/bluetooth_socket.idl index cb95c02..2d98e92 100644 --- a/extensions/common/api/bluetooth_socket.idl +++ b/extensions/common/api/bluetooth_socket.idl
@@ -195,16 +195,16 @@ // Creates a Bluetooth socket. // |properties| : The socket properties (optional). // |callback| : Called when the socket has been created. - static void create(optional SocketProperties properties, - CreateCallback callback); + [supportsPromises] static void create(optional SocketProperties properties, + CreateCallback callback); // Updates the socket properties. // |socketId| : The socket identifier. // |properties| : The properties to update. // |callback| : Called when the properties are updated. - static void update(long socketId, - SocketProperties properties, - optional UpdateCallback callback); + [supportsPromises] static void update(long socketId, + SocketProperties properties, + optional UpdateCallback callback); // Enables or disables a connected socket from receiving messages from its // peer, or a listening socket from accepting new connections. The default @@ -216,29 +216,32 @@ // connections are accepted until its backlog is full then additional // connection requests are refused. <code>onAccept</code> events are raised // only when the socket is un-paused. - static void setPaused(long socketId, - boolean paused, - optional SetPausedCallback callback); + [supportsPromises] static void setPaused( + long socketId, + boolean paused, + optional SetPausedCallback callback); // Listen for connections using the RFCOMM protocol. // |socketId| : The socket identifier. // |uuid| : Service UUID to listen on. // |options| : Optional additional options for the service. // |callback| : Called when listen operation completes. - static void listenUsingRfcomm(long socketId, - DOMString uuid, - optional ListenOptions options, - ListenCallback callback); + [supportsPromises] static void listenUsingRfcomm( + long socketId, + DOMString uuid, + optional ListenOptions options, + ListenCallback callback); // Listen for connections using the L2CAP protocol. // |socketId| : The socket identifier. // |uuid| : Service UUID to listen on. // |options| : Optional additional options for the service. // |callback| : Called when listen operation completes. - static void listenUsingL2cap(long socketId, - DOMString uuid, - optional ListenOptions options, - ListenCallback callback); + [supportsPromises] static void listenUsingL2cap( + long socketId, + DOMString uuid, + optional ListenOptions options, + ListenCallback callback); // Connects the socket to a remote Bluetooth device. When the // <code>connect</code> operation completes successfully, @@ -251,16 +254,17 @@ // |address| : The address of the Bluetooth device. // |uuid| : The UUID of the service to connect to. // |callback| : Called when the connect attempt is complete. - static void connect(long socketId, - DOMString address, - DOMString uuid, - ConnectCallback callback); + [supportsPromises] static void connect(long socketId, + DOMString address, + DOMString uuid, + ConnectCallback callback); // Disconnects the socket. The socket identifier remains valid. // |socketId| : The socket identifier. // |callback| : Called when the disconnect attempt is complete. - static void disconnect(long socketId, - optional DisconnectCallback callback); + [supportsPromises] static void disconnect( + long socketId, + optional DisconnectCallback callback); // Disconnects and destroys the socket. Each socket created should be // closed after use. The socket id is no longer valid as soon at the @@ -268,26 +272,26 @@ // when the callback is invoked. // |socketId| : The socket identifier. // |callback| : Called when the <code>close</code> operation completes. - static void close(long socketId, - optional CloseCallback callback); + [supportsPromises] static void close(long socketId, + optional CloseCallback callback); // Sends data on the given Bluetooth socket. // |socketId| : The socket identifier. // |data| : The data to send. // |callback| : Called with the number of bytes sent. - static void send(long socketId, - ArrayBuffer data, - optional SendCallback callback); + [supportsPromises] static void send(long socketId, + ArrayBuffer data, + optional SendCallback callback); // Retrieves the state of the given socket. // |socketId| : The socket identifier. // |callback| : Called when the socket state is available. - static void getInfo(long socketId, - GetInfoCallback callback); + [supportsPromises] static void getInfo(long socketId, + GetInfoCallback callback); // Retrieves the list of currently opened sockets owned by the application. // |callback| : Called when the list of sockets is available. - static void getSockets(GetSocketsCallback callback); + [supportsPromises] static void getSockets(GetSocketsCallback callback); }; interface Events {
diff --git a/extensions/common/api/cast_channel.idl b/extensions/common/api/cast_channel.idl index 6fd3035b..9b80a4d 100644 --- a/extensions/common/api/cast_channel.idl +++ b/extensions/common/api/cast_channel.idl
@@ -176,25 +176,25 @@ // callback will be invoked with a ChannelInfo with channel.readyState == // 'closed', channel.errorState will be set to the error condition, and // onError will be fired with error details. - static void open(ConnectInfo connectInfo, - ChannelInfoCallback callback); + [supportsPromises] static void open(ConnectInfo connectInfo, + ChannelInfoCallback callback); // Sends a message on the channel and invokes callback with the resulting // channel status. The channel must be in readyState == 'open'. If // unsuccessful, channel.readyState will be set to 'closed', // channel.errorState will be set to the error condition, and onError will // be fired with error details. - static void send(ChannelInfo channel, - MessageInfo message, - ChannelInfoCallback callback); + [supportsPromises] static void send(ChannelInfo channel, + MessageInfo message, + ChannelInfoCallback callback); // Requests that the channel be closed and invokes callback with the // resulting channel status. The channel must be in readyState == 'open' or // 'connecting'. If successful, onClose will be fired with readyState == // 'closed'. If unsuccessful, channel.readyState will be set to 'closed', // and channel.errorState will be set to the error condition. - static void close(ChannelInfo channel, - ChannelInfoCallback callback); + [supportsPromises] static void close(ChannelInfo channel, + ChannelInfoCallback callback); }; // Events on the channel.
diff --git a/extensions/common/api/cec_private.idl b/extensions/common/api/cec_private.idl index b32874e..4c3af5f 100644 --- a/extensions/common/api/cec_private.idl +++ b/extensions/common/api/cec_private.idl
@@ -46,7 +46,8 @@ // // |callback| will be run as soon as all displays have been requested to // change their power state. - static void sendStandBy(optional ChangePowerStateCallback callback); + [supportsPromises] static void sendStandBy( + optional ChangePowerStateCallback callback); // Attempt to announce this device as the active input source towards all // HDMI CEC enabled displays connected, waking them from standby if @@ -54,10 +55,11 @@ // // |callback| will be run as soon as all displays have been requested to // change their power state. - static void sendWakeUp(optional ChangePowerStateCallback callback); + [supportsPromises] static void sendWakeUp( + optional ChangePowerStateCallback callback); // Queries all HDMI CEC capable displays for their current power state. - static void queryDisplayCecPowerState( + [supportsPromises] static void queryDisplayCecPowerState( DisplayCecPowerStateCallback callback); }; };
diff --git a/extensions/common/api/clipboard.idl b/extensions/common/api/clipboard.idl index 55b3bb8..382da46c 100644 --- a/extensions/common/api/clipboard.idl +++ b/extensions/common/api/clipboard.idl
@@ -46,9 +46,10 @@ // The callback is called with <code>chrome.runtime.lastError</code> // set to error code if there is an error. // Requires clipboard and clipboardWrite permissions. - static void setImageData(ArrayBuffer imageData, - ImageType type, - optional AdditionalDataItem[] additionalItems, - optional SetImageDataCallback callback); + [supportsPromises] static void setImageData( + ArrayBuffer imageData, + ImageType type, + optional AdditionalDataItem[] additionalItems, + optional SetImageDataCallback callback); }; };
diff --git a/extensions/common/api/declarative_net_request.idl b/extensions/common/api/declarative_net_request.idl index 4eb0487..babe792 100644 --- a/extensions/common/api/declarative_net_request.idl +++ b/extensions/common/api/declarative_net_request.idl
@@ -471,13 +471,14 @@ // to the rule set. This can happen for multiple reasons, such as invalid // rule format, duplicate rule ID, rule count limit exceeded, internal // errors, and others. - static void updateDynamicRules(UpdateRuleOptions options, - optional EmptyCallback callback); + [supportsPromises] static void updateDynamicRules( + UpdateRuleOptions options, + optional EmptyCallback callback); // Returns the current set of dynamic rules for the extension. // |callback|: Called with the set of dynamic rules. An error might be // raised in case of transient internal errors. - static void getDynamicRules(GetRulesCallback callback); + [supportsPromises] static void getDynamicRules(GetRulesCallback callback); // Modifies the current set of session scoped rules for the extension. // The rules with IDs listed in <code>options.removeRuleIds</code> are first @@ -495,12 +496,13 @@ // an error, $(ref:runtime.lastError) will be set and no change will be made // to the rule set. This can happen for multiple reasons, such as invalid // rule format, duplicate rule ID, rule count limit exceeded, and others. - static void updateSessionRules(UpdateRuleOptions options, - optional EmptyCallback callback); + [supportsPromises] static void updateSessionRules( + UpdateRuleOptions options, + optional EmptyCallback callback); // Returns the current set of session scoped rules for the extension. // |callback|: Called with the set of session scoped rules. - static void getSessionRules(GetRulesCallback callback); + [supportsPromises] static void getSessionRules(GetRulesCallback callback); // Updates the set of enabled static rulesets for the extension. The // rulesets with IDs listed in <code>options.disableRulesetIds</code> are @@ -514,13 +516,15 @@ // $(ref:runtime.lastError) will be set and no change will be made to set of // enabled rulesets. This can happen for multiple reasons, such as invalid // ruleset IDs, rule count limit exceeded, or internal errors. - static void updateEnabledRulesets(UpdateRulesetOptions options, - optional EmptyCallback callback); + [supportsPromises] static void updateEnabledRulesets( + UpdateRulesetOptions options, + optional EmptyCallback callback); // Returns the ids for the current set of enabled static rulesets. // |callback|: Called with a list of ids, where each id corresponds to an // enabled static $(ref:Ruleset). - static void getEnabledRulesets(GetEnabledRulesetsCallback callback); + [supportsPromises] static void getEnabledRulesets( + GetEnabledRulesetsCallback callback); // Returns all rules matched for the extension. Callers can optionally // filter the list of matched rules by specifying a |filter|. This method is @@ -535,13 +539,14 @@ // case of an error, $(ref:runtime.lastError) will be set and no rules will // be returned. This can happen for multiple reasons, such as insufficient // permissions, or exceeding the quota. - static void getMatchedRules(optional MatchedRulesFilter filter, - GetMatchedRulesCallback callback); + [supportsPromises] static void getMatchedRules( + optional MatchedRulesFilter filter, + GetMatchedRulesCallback callback); // Configures if the action count for tabs should be displayed as the // extension action's badge text and provides a way for that action count to // be incremented. - static void setExtensionActionOptions( + [supportsPromises] static void setExtensionActionOptions( ExtensionActionOptions options, optional EmptyCallback callback); @@ -550,12 +555,13 @@ // |regexOptions|: The regular expression to check. // |callback|: Called with details consisting of whether the regular // expression is supported and the reason if not. - static void isRegexSupported(RegexOptions regexOptions, - IsRegexSupportedCallback callback); + [supportsPromises] static void isRegexSupported( + RegexOptions regexOptions, + IsRegexSupportedCallback callback); // Returns the number of static rules an extension can enable before the // <a href="#global-rule-limit">global static rule limit</a> is reached. - static void getAvailableStaticRuleCount( + [supportsPromises] static void getAvailableStaticRuleCount( GetAvailableStaticRuleCountCallback callback); };
diff --git a/fuchsia/engine/context_provider_impl.cc b/fuchsia/engine/context_provider_impl.cc index a62bb75..5c8dc52 100644 --- a/fuchsia/engine/context_provider_impl.cc +++ b/fuchsia/engine/context_provider_impl.cc
@@ -171,6 +171,7 @@ switches::kMaxDecodedImageSizeMb, switches::kRendererProcessLimit, switches::kUseCmdDecoder, + switches::kVModule, switches::kVulkanHeapMemoryLimitMb, switches::kVulkanSyncCpuMemoryLimitMb, switches::kWebglAntialiasingMode,
diff --git a/gpu/command_buffer/service/scheduler.cc b/gpu/command_buffer/service/scheduler.cc index d5001368..4730d63 100644 --- a/gpu/command_buffer/service/scheduler.cc +++ b/gpu/command_buffer/service/scheduler.cc
@@ -5,6 +5,7 @@ #include "gpu/command_buffer/service/scheduler.h" #include <algorithm> +#include <vector> #include "base/bind.h" #include "base/callback.h" @@ -13,6 +14,7 @@ #include "base/metrics/histogram_macros.h" #include "base/single_thread_task_runner.h" #include "base/stl_util.h" +#include "base/time/time.h" #include "base/timer/elapsed_timer.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/traced_value.h" @@ -185,6 +187,20 @@ return order_num; } +base::TimeDelta Scheduler::Sequence::FrontTaskWaitingDependencyDelta() { + DCHECK(!tasks_.empty()); + if (tasks_.front().first_dependency_added.is_null()) { + // didn't wait for dependencies. + return base::TimeDelta(); + } + return tasks_.front().running_ready - tasks_.front().first_dependency_added; +} + +base::TimeDelta Scheduler::Sequence::FrontTaskSchedulingDelay() { + DCHECK(!tasks_.empty()); + return base::TimeTicks::Now() - tasks_.front().running_ready; +} + uint32_t Scheduler::Sequence::BeginTask(base::OnceClosure* closure) { DCHECK(closure); DCHECK(!tasks_.empty()); @@ -204,6 +220,14 @@ running_state_ = IDLE; } +void Scheduler::Sequence::SetLastTaskFirstDependencyTimeIfNeeded() { + DCHECK(!tasks_.empty()); + if (tasks_.back().first_dependency_added.is_null()) { + // Fence are always added for the last task (which should always exists). + tasks_.back().first_dependency_added = base::TimeTicks::Now(); + } +} + void Scheduler::Sequence::AddWaitFence(const SyncToken& sync_token, uint32_t order_num, SequenceId release_sequence_id) { @@ -233,6 +257,17 @@ SchedulingPriority wait_priority = it->second; wait_fences_.erase(it); + for (auto& task : tasks_) { + if (order_num == task.order_num) { + // The fence applies to this task, bump the readiness timestamp + task.running_ready = base::TimeTicks::Now(); + break; + } else if (order_num < task.order_num) { + // Updated all task related to this fence. + break; + } + } + Sequence* release_sequence = scheduler_->GetSequence(release_sequence_id); if (release_sequence) release_sequence->RemoveWaitingPriority(wait_priority); @@ -424,6 +459,7 @@ sync_token, order_num, release_sequence_id, sequence_id))) { sequence->AddWaitFence(sync_token, order_num, release_sequence_id); + sequence->SetLastTaskFirstDependencyTimeIfNeeded(); } } @@ -544,6 +580,18 @@ Sequence* sequence = GetSequence(state.sequence_id); DCHECK(sequence); + UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES( + "GPU.Scheduler.TaskDependencyTime", + sequence->FrontTaskWaitingDependencyDelta(), + base::TimeDelta::FromMicroseconds(10), base::TimeDelta::FromSeconds(30), + 100); + + UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES( + "GPU.Scheduler.TaskSchedulingDelayTime", + sequence->FrontTaskSchedulingDelay(), + base::TimeDelta::FromMicroseconds(10), base::TimeDelta::FromSeconds(30), + 100); + base::OnceClosure closure; uint32_t order_num = sequence->BeginTask(&closure); DCHECK_EQ(order_num, state.order_num);
diff --git a/gpu/command_buffer/service/scheduler.h b/gpu/command_buffer/service/scheduler.h index c47f6f5..9df2986 100644 --- a/gpu/command_buffer/service/scheduler.h +++ b/gpu/command_buffer/service/scheduler.h
@@ -17,6 +17,7 @@ #include "base/memory/weak_ptr.h" #include "base/synchronization/lock.h" #include "base/threading/thread_checker.h" +#include "base/time/time.h" #include "gpu/command_buffer/common/command_buffer_id.h" #include "gpu/command_buffer/common/scheduling_priority.h" #include "gpu/command_buffer/common/sync_token.h" @@ -169,6 +170,14 @@ // Update cached scheduling priority while running. void UpdateRunningPriority(); + // The time delta it took for the front task's dependencies to be completed. + base::TimeDelta FrontTaskWaitingDependencyDelta(); + + // The delay between when the front task was ready to run (no more + // dependencies) and now. This is used when the task is actually started to + // check for low scheduling delays. + base::TimeDelta FrontTaskSchedulingDelay(); + // Returns the next order number and closure. Sets running state to RUNNING. uint32_t BeginTask(base::OnceClosure* closure); @@ -183,6 +192,10 @@ // in between |BeginTask| and |FinishTask|. void ContinueTask(base::OnceClosure closure); + // Sets the first dependency added time on the last task if it wasn't + // already set, no-op otherwise. + void SetLastTaskFirstDependencyTimeIfNeeded(); + // Add a sync token fence that this sequence should wait on. void AddWaitFence(const SyncToken& sync_token, uint32_t order_num, @@ -235,6 +248,13 @@ base::OnceClosure closure; uint32_t order_num; + + // TODO(b/181148082): add measuring callback to return values to task + // owner + // Note: this time is only correct once the last fence has been removed, + // as it is updated for all fences. + base::TimeTicks running_ready = base::TimeTicks::Now(); + base::TimeTicks first_dependency_added; }; // Description of Stream priority propagation: Each Stream has an initial
diff --git a/gpu/gles2_conform_support/generate_gles2_conform_tests.py b/gpu/gles2_conform_support/generate_gles2_conform_tests.py index b6b49a1..632864f 100755 --- a/gpu/gles2_conform_support/generate_gles2_conform_tests.py +++ b/gpu/gles2_conform_support/generate_gles2_conform_tests.py
@@ -30,17 +30,17 @@ out_file.write(""" #include "gpu/gles2_conform_support/gles2_conform_test.h" #include "testing/gtest/include/gtest/gtest.h" -""") +""".encode("utf8")) for test in tests: - out_file.write(""" + out_file.write((""" TEST(GLES2ConformTest, %(name)s) { EXPECT_TRUE(RunGLES2ConformTest("%(path)s")); } """ % { "name": re.sub(r'[^A-Za-z0-9]', '_', test), "path": test, - }) + }).encode("utf8")) def main(argv): @@ -52,7 +52,7 @@ out_dir = '.' out_filename = os.path.join(out_dir, 'gles2_conform_test_autogen.cc') - with open(out_filename, 'wb') as out_file: + with open(out_filename, 'w') as out_file: GenerateTests(out_file) return 0
diff --git a/gpu/gles2_conform_support/generate_gles2_embedded_data.py b/gpu/gles2_conform_support/generate_gles2_embedded_data.py index 809b24a5..d8eb08f 100755 --- a/gpu/gles2_conform_support/generate_gles2_embedded_data.py +++ b/gpu/gles2_conform_support/generate_gles2_embedded_data.py
@@ -5,6 +5,8 @@ """generates files to embed the gles2 conformance test data in executable.""" +from __future__ import print_function + import os import sys @@ -35,23 +37,23 @@ self.files_data_c = open(os.path.join(base_dir, "FilesDATA.c"), "wb") self.files_toc_c = open(os.path.join(base_dir, "FilesTOC.c"), "wb") - self.files_data_h.write("#ifndef FilesDATA_h\n\n") - self.files_data_h.write("#define FilesDATA_h\n\n"); + self.files_data_h.write(b"#ifndef FilesDATA_h\n\n") + self.files_data_h.write(b"#define FilesDATA_h\n\n"); - self.files_data_c.write("#include \"FilesDATA.h\"\n\n") + self.files_data_c.write(b"#include \"FilesDATA.h\"\n\n") - self.files_toc_c.write("#include \"FilesTOC.h\"\n\n"); - self.files_toc_c.write("struct GTFVectorFileEntry tempFiles;\n\n"); - self.files_toc_c.write("struct FileEntry files[] = {\n"); + self.files_toc_c.write(b"#include \"FilesTOC.h\"\n\n"); + self.files_toc_c.write(b"struct GTFVectorFileEntry tempFiles;\n\n"); + self.files_toc_c.write(b"struct FileEntry files[] = {\n"); self.AddFiles(scan_dir) if self.base_dir != None: - self.files_toc_c.write("\n};\n\n"); + self.files_toc_c.write(b"\n};\n\n"); self.files_toc_c.write( - "int numFileEntrys = sizeof(files) / sizeof(struct FileEntry);\n"); + b"int numFileEntrys = sizeof(files) / sizeof(struct FileEntry);\n"); - self.files_data_h.write("\n\n#endif // FilesDATA_h\n"); + self.files_data_h.write(b"\n\n#endif // FilesDATA_h\n"); self.files_data_c.close() self.files_data_h.close() @@ -70,14 +72,16 @@ sub_dirs.append(full_path) elif ext in GenerateEmbeddedFiles.extensions_to_include: if self.base_dir == None: - print full_path.replace("\\", "/") + print(full_path.replace("\\", "/")) else: self.count += 1 name = "_FILE_%s_%d" % (ext.upper(), self.count) name = name.replace(".", "_") - self.files_data_h.write("extern const char %s[];\n" % name) - self.files_data_c.write("const char %s[] = \n" % name) + self.files_data_h.write( + ("extern const char %s[];\n" % name).encode("utf8")) + self.files_data_c.write( + ("const char %s[] = \n" % name).encode("utf8")) data = open(full_path, "r") lines = data.readlines(); @@ -89,11 +93,11 @@ line = line.replace("\\", "\\\\") line = line.replace("\"", "\\\"") - self.files_data_c.write('"%s\\n"\n' % line) + self.files_data_c.write(('"%s\\n"\n' % line).encode("utf8")) - self.files_data_c.write(";\n") - self.files_toc_c.write("\t{ \"%s\", %s, 0 },\n" % ( - base_path.replace("\\", "/"), name)) + self.files_data_c.write(b";\n") + self.files_toc_c.write(("\t{ \"%s\", %s, 0 },\n" % ( + base_path.replace("\\", "/"), name)).encode("utf8")) for sub_dir in sub_dirs: self.AddFiles(sub_dir)
diff --git a/infra/config/generated/commit-queue.cfg b/infra/config/generated/commit-queue.cfg index 0f616146..3d7963b 100644 --- a/infra/config/generated/commit-queue.cfg +++ b/infra/config/generated/commit-queue.cfg
@@ -508,6 +508,7 @@ location_regexp: ".+/[+]/third_party/blink/web_tests/wpt_internal/webgpu/.+" location_regexp: ".+/[+]/third_party/blink/web_tests/WebGPUExpectations" location_regexp: ".+/[+]/third_party/dawn/.+" + location_regexp: ".+/[+]/third_party/webgpu-cts/.+" location_regexp: ".+/[+]/tools/clang/scripts/update.py" location_regexp: ".+/[+]/ui/gl/features.gni" location_regexp_exclude: ".+/[+]/docs/.+" @@ -522,6 +523,7 @@ location_regexp: ".+/[+]/third_party/blink/web_tests/wpt_internal/webgpu/.+" location_regexp: ".+/[+]/third_party/blink/web_tests/WebGPUExpectations" location_regexp: ".+/[+]/third_party/dawn/.+" + location_regexp: ".+/[+]/third_party/webgpu-cts/.+" location_regexp: ".+/[+]/tools/clang/scripts/update.py" location_regexp: ".+/[+]/ui/gl/features.gni" location_regexp_exclude: ".+/[+]/docs/.+" @@ -544,6 +546,7 @@ location_regexp: ".+/[+]/third_party/blink/web_tests/wpt_internal/webgpu/.+" location_regexp: ".+/[+]/third_party/blink/web_tests/WebGPUExpectations" location_regexp: ".+/[+]/third_party/dawn/.+" + location_regexp: ".+/[+]/third_party/webgpu-cts/.+" location_regexp: ".+/[+]/tools/clang/scripts/update.py" location_regexp: ".+/[+]/ui/gl/features.gni" location_regexp_exclude: ".+/[+]/docs/.+" @@ -558,6 +561,7 @@ location_regexp: ".+/[+]/third_party/blink/web_tests/wpt_internal/webgpu/.+" location_regexp: ".+/[+]/third_party/blink/web_tests/WebGPUExpectations" location_regexp: ".+/[+]/third_party/dawn/.+" + location_regexp: ".+/[+]/third_party/webgpu-cts/.+" location_regexp: ".+/[+]/tools/clang/scripts/update.py" location_regexp: ".+/[+]/ui/gl/features.gni" location_regexp_exclude: ".+/[+]/docs/.+"
diff --git a/infra/config/generated/cq-builders.md b/infra/config/generated/cq-builders.md index 41b2637..7d7b4ac3 100644 --- a/infra/config/generated/cq-builders.md +++ b/infra/config/generated/cq-builders.md
@@ -183,6 +183,7 @@ * [`//third_party/blink/web_tests/wpt_internal/webgpu/.+`](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/wpt_internal/webgpu/) * [`//third_party/blink/web_tests/WebGPUExpectations`](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/WebGPUExpectations) * [`//third_party/dawn/.+`](https://cs.chromium.org/chromium/src/third_party/dawn/) + * [`//third_party/webgpu-cts/.+`](https://cs.chromium.org/chromium/src/third_party/webgpu-cts/) * [`//tools/clang/scripts/update.py`](https://cs.chromium.org/search?q=package:%5Echromium$+file:tools/clang/scripts/update.py) * [`//ui/gl/features.gni`](https://cs.chromium.org/search?q=package:%5Echromium$+file:ui/gl/features.gni) @@ -196,6 +197,7 @@ * [`//third_party/blink/web_tests/wpt_internal/webgpu/.+`](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/wpt_internal/webgpu/) * [`//third_party/blink/web_tests/WebGPUExpectations`](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/WebGPUExpectations) * [`//third_party/dawn/.+`](https://cs.chromium.org/chromium/src/third_party/dawn/) + * [`//third_party/webgpu-cts/.+`](https://cs.chromium.org/chromium/src/third_party/webgpu-cts/) * [`//tools/clang/scripts/update.py`](https://cs.chromium.org/search?q=package:%5Echromium$+file:tools/clang/scripts/update.py) * [`//ui/gl/features.gni`](https://cs.chromium.org/search?q=package:%5Echromium$+file:ui/gl/features.gni) @@ -209,6 +211,7 @@ * [`//third_party/blink/web_tests/wpt_internal/webgpu/.+`](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/wpt_internal/webgpu/) * [`//third_party/blink/web_tests/WebGPUExpectations`](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/WebGPUExpectations) * [`//third_party/dawn/.+`](https://cs.chromium.org/chromium/src/third_party/dawn/) + * [`//third_party/webgpu-cts/.+`](https://cs.chromium.org/chromium/src/third_party/webgpu-cts/) * [`//tools/clang/scripts/update.py`](https://cs.chromium.org/search?q=package:%5Echromium$+file:tools/clang/scripts/update.py) * [`//ui/gl/features.gni`](https://cs.chromium.org/search?q=package:%5Echromium$+file:ui/gl/features.gni) @@ -222,6 +225,7 @@ * [`//third_party/blink/web_tests/wpt_internal/webgpu/.+`](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/wpt_internal/webgpu/) * [`//third_party/blink/web_tests/WebGPUExpectations`](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/WebGPUExpectations) * [`//third_party/dawn/.+`](https://cs.chromium.org/chromium/src/third_party/dawn/) + * [`//third_party/webgpu-cts/.+`](https://cs.chromium.org/chromium/src/third_party/webgpu-cts/) * [`//tools/clang/scripts/update.py`](https://cs.chromium.org/search?q=package:%5Echromium$+file:tools/clang/scripts/update.py) * [`//ui/gl/features.gni`](https://cs.chromium.org/search?q=package:%5Echromium$+file:ui/gl/features.gni)
diff --git a/infra/config/subprojects/chromium/try.star b/infra/config/subprojects/chromium/try.star index 9583e43..ad167fe 100644 --- a/infra/config/subprojects/chromium/try.star +++ b/infra/config/subprojects/chromium/try.star
@@ -814,6 +814,7 @@ ".+/[+]/third_party/blink/web_tests/wpt_internal/webgpu/.+", ".+/[+]/third_party/blink/web_tests/WebGPUExpectations", ".+/[+]/third_party/dawn/.+", + ".+/[+]/third_party/webgpu-cts/.+", ".+/[+]/tools/clang/scripts/update.py", ".+/[+]/ui/gl/features.gni", ], @@ -834,6 +835,7 @@ ".+/[+]/third_party/blink/web_tests/wpt_internal/webgpu/.+", ".+/[+]/third_party/blink/web_tests/WebGPUExpectations", ".+/[+]/third_party/dawn/.+", + ".+/[+]/third_party/webgpu-cts/.+", ".+/[+]/tools/clang/scripts/update.py", ".+/[+]/ui/gl/features.gni", ], @@ -854,6 +856,7 @@ ".+/[+]/third_party/blink/web_tests/wpt_internal/webgpu/.+", ".+/[+]/third_party/blink/web_tests/WebGPUExpectations", ".+/[+]/third_party/dawn/.+", + ".+/[+]/third_party/webgpu-cts/.+", ".+/[+]/tools/clang/scripts/update.py", ".+/[+]/ui/gl/features.gni", ], @@ -874,6 +877,7 @@ ".+/[+]/third_party/blink/web_tests/wpt_internal/webgpu/.+", ".+/[+]/third_party/blink/web_tests/WebGPUExpectations", ".+/[+]/third_party/dawn/.+", + ".+/[+]/third_party/webgpu-cts/.+", ".+/[+]/tools/clang/scripts/update.py", ".+/[+]/ui/gl/features.gni", ],
diff --git a/ios/build/bots/chromium.webrtc.fyi/WebRTC Chromium FYI ios-device.json b/ios/build/bots/chromium.webrtc.fyi/WebRTC Chromium FYI ios-device.json index 4378efb..fee62969 100644 --- a/ios/build/bots/chromium.webrtc.fyi/WebRTC Chromium FYI ios-device.json +++ b/ios/build/bots/chromium.webrtc.fyi/WebRTC Chromium FYI ios-device.json
@@ -5,6 +5,7 @@ ], "xcode build version": "12d4e", "gn_args": [ + "enable_run_ios_unittests_with_xctest=true", "goma_dir=\"$(goma_dir)\"", "ios_enable_code_signing=false", "ios_set_attributes_for_xcode_project_generation=false",
diff --git a/ios/build/bots/chromium.webrtc.fyi/WebRTC Chromium FYI ios-simulator.json b/ios/build/bots/chromium.webrtc.fyi/WebRTC Chromium FYI ios-simulator.json index 944f3a474..d63f36dc 100644 --- a/ios/build/bots/chromium.webrtc.fyi/WebRTC Chromium FYI ios-simulator.json +++ b/ios/build/bots/chromium.webrtc.fyi/WebRTC Chromium FYI ios-simulator.json
@@ -4,6 +4,7 @@ ], "xcode build version": "12d4e", "gn_args": [ + "enable_run_ios_unittests_with_xctest=true", "goma_dir=\"$(goma_dir)\"", "ios_enable_code_signing=false", "ios_set_attributes_for_xcode_project_generation=false",
diff --git a/ios/chrome/app/BUILD.gn b/ios/chrome/app/BUILD.gn index be6bfcf7..a7d178f 100644 --- a/ios/chrome/app/BUILD.gn +++ b/ios/chrome/app/BUILD.gn
@@ -163,6 +163,18 @@ ] } +source_set("safe_mode_app_state_agent") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ + "safe_mode_app_state_agent.h", + "safe_mode_app_state_agent.mm", + ] + deps = [ + "//base", + "//ios/chrome/app/application_delegate:app_state_header", + ] +} + source_set("app_internal") { configs += [ "//build/config/compiler:enable_arc" ] sources = [ @@ -186,6 +198,7 @@ ":blocking_scene_commands", ":content_suggestions_scheduler_app_state_agent", ":mode", + ":safe_mode_app_state_agent", ":tests_hook", "//base", "//build:branding_buildflags",
diff --git a/ios/chrome/app/application_delegate/BUILD.gn b/ios/chrome/app/application_delegate/BUILD.gn index 712b732d..8e405d9 100644 --- a/ios/chrome/app/application_delegate/BUILD.gn +++ b/ios/chrome/app/application_delegate/BUILD.gn
@@ -47,6 +47,7 @@ "//ios/chrome/app", "//ios/chrome/app:app_internal", "//ios/chrome/app:mode", + "//ios/chrome/app:safe_mode_app_state_agent", "//ios/chrome/app/intents", "//ios/chrome/app/spotlight", "//ios/chrome/app/startup", @@ -140,6 +141,7 @@ sources = [ "app_state.h", "app_state_agent.h", + "app_state_observer.h", ] public_deps = [ "//ios/chrome/browser/ui/main:scene_state_observer",
diff --git a/ios/chrome/app/application_delegate/app_state.h b/ios/chrome/app/application_delegate/app_state.h index 4f15d69..6648be7 100644 --- a/ios/chrome/app/application_delegate/app_state.h +++ b/ios/chrome/app/application_delegate/app_state.h
@@ -10,6 +10,7 @@ #include <memory> #import "ios/chrome/app/application_delegate/app_state_agent.h" +#import "ios/chrome/app/application_delegate/app_state_observer.h" #import "ios/chrome/browser/ui/main/scene_state_observer.h" #import "ios/chrome/browser/ui/scoped_ui_blocker/ui_blocker_manager.h" @@ -30,26 +31,6 @@ class TimeTicks; } -@protocol AppStateObserver <NSObject> - -@optional - -// Called when a scene is connected. -// On iOS 12, called when the mainSceneState is set. -- (void)appState:(AppState*)appState sceneConnected:(SceneState*)sceneState; - -// Called when the first scene initializes its UI. -- (void)appState:(AppState*)appState - firstSceneHasInitializedUI:(SceneState*)sceneState; - -// Called after the app exits safe mode. -- (void)appStateDidExitSafeMode:(AppState*)appState; - -// Called when |AppState.lastTappedWindow| changes. -- (void)appState:(AppState*)appState lastTappedWindowChanged:(UIWindow*)window; - -@end - // Represents the application state and responds to application state changes // and system events. @interface AppState : NSObject <UIBlockerManager, SceneStateObserver> @@ -109,6 +90,9 @@ // Timestamp of when a scene was last becoming active. Can be null. @property(nonatomic, assign) base::TimeTicks lastTimeInForeground; +// The initialization stage the app is currently at. +@property(nonatomic, readonly) InitStage initStage; + // Saves the launchOptions to be used from -newTabFromLaunchOptions. If the // application is in background, initialize the browser to basic. If not, launch // the browser. @@ -177,6 +161,10 @@ // This automatically sets the app state on the |agent|. - (void)addAgent:(id<AppStateAgent>)agent; +// Queue the transition to the next app initialization stage. Will stop +// transitioning when the Final stage is reached. +- (void)queueTransitionToNextInitStage; + @end #endif // IOS_CHROME_APP_APPLICATION_DELEGATE_APP_STATE_H_
diff --git a/ios/chrome/app/application_delegate/app_state.mm b/ios/chrome/app/application_delegate/app_state.mm index 1d448b4..e98fbda 100644 --- a/ios/chrome/app/application_delegate/app_state.mm +++ b/ios/chrome/app/application_delegate/app_state.mm
@@ -154,6 +154,13 @@ // Agents attached to this app state. @property(nonatomic, strong) NSMutableArray<id<AppStateAgent>>* agents; +// Operational blocks to be run by the local runloop that are queued by the +// init stage agents. +@property(nonatomic, strong) NSMutableArray* stageQueue; + +// Redefined internaly as readwrite. +@property(nonatomic, assign, readwrite) InitStage initStage; + @end @implementation AppState @@ -189,6 +196,8 @@ object:nil]; } } + + _stageQueue = [NSMutableArray new]; } return self; } @@ -552,6 +561,13 @@ [agent setAppState:self]; } +- (void)queueTransitionToNextInitStage { + __weak AppState* weakSelf = self; + [_stageQueue addObject:(^{ + [weakSelf advanceToNextInitStage]; + })]; +} + #pragma mark - Multiwindow-related - (SceneState*)foregroundActiveScene { @@ -602,6 +618,8 @@ #pragma mark - SafeModeCoordinatorDelegate Implementation +// TODO(crbug.com/1178809): Handle this with an app state agent when +// transitioning out of safe mode. - (void)coordinatorDidExitSafeMode:(nonnull SafeModeCoordinator*)coordinator { [self stopSafeMode]; [_browserLauncher startUpBrowserToStage:INITIALIZATION_STAGE_FOREGROUND]; @@ -648,6 +666,9 @@ _userInteracted = YES; [self saveLaunchDetailsToDefaults]; + [self startInitStages]; + + // TODO(crbug.com/1178809): Move this logic to the safe mode agent. if ([SafeModeCoordinator shouldStart]) { self.inSafeMode = YES; if (!base::ios::IsMultiwindowSupported()) { @@ -658,6 +679,9 @@ return; } + // TODO(crbug.com/1178809): Move the logic below to a Final Init Stage agent + // to make sure that the logic is only executed when getting out of safe mode. + // Don't add code here. Add it in MainController's // -startUpBrowserForegroundInitialization. DCHECK([self.startupInformation isColdStart]); @@ -689,6 +713,41 @@ [[PreviousSessionInfo sharedInstance] beginRecordingCurrentSession]; } +// Advances to the next init stage. +- (void)advanceToNextInitStage { + // The app is done with all init stages, nothing to do. + if (self.initStage == InitStageFinal) + return; + + InitStage newInitStage = static_cast<InitStage>(self.initStage + 1); + + [self.observers appState:self willTransitionToInitStage:newInitStage]; + self.initStage = newInitStage; + [self.observers appState:self didTransitionToInitStage:self.initStage]; +} + +// Starts the transition through init stages. +- (void)startInitStages { + __weak AppState* weakSelf = self; + [_stageQueue addObject:(^{ + [weakSelf.observers appState:weakSelf + willTransitionToInitStage:InitStageStart]; + [weakSelf.observers appState:weakSelf + didTransitionToInitStage:InitStageStart]; + })]; + [self executeInitStageQueue]; +} + +// Executes the blocks in the init stage queue until the queue is empty. This +// will also execute the new blocks that are queued on the fly. +- (void)executeInitStageQueue { + while ([_stageQueue count] > 0) { + void (^stageBlock)() = [_stageQueue objectAtIndex:0]; + stageBlock(); + [_stageQueue removeObjectAtIndex:0]; + } +} + #pragma mark - UIBlockerManager - (void)incrementBlockingUICounterForTarget:(id<UIBlockerTarget>)target {
diff --git a/ios/chrome/app/application_delegate/app_state_observer.h b/ios/chrome/app/application_delegate/app_state_observer.h new file mode 100644 index 0000000..f3b326e --- /dev/null +++ b/ios/chrome/app/application_delegate/app_state_observer.h
@@ -0,0 +1,56 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#ifndef IOS_CHROME_APP_APPLICATION_DELEGATE_APP_STATE_OBSERVER_H_ +#define IOS_CHROME_APP_APPLICATION_DELEGATE_APP_STATE_OBSERVER_H_ + +@class AppState; +@class UIWindow; +@class SceneState; + +// App initialization stages. The app will go sequentially in-order through each +// stage each time the app is launched. This enum might expand in the future but +// the start and last stages will always keep the same label and relative +// position. +typedef NS_ENUM(NSUInteger, InitStage) { + // The first stage when starting the initialization. The label and value of + // this enum item should not change. + InitStageStart = 0, + // The app is in safe mode. + InitStageSafeMode, + // The final stage before being done with initialization. The label and + // relative position (always last) of this enum item should not change. + // The value may change when inserting enum items between Start and Final. + InitStageFinal +}; + +@protocol AppStateObserver <NSObject> + +@optional + +// Called when a scene is connected. +// On iOS 12, called when the mainSceneState is set. +- (void)appState:(AppState*)appState sceneConnected:(SceneState*)sceneState; + +// Called when the first scene initializes its UI. +- (void)appState:(AppState*)appState + firstSceneHasInitializedUI:(SceneState*)sceneState; + +// Called after the app exits safe mode. +- (void)appStateDidExitSafeMode:(AppState*)appState; + +// Called when |AppState.lastTappedWindow| changes. +- (void)appState:(AppState*)appState lastTappedWindowChanged:(UIWindow*)window; + +// Called when the app is about to transition to |initStage|. The init stage of +// the app at that moment is still |initStage| - 1. +- (void)appState:(AppState*)appState + willTransitionToInitStage:(InitStage)initStage; + +// Called right after the app is transitioned to the |initStage|. +- (void)appState:(AppState*)appState + didTransitionToInitStage:(InitStage)initStage; + +@end + +#endif // IOS_CHROME_APP_APPLICATION_DELEGATE_APP_STATE_OBSERVER_H_
diff --git a/ios/chrome/app/application_delegate/app_state_unittest.mm b/ios/chrome/app/application_delegate/app_state_unittest.mm index 95dd9e4..ed68254a 100644 --- a/ios/chrome/app/application_delegate/app_state_unittest.mm +++ b/ios/chrome/app/application_delegate/app_state_unittest.mm
@@ -11,6 +11,7 @@ #import "base/ios/ios_util.h" #import "base/test/task_environment.h" #import "ios/chrome/app/app_startup_parameters.h" +#import "ios/chrome/app/application_delegate/app_state_observer.h" #import "ios/chrome/app/application_delegate/app_state_testing.h" #import "ios/chrome/app/application_delegate/browser_launcher.h" #import "ios/chrome/app/application_delegate/fake_startup_information.h" @@ -21,6 +22,8 @@ #import "ios/chrome/app/application_delegate/tab_switching.h" #import "ios/chrome/app/application_delegate/user_activity_handler.h" #import "ios/chrome/app/main_application_delegate.h" +#import "ios/chrome/app/safe_mode_app_state_agent.h" +#include "ios/chrome/app/safe_mode_app_state_agent.h" #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" #include "ios/chrome/browser/chrome_url_constants.h" #import "ios/chrome/browser/device_sharing/device_sharing_manager.h" @@ -61,8 +64,11 @@ // Exposes private safe mode start/stop methods. @interface AppState (Private) +@property(nonatomic, strong) SafeModeCoordinator* safeModeCoordinator; + - (void)startSafeMode; - (void)stopSafeMode; +- (void)coordinatorDidExitSafeMode:(SafeModeCoordinator*)coordinator; @end #pragma mark - Class definition. @@ -134,6 +140,7 @@ class AppStateTest : public BlockCleanupTest { protected: AppStateTest() { + // Init mocks. browser_launcher_mock_ = [OCMockObject mockForProtocol:@protocol(BrowserLauncher)]; startup_information_mock_ = @@ -143,6 +150,8 @@ main_application_delegate_ = [OCMockObject mockForClass:[MainApplicationDelegate class]]; window_ = [OCMockObject mockForClass:[UIWindow class]]; + app_state_observer_mock_ = + [OCMockObject mockForProtocol:@protocol(AppStateObserver)]; interface_provider_ = [[StubBrowserInterfaceProvider alloc] init]; } @@ -289,6 +298,7 @@ id getConnectionInformationMock() { return connection_information_mock_; } id getApplicationDelegateMock() { return main_application_delegate_; } id getWindowMock() { return window_; } + id getAppStateObserverMock() { return app_state_observer_mock_; } StubBrowserInterfaceProvider* getInterfaceProvider() { return interface_provider_; } @@ -306,6 +316,7 @@ id startup_information_mock_; id main_application_delegate_; id window_; + id app_state_observer_mock_; StubBrowserInterfaceProvider* interface_provider_; ScenesBlock connected_scenes_swizzle_block_; DecisionBlock safe_mode_swizzle_block_; @@ -354,6 +365,10 @@ // Test. EXPECT_TRUE(result); EXPECT_OCMOCK_VERIFY(browserLauncherMock); + + // Verify the launch stage is still at the starting point when the app is in + // background. + EXPECT_EQ(InitStageStart, appState.initStage); } // Tests that if the application is active and Safe Mode should be activated @@ -377,15 +392,44 @@ [[windowMock expect] makeKeyAndVisible]; AppState* appState = getAppStateWithMock(); + ASSERT_FALSE([appState isInSafeMode]); + + id appStateObserverMock = getAppStateObserverMock(); + // Expected app state observer calls when starting the init stages. + [[appStateObserverMock expect] appState:appState + willTransitionToInitStage:InitStageStart]; + [[appStateObserverMock expect] appState:appState + didTransitionToInitStage:InitStageStart]; + // Expected app state observer calls when transitioning from Start to Safe + // Mode. + [[appStateObserverMock expect] appState:appState + willTransitionToInitStage:InitStageSafeMode]; + [[appStateObserverMock expect] appState:appState + didTransitionToInitStage:InitStageSafeMode]; + // Expected app state observer calls when transitioning from Safe Mode to + // Final. + [[appStateObserverMock expect] appState:appState + willTransitionToInitStage:InitStageFinal]; + [[appStateObserverMock expect] appState:appState + didTransitionToInitStage:InitStageFinal]; + [appState addObserver:appStateObserverMock]; + + [appState addAgent:[[SafeModeAppAgent alloc] init]]; id browserLauncherMock = getBrowserLauncherMock(); BrowserInitializationStageType stageBasic = INITIALIZATION_STAGE_BASIC; [[browserLauncherMock expect] startUpBrowserToStage:stageBasic]; [[browserLauncherMock expect] setLaunchOptions:launchOptions]; - swizzleSafeModeShouldStart(YES); + // Expected calls on AppState#coordinatorDidExitSafeMode. + [[appStateObserverMock expect] appStateDidExitSafeMode:appState]; + [[browserLauncherMock expect] + startUpBrowserToStage:INITIALIZATION_STAGE_FOREGROUND]; + id applicationDelegateMock = getApplicationDelegateMock(); + [[applicationDelegateMock expect] + applicationDidBecomeActive:[UIApplication sharedApplication]]; - ASSERT_FALSE([appState isInSafeMode]); + swizzleSafeModeShouldStart(YES); appState.mainSceneState.activationLevel = SceneActivationLevelForegroundActive; @@ -395,18 +439,25 @@ stateBackground:NO]; if (base::ios::IsMultiwindowSupported()) { - [appState startSafeMode]; + // Start the safe mode by transitioning the scene to foreground again after + // #requiresHandlingAfterLaunchWithOptions which starts the safe mode. + appState.mainSceneState.activationLevel = + SceneActivationLevelForegroundActive; } - // Test. EXPECT_TRUE(result); EXPECT_TRUE([appState isInSafeMode]); - EXPECT_OCMOCK_VERIFY(browserLauncherMock); - EXPECT_OCMOCK_VERIFY(windowMock); - if (base::ios::IsMultiwindowSupported()) { - [appState stopSafeMode]; - } + // Stop safe mode. + [appState coordinatorDidExitSafeMode:appState.safeModeCoordinator]; + + // Verify that the dependencies are called properly during the app journey. + EXPECT_OCMOCK_VERIFY(windowMock); + EXPECT_OCMOCK_VERIFY(browserLauncherMock); + EXPECT_OCMOCK_VERIFY(appStateObserverMock); + EXPECT_OCMOCK_VERIFY(applicationDelegateMock); + + EXPECT_EQ(InitStageFinal, appState.initStage); } // Tests that if the application is active @@ -423,6 +474,33 @@ [[[getWindowMock() stub] andReturn:nil] rootViewController]; AppState* appState = getAppStateWithMock(); + ASSERT_FALSE([appState isInSafeMode]); + + id appStateObserverMock = getAppStateObserverMock(); + // Expected app state observer calls when starting the init stages. + [[appStateObserverMock expect] appState:appState + willTransitionToInitStage:InitStageStart]; + [[appStateObserverMock expect] appState:appState + didTransitionToInitStage:InitStageStart]; + // Expected app state observer calls when transitioning from Start to Safe + // Mode. + [[appStateObserverMock expect] appState:appState + willTransitionToInitStage:InitStageSafeMode]; + [[appStateObserverMock expect] appState:appState + didTransitionToInitStage:InitStageSafeMode]; + // Expected app state observer calls when transitioning from Safe Mode to + // Final. + [[appStateObserverMock expect] appState:appState + willTransitionToInitStage:InitStageFinal]; + [[appStateObserverMock expect] appState:appState + didTransitionToInitStage:InitStageFinal]; + [appState addObserver:appStateObserverMock]; + + [appState addAgent:[[SafeModeAppAgent alloc] init]]; + + id applicationDelegateMock = getApplicationDelegateMock(); + [[applicationDelegateMock expect] + applicationDidBecomeActive:[UIApplication sharedApplication]]; id browserLauncherMock = getBrowserLauncherMock(); BrowserInitializationStageType stageBasic = INITIALIZATION_STAGE_BASIC; @@ -440,7 +518,11 @@ // Test. EXPECT_TRUE(result); + EXPECT_EQ(InitStageFinal, appState.initStage); + + // Verify that the dependencies were called properly. EXPECT_OCMOCK_VERIFY(browserLauncherMock); + EXPECT_OCMOCK_VERIFY(appStateObserverMock); } using AppStateNoFixtureTest = PlatformTest; @@ -802,6 +884,8 @@ [[window expect] makeKeyAndVisible]; AppState* appState = getAppStateWithRealWindow(window); + [appState addAgent:[[SafeModeAppAgent alloc] init]]; + // Starting safe mode will call makeKeyAndVisible on the window. [[window expect] makeKeyAndVisible]; appState.mainSceneState.activationLevel = @@ -809,13 +893,18 @@ appState.mainSceneState.window = window; // Actions. - [getAppStateWithMock() applicationWillEnterForeground:application - metricsMediator:metricsMediator - memoryHelper:memoryHelper]; + [appState applicationWillEnterForeground:application + metricsMediator:metricsMediator + memoryHelper:memoryHelper]; // Tests. EXPECT_OCMOCK_VERIFY(window); - EXPECT_TRUE([getAppStateWithMock() isInSafeMode]); + + // Verify that the app is still in safe mode after initializing the UI when + // entering foreground from background. + EXPECT_TRUE([appState isInSafeMode]); + + EXPECT_EQ(InitStageFinal, appState.initStage); } // Tests that -applicationDidEnterBackground calls the metrics mediator.
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm index 6c029f1..fd15a82 100644 --- a/ios/chrome/app/main_controller.mm +++ b/ios/chrome/app/main_controller.mm
@@ -34,6 +34,7 @@ #import "ios/chrome/app/content_suggestions_scheduler_app_state_agent.h" #import "ios/chrome/app/deferred_initialization_runner.h" #import "ios/chrome/app/memory_monitor.h" +#import "ios/chrome/app/safe_mode_app_state_agent.h" #import "ios/chrome/app/spotlight/spotlight_manager.h" #include "ios/chrome/app/startup/chrome_app_startup_parameters.h" #include "ios/chrome/app/startup/chrome_main_starter.h" @@ -616,6 +617,7 @@ [appState addAgent:[[AppMetricsAppStateAgent alloc] init]]; [appState addAgent:[[ContentSuggestionsSchedulerAppAgent alloc] init]]; [appState addAgent:[[IncognitoUsageAppStateAgent alloc] init]]; + [appState addAgent:[[SafeModeAppAgent alloc] init]]; // Create the window accessibility agent only when multuple windows are // possible.
diff --git a/ios/chrome/app/safe_mode_app_state_agent.h b/ios/chrome/app/safe_mode_app_state_agent.h new file mode 100644 index 0000000..1aafd462 --- /dev/null +++ b/ios/chrome/app/safe_mode_app_state_agent.h
@@ -0,0 +1,17 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_APP_SAFE_MODE_APP_STATE_AGENT_H_ +#define IOS_CHROME_APP_SAFE_MODE_APP_STATE_AGENT_H_ + +#import "ios/chrome/app/application_delegate/app_state_agent.h" + +@class AppState; + +// App state agent that triggers the safe mode stage when needed. +@interface SafeModeAppAgent : NSObject <AppStateAgent> + +@end + +#endif // IOS_CHROME_APP_SAFE_MODE_APP_STATE_AGENT_H_
diff --git a/ios/chrome/app/safe_mode_app_state_agent.mm b/ios/chrome/app/safe_mode_app_state_agent.mm new file mode 100644 index 0000000..26d802a --- /dev/null +++ b/ios/chrome/app/safe_mode_app_state_agent.mm
@@ -0,0 +1,48 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/app/safe_mode_app_state_agent.h" + +#include "base/check.h" +#import "ios/chrome/app/application_delegate/app_state.h" +#import "ios/chrome/app/application_delegate/app_state_observer.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@interface SafeModeAppAgent () <AppStateObserver> + +// The app state for the app. +@property(nonatomic, weak, readonly) AppState* appState; + +@end + +@implementation SafeModeAppAgent + +#pragma mark - AppStateAgent + +- (void)setAppState:(AppState*)appState { + // This should only be called once! + DCHECK(!_appState); + + _appState = appState; + [appState addObserver:self]; +} + +#pragma mark - AppStateObserver + +- (void)appState:(AppState*)appState + didTransitionToInitStage:(InitStage)initStage { + if (initStage == InitStageStart) { + // TODO(crbug.com/1178809): Move this responsibility to a specific agent. + // Handle the transition out of the Start stage. + [self.appState queueTransitionToNextInitStage]; + } else if (initStage == InitStageSafeMode) { + // TODO(crbug.com/1178809): Trigger safe mode from here. + [self.appState queueTransitionToNextInitStage]; + } +} + +@end
diff --git a/ios/chrome/browser/resources/Settings.bundle/Experimental.plist b/ios/chrome/browser/resources/Settings.bundle/Experimental.plist index 8f996bd..aa69029 100644 --- a/ios/chrome/browser/resources/Settings.bundle/Experimental.plist +++ b/ios/chrome/browser/resources/Settings.bundle/Experimental.plist
@@ -24,6 +24,16 @@ </dict> <dict> <key>Type</key> + <string>PSToggleSwitchSpecifier</string> + <key>Title</key> + <string>Reset Notice Card</string> + <key>Key</key> + <string>ResetNoticeCard</string> + <key>DefaultValue</key> + <false/> + </dict> + <dict> + <key>Type</key> <string>PSGroupSpecifier</string> <key>Title</key> <string>UI Settings</string>
diff --git a/ios/chrome/browser/system_flags.h b/ios/chrome/browser/system_flags.h index 4a1fe78..9db3af3c 100644 --- a/ios/chrome/browser/system_flags.h +++ b/ios/chrome/browser/system_flags.h
@@ -47,6 +47,11 @@ // Returns the URL for the alternative Discover Feed server. std::string getAlternateDiscoverFeedServerURL(); +// Returns true if the prefs for the notice card views count and clicks count +// should be reset to zero on feed start. +// TODO(crbug.com/1189232): Remove after launch. +bool ShouldResetNoticeCardOnFeedStart(); + // Whether memory debugging tools are enabled. bool IsMemoryDebuggingEnabled();
diff --git a/ios/chrome/browser/system_flags.mm b/ios/chrome/browser/system_flags.mm index 044733e..ef17d31d 100644 --- a/ios/chrome/browser/system_flags.mm +++ b/ios/chrome/browser/system_flags.mm
@@ -89,6 +89,11 @@ return base::SysNSStringToUTF8(alternateServerURL); } +bool ShouldResetNoticeCardOnFeedStart() { + return [[NSUserDefaults standardUserDefaults] + boolForKey:@"ResetNoticeCard"]; +} + bool IsMemoryDebuggingEnabled() { // Always return true for Chromium builds, but check the user default for // official builds because memory debugging should never be enabled on stable.
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm index b20f2588..9d6c1ba 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm
@@ -421,8 +421,8 @@ [self.identityDiscButton.trailingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.trailingAnchor constant:-ntp_home::kIdentityAvatarMargin], - [self.identityDiscButton.centerYAnchor - constraintEqualToAnchor:self.logoVendor.view.centerYAnchor], + [self.identityDiscButton.topAnchor + constraintEqualToAnchor:self.logoVendor.view.topAnchor], ]; self.identityDiscLogoPortraitConstraints = @[ [self.identityDiscButton.heightAnchor @@ -430,8 +430,8 @@ [self.identityDiscButton.widthAnchor constraintEqualToConstant:dimension], [self.identityDiscButton.trailingAnchor constraintEqualToAnchor:self.fakeOmnibox.trailingAnchor], - [self.identityDiscButton.centerYAnchor - constraintEqualToAnchor:self.logoVendor.view.centerYAnchor], + [self.identityDiscButton.topAnchor + constraintEqualToAnchor:self.logoVendor.view.topAnchor], ]; [self updateIdentityDiscLogoConstraints]; }
diff --git a/ios/chrome/browser/ui/infobars/translate_infobar_egtest.mm b/ios/chrome/browser/ui/infobars/translate_infobar_egtest.mm index c5c574c..801c8af 100644 --- a/ios/chrome/browser/ui/infobars/translate_infobar_egtest.mm +++ b/ios/chrome/browser/ui/infobars/translate_infobar_egtest.mm
@@ -718,7 +718,7 @@ } // Tests that the target language can be changed. TODO(crbug.com/1046629): -// implement test for changing source langauge. +// implement test for changing source language. - (void)testInfobarChangeTargetLanguage { // TODO(crbug.com/1116012): This test is failing flaky on iOS14. if (@available(iOS 14, *)) {
diff --git a/ios/components/security_interstitials/OWNERS b/ios/components/security_interstitials/OWNERS index 233a0ea..78f00191 100644 --- a/ios/components/security_interstitials/OWNERS +++ b/ios/components/security_interstitials/OWNERS
@@ -1,2 +1,3 @@ ajuma@chromium.org livvielin@chromium.org +meacer@chromium.org
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1 index 14024df..36158ff 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@ -70e77cb35c58de6693356fcf9a6f384a50da3ef5 \ No newline at end of file +9b438e95b482b83c7ae096b5afd1721b1a50758a \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1 index dcfe9cda..126acbe 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@ -e3f24663c0957236353f1e1dad5c7f4417eae5be \ No newline at end of file +f8da1f28be68712961abba6e8f26c62607d0e34a \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.arm64.zip.sha1 index 3d4b58f..31c69d2 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.arm64.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@ -2f8661337a074bfc9fd5f1932e273d647e388b2b \ No newline at end of file +848872ce8642d00623bde9a516d659181e3121ab \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.x64.zip.sha1 index e463560..1d039db0 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.x64.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@ -bd6a44349addc2c07d9b452e021d9fd005208f2c \ No newline at end of file +0718b675d3af2162abe6a469aee4df9df5ee81f5 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1 index ecdf669..28a2256 100644 --- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@ -1f4c7e89852343e0d0633613d5bb250c7adceab6 \ No newline at end of file +6bc6cf8dfda89bf0ee1e866911f5a7e6dbf2063c \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1 index 0ee3986d..3c9cc78 100644 --- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@ -8e08472a0c9b205a411fde56afff21c791dda162 \ No newline at end of file +5394113d19e7177373d044afc9d37bc041436b21 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1 index 64ac7c5..2cbbe0ac7 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@ -b96084a447b21f54b645407e032011d3df25f485 \ No newline at end of file +93806748177178ac91a660014863ea507c536e43 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1 index a6afdc18..7fd99b2 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@ -4ef14f914340fbddee158dcd2dbefbe6e42db3f1 \ No newline at end of file +941d9df1c0e3c3d296062316d72435f79c38677d \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1 index a9b8647..8226b15 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@ -14857a6a127c0b6d2782ea3dd9505c97abd6d25f \ No newline at end of file +c4b6718178c8783b838229beea2a66b042d514e4 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1 index cefb490..5ba7298 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@ -a788983e472722474a7faada8dfd16c73f3ed886 \ No newline at end of file +55b923d64c82bd6bcfecb41efe3b2d6208f6bef4 \ No newline at end of file
diff --git a/ios/web_view/internal/translate/cwv_translation_controller_internal.h b/ios/web_view/internal/translate/cwv_translation_controller_internal.h index 0788063..2f09c20 100644 --- a/ios/web_view/internal/translate/cwv_translation_controller_internal.h +++ b/ios/web_view/internal/translate/cwv_translation_controller_internal.h
@@ -34,7 +34,7 @@ // Called to keep this class informed of the current translate progress. // |step| the state of current translation. // |sourceLanguage| the source language associated with the current |step|. -// |targetLanguage| the target langauge associated with the current |step|. +// |targetLanguage| the target language associated with the current |step|. // |errorType| the error, if any for the current |step|. // |triggeredFromMenu| should be true if this was a result from user action. - (void)updateTranslateStep:(translate::TranslateStep)step
diff --git a/net/http2/platform/impl/http2_bug_tracker_impl.h b/net/http2/platform/impl/http2_bug_tracker_impl.h index 8ee3bd0..ed3fb8d 100644 --- a/net/http2/platform/impl/http2_bug_tracker_impl.h +++ b/net/http2/platform/impl/http2_bug_tracker_impl.h
@@ -9,6 +9,10 @@ #define HTTP2_BUG_IMPL LOG(DFATAL) #define HTTP2_BUG_IF_IMPL LOG_IF(DFATAL, (condition)) + +#define HTTP2_BUG_V2_IMPL(bug_id) LOG(DFATAL) +#define HTTP2_BUG_IF_V2_IMPL(bug_id, condition) LOG_IF(DFATAL, (condition)) + #define FLAGS_http2_always_log_bugs_for_tests_IMPL (true) #endif // NET_HTTP2_PLATFORM_IMPL_HTTP2_BUG_TRACKER_IMPL_H_
diff --git a/net/quic/mock_decrypter.cc b/net/quic/mock_decrypter.cc index 51350fd..6950369a 100644 --- a/net/quic/mock_decrypter.cc +++ b/net/quic/mock_decrypter.cc
@@ -52,12 +52,12 @@ } bool MockDecrypter::SetPreliminaryKey(absl::string_view key) { - QUIC_BUG << "Should not be called"; + LOG(DFATAL) << "Should not be called"; return false; } bool MockDecrypter::SetDiversificationNonce(const DiversificationNonce& nonce) { - QUIC_BUG << "Should not be called"; + LOG(DFATAL) << "Should not be called"; return true; }
diff --git a/net/quic/platform/impl/quic_bug_tracker_impl.h b/net/quic/platform/impl/quic_bug_tracker_impl.h index ac6f5a02..d421e66 100644 --- a/net/quic/platform/impl/quic_bug_tracker_impl.h +++ b/net/quic/platform/impl/quic_bug_tracker_impl.h
@@ -6,10 +6,10 @@ #include "net/third_party/quiche/src/quic/platform/api/quic_logging.h" -#define QUIC_BUG_IMPL QUIC_LOG(DFATAL) -#define QUIC_BUG_IF_IMPL(condition) QUIC_LOG_IF(DFATAL, condition) -#define QUIC_PEER_BUG_IMPL QUIC_LOG(ERROR) -#define QUIC_PEER_BUG_IF_IMPL(condition) QUIC_LOG_IF(ERROR, condition) +#define QUIC_BUG_IMPL(bug_id) QUIC_LOG(DFATAL) +#define QUIC_BUG_IF_IMPL(bug_id, condition) QUIC_LOG_IF(DFATAL, condition) +#define QUIC_PEER_BUG_IMPL(bug_id) QUIC_LOG(ERROR) +#define QUIC_PEER_BUG_IF_IMPL(bug_id, condition) QUIC_LOG_IF(ERROR, condition) #define QUIC_BUG_V2_IMPL(bug_id) QUIC_LOG(DFATAL) #define QUIC_BUG_IF_V2_IMPL(bug_id, condition) QUIC_LOG_IF(DFATAL, condition)
diff --git a/net/quic/platform/impl/quic_linux_socket_utils.h b/net/quic/platform/impl/quic_linux_socket_utils.h index 7f6e7f16..a5ac07ff 100644 --- a/net/quic/platform/impl/quic_linux_socket_utils.h +++ b/net/quic/platform/impl/quic_linux_socket_utils.h
@@ -227,8 +227,9 @@ return WriteResult(WRITE_STATUS_OK, mhdr->num_bytes_sent(rc)); } else if (rc == 0) { - QUIC_BUG << "sendmmsg returned 0, returning WRITE_STATUS_ERROR. errno: " - << errno; + LOG(DFATAL) + << "sendmmsg returned 0, returning WRITE_STATUS_ERROR. errno: " + << errno; errno = EIO; }
diff --git a/net/quic/platform/impl/quic_socket_address_impl.cc b/net/quic/platform/impl/quic_socket_address_impl.cc index 9b7a6708..50668ab 100644 --- a/net/quic/platform/impl/quic_socket_address_impl.cc +++ b/net/quic/platform/impl/quic_socket_address_impl.cc
@@ -75,7 +75,7 @@ } QuicSocketAddressImpl QuicSocketAddressImpl::Normalized() const { - QUIC_BUG << "QuicSocketAddressImpl::Normalized() is not implemented."; + LOG(DFATAL) << "QuicSocketAddressImpl::Normalized() is not implemented."; return QuicSocketAddressImpl(); }
diff --git a/net/quic/platform/impl/quic_socket_utils.cc b/net/quic/platform/impl/quic_socket_utils.cc index 97f3b85..2922dcd 100644 --- a/net/quic/platform/impl/quic_socket_utils.cc +++ b/net/quic/platform/impl/quic_socket_utils.cc
@@ -237,8 +237,8 @@ } if (hdr.msg_flags & MSG_CTRUNC) { - QUIC_BUG << "Incorrectly set control length: " << hdr.msg_controllen - << ", expected " << sizeof(cbuf); + LOG(DFATAL) << "Incorrectly set control length: " << hdr.msg_controllen + << ", expected " << sizeof(cbuf); return -1; } @@ -368,7 +368,7 @@ in6_pktinfo* pktinfo = static_cast<in6_pktinfo*>(cmsg_data); memcpy(&pktinfo->ipi6_addr, address_str.c_str(), address_str.length()); } else { - QUIC_BUG << "Unrecognized IPAddress"; + LOG(DFATAL) << "Unrecognized IPAddress"; } }
diff --git a/net/quic/quic_test_packet_maker.cc b/net/quic/quic_test_packet_maker.cc index 17c26bf..4f23bdc 100644 --- a/net/quic/quic_test_packet_maker.cc +++ b/net/quic/quic_test_packet_maker.cc
@@ -1111,7 +1111,7 @@ QuicTestPacketMaker::MakeStatelessResetPacket() { auto connection_id = quic::test::TestConnectionId(); return quic::QuicFramer::BuildIetfStatelessResetPacket( - connection_id, + connection_id, quic::QuicFramer::GetMinStatelessResetPacketLength(), quic::QuicUtils::GenerateStatelessResetToken(connection_id)); } @@ -1143,7 +1143,7 @@ long_header_type_ = quic::INVALID_PACKET_TYPE; break; default: - QUIC_BUG << quic::EncryptionLevelToString(level); + LOG(DFATAL) << quic::EncryptionLevelToString(level); long_header_type_ = quic::INVALID_PACKET_TYPE; } }
diff --git a/net/spdy/platform/impl/spdy_bug_tracker_impl.h b/net/spdy/platform/impl/spdy_bug_tracker_impl.h index 2d4bab9..931e1052 100644 --- a/net/spdy/platform/impl/spdy_bug_tracker_impl.h +++ b/net/spdy/platform/impl/spdy_bug_tracker_impl.h
@@ -7,8 +7,12 @@ #include "base/logging.h" -#define SPDY_BUG_IMPL LOG(DFATAL) -#define SPDY_BUG_IF_IMPL(condition) LOG_IF(DFATAL, (condition)) +#define SPDY_BUG_IMPL(bug_id) LOG(DFATAL) +#define SPDY_BUG_IF_IMPL(bug_id, condition) LOG_IF(DFATAL, (condition)) + +#define SPDY_BUG_V2_IMPL(bug_id) LOG(DFATAL) +#define SPDY_BUG_IF_V2_IMPL(bug_id, condition) LOG_IF(DFATAL, (condition)) + #define FLAGS_spdy_always_log_bugs_for_tests_impl (true) #endif // NET_SPDY_PLATFORM_IMPL_SPDY_BUG_TRACKER_IMPL_H_
diff --git a/net/third_party/quiche/BUILD.gn b/net/third_party/quiche/BUILD.gn index 3f84328..4985dce8 100644 --- a/net/third_party/quiche/BUILD.gn +++ b/net/third_party/quiche/BUILD.gn
@@ -123,8 +123,6 @@ "src/http2/hpack/decoder/hpack_whole_entry_listener.cc", "src/http2/hpack/decoder/hpack_whole_entry_listener.h", "src/http2/hpack/hpack_static_table_entries.inc", - "src/http2/hpack/hpack_string.cc", - "src/http2/hpack/hpack_string.h", "src/http2/hpack/http2_hpack_constants.cc", "src/http2/hpack/http2_hpack_constants.h", "src/http2/hpack/huffman/hpack_huffman_decoder.cc", @@ -360,6 +358,8 @@ "src/quic/core/http/spdy_server_push_utils.h", "src/quic/core/http/spdy_utils.cc", "src/quic/core/http/spdy_utils.h", + "src/quic/core/http/web_transport_http3.cc", + "src/quic/core/http/web_transport_http3.h", "src/quic/core/legacy_quic_stream_id_manager.cc", "src/quic/core/legacy_quic_stream_id_manager.h", "src/quic/core/packet_number_indexed_queue.h", @@ -953,6 +953,8 @@ "src/quic/test_tools/quic_stream_sequencer_peer.h", "src/quic/test_tools/quic_sustained_bandwidth_recorder_peer.cc", "src/quic/test_tools/quic_sustained_bandwidth_recorder_peer.h", + "src/quic/test_tools/quic_test_backend.cc", + "src/quic/test_tools/quic_test_backend.h", "src/quic/test_tools/quic_test_utils.cc", "src/quic/test_tools/quic_test_utils.h", "src/quic/test_tools/quic_time_wait_list_manager_peer.cc", @@ -1228,7 +1230,6 @@ "src/http2/hpack/decoder/hpack_string_collector.h", "src/http2/hpack/decoder/hpack_string_decoder_test.cc", "src/http2/hpack/decoder/hpack_whole_entry_buffer_test.cc", - "src/http2/hpack/hpack_string_test.cc", "src/http2/hpack/http2_hpack_constants_test.cc", "src/http2/hpack/huffman/hpack_huffman_decoder_test.cc", "src/http2/hpack/huffman/hpack_huffman_encoder_test.cc",
diff --git a/net/tools/epoll_server/platform/impl/epoll_bug_impl.h b/net/tools/epoll_server/platform/impl/epoll_bug_impl.h index 696a960..ec84dab 100644 --- a/net/tools/epoll_server/platform/impl/epoll_bug_impl.h +++ b/net/tools/epoll_server/platform/impl/epoll_bug_impl.h
@@ -7,6 +7,7 @@ #include "net/tools/epoll_server/platform/impl/epoll_logging_impl.h" -#define EPOLL_BUG_IMPL EPOLL_LOG_IMPL(DFATAL) +#define EPOLL_BUG_IMPL(bug_id) EPOLL_LOG_IMPL(DFATAL) +#define EPOLL_BUG_V2_IMPL(bug_id) EPOLL_LOG_IMPL(DFATAL) #endif // NET_TOOLS_EPOLL_SERVER_PLATFORM_IMPL_EPOLL_BUG_IMPL_H_
diff --git a/remoting/host/curtain_mode_linux.cc b/remoting/host/curtain_mode_linux.cc index 5c09359..cf815a5 100644 --- a/remoting/host/curtain_mode_linux.cc +++ b/remoting/host/curtain_mode_linux.cc
@@ -50,14 +50,14 @@ // Try to identify a virtual session. Since there's no way to tell from the // vendor string, we check for known virtual input devices. // TODO(rmsousa): Find a similar way to determine that the *output* is secure. - x11::Connection connection; - if (!connection.xinput().present()) { + x11::Connection* connection = x11::Connection::Get(); + if (!connection->xinput().present()) { // If XInput is not available, assume it is not a virtual session. LOG(ERROR) << "X Input extension not available"; return false; } - auto devices = connection.xinput().ListInputDevices().Sync(); + auto devices = connection->xinput().ListInputDevices().Sync(); if (!devices) { LOG(ERROR) << "ListInputDevices failed"; return false;
diff --git a/remoting/host/desktop_resizer_x11.cc b/remoting/host/desktop_resizer_x11.cc index 5b4036d..fe10ee9f 100644 --- a/remoting/host/desktop_resizer_x11.cc +++ b/remoting/host/desktop_resizer_x11.cc
@@ -106,8 +106,9 @@ } DesktopResizerX11::DesktopResizerX11() - : randr_(&connection_.randr()), - screen_(&connection_.default_screen()), + : connection_(x11::Connection::Get()), + randr_(&connection_->randr()), + screen_(&connection_->default_screen()), root_(screen_->root), exact_resize_(base::CommandLine::ForCurrentProcess()->HasSwitch( "server-supports-exact-resize")) { @@ -127,11 +128,11 @@ // Process pending events so that the connection setup data is updated // with the correct display metrics. if (has_randr_) - connection_.DispatchAll(); + connection_->DispatchAll(); ScreenResolution result( - webrtc::DesktopSize(connection_.default_screen().width_in_pixels, - connection_.default_screen().height_in_pixels), + webrtc::DesktopSize(connection_->default_screen().width_in_pixels, + connection_->default_screen().height_in_pixels), webrtc::DesktopVector(kDefaultDPI, kDefaultDPI)); return result; } @@ -177,11 +178,11 @@ // error, for example if xrandr has been used to add a mode with the same // name as our temporary mode, or to remove the "client resolution" mode. We // don't want to terminate the process if this happens. - x11::ScopedIgnoreErrors ignore_errors(&connection_); + x11::ScopedIgnoreErrors ignore_errors(connection_); // Grab the X server while we're changing the display resolution. This ensures // that the display configuration doesn't change under our feet. - ScopedXGrabServer grabber(&connection_); + ScopedXGrabServer grabber(connection_); if (exact_resize_) SetResolutionNewMode(resolution);
diff --git a/remoting/host/desktop_resizer_x11.h b/remoting/host/desktop_resizer_x11.h index 5982353..a684408 100644 --- a/remoting/host/desktop_resizer_x11.h +++ b/remoting/host/desktop_resizer_x11.h
@@ -75,7 +75,7 @@ // its resolution. void SwitchToMode(const char* name); - x11::Connection connection_; + x11::Connection* connection_; x11::RandR* const randr_ = nullptr; const x11::Screen* const screen_ = nullptr; x11::Window root_;
diff --git a/remoting/host/input_monitor/BUILD.gn b/remoting/host/input_monitor/BUILD.gn index 84e6ea623..42f4503 100644 --- a/remoting/host/input_monitor/BUILD.gn +++ b/remoting/host/input_monitor/BUILD.gn
@@ -39,6 +39,8 @@ if (use_x11 && (!is_chromeos_ash || use_ozone)) { sources += [ "local_hotkey_input_monitor_x11.cc", + "local_input_monitor_x11_common.cc", + "local_input_monitor_x11_common.h", "local_keyboard_input_monitor_x11.cc", "local_mouse_input_monitor_x11.cc", ]
diff --git a/remoting/host/input_monitor/local_hotkey_input_monitor_x11.cc b/remoting/host/input_monitor/local_hotkey_input_monitor_x11.cc index 7d47d3e4..f51fff5a4 100644 --- a/remoting/host/input_monitor/local_hotkey_input_monitor_x11.cc +++ b/remoting/host/input_monitor/local_hotkey_input_monitor_x11.cc
@@ -18,7 +18,7 @@ #include "base/macros.h" #include "base/sequence_checker.h" #include "base/single_thread_task_runner.h" -#include "ui/events/devices/x11/xinput_util.h" +#include "remoting/host/input_monitor/local_input_monitor_x11_common.h" #include "ui/gfx/x/connection.h" #include "ui/gfx/x/event.h" #include "ui/gfx/x/future.h" @@ -80,7 +80,7 @@ // True when Ctrl is pressed. bool ctrl_pressed_ = false; - std::unique_ptr<x11::Connection> connection_; + x11::Connection* connection_ = nullptr; DISALLOW_COPY_AND_ASSIGN(Core); }; @@ -132,29 +132,24 @@ base::BindOnce(&Core::StopOnInputThread, this)); } -LocalHotkeyInputMonitorX11::Core::~Core() { - DCHECK(!connection_); -} +LocalHotkeyInputMonitorX11::Core::~Core() = default; void LocalHotkeyInputMonitorX11::Core::StartOnInputThread() { DCHECK(input_task_runner_->BelongsToCurrentThread()); DCHECK(!connection_); - // TODO(jamiewalch): We should pass the connection in. - connection_ = std::make_unique<x11::Connection>(); + connection_ = x11::Connection::Get(); connection_->AddEventObserver(this); if (!connection_->xinput().present()) { - LOG(ERROR) << "X Record extension not available."; + LOG(ERROR) << "X Input extension not available."; return; } // Let the server know the client XInput version. connection_->xinput().XIQueryVersion( {x11::Input::major_version, x11::Input::minor_version}); - x11::Input::XIEventMask mask{}; - ui::SetXinputMask(&mask, x11::Input::RawDeviceEvent::RawKeyPress); - ui::SetXinputMask(&mask, x11::Input::RawDeviceEvent::RawKeyRelease); + auto mask = CommonXIEventMaskForRootWindow(); connection_->xinput().XISelectEvents( {connection_->default_root(), {{x11::Input::DeviceId::AllMaster, {mask}}}}); @@ -173,7 +168,6 @@ void LocalHotkeyInputMonitorX11::Core::StopOnInputThread() { DCHECK(input_task_runner_->BelongsToCurrentThread()); controller_.reset(); - connection_.reset(); } void LocalHotkeyInputMonitorX11::Core::OnConnectionData() { @@ -193,8 +187,10 @@ // selected them. if (!raw) return; - DCHECK(raw->opcode == x11::Input::RawDeviceEvent::RawKeyPress || - raw->opcode == x11::Input::RawDeviceEvent::RawKeyRelease); + if (raw->opcode != x11::Input::RawDeviceEvent::RawKeyPress && + raw->opcode != x11::Input::RawDeviceEvent::RawKeyRelease) { + return; + } const bool down = raw->opcode == x11::Input::RawDeviceEvent::RawKeyPress; const auto key_sym =
diff --git a/remoting/host/input_monitor/local_input_monitor_x11_common.cc b/remoting/host/input_monitor/local_input_monitor_x11_common.cc new file mode 100644 index 0000000..82809f4c --- /dev/null +++ b/remoting/host/input_monitor/local_input_monitor_x11_common.cc
@@ -0,0 +1,17 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "remoting/host/input_monitor/local_input_monitor_x11_common.h" + +namespace remoting { + +x11::Input::XIEventMask CommonXIEventMaskForRootWindow() { + x11::Input::XIEventMask mask{}; + ui::SetXinputMask(&mask, x11::Input::RawDeviceEvent::RawKeyPress); + ui::SetXinputMask(&mask, x11::Input::RawDeviceEvent::RawKeyRelease); + ui::SetXinputMask(&mask, x11::Input::RawDeviceEvent::RawMotion); + return mask; +} + +} // namespace remoting
diff --git a/remoting/host/input_monitor/local_input_monitor_x11_common.h b/remoting/host/input_monitor/local_input_monitor_x11_common.h new file mode 100644 index 0000000..a28d12f8 --- /dev/null +++ b/remoting/host/input_monitor/local_input_monitor_x11_common.h
@@ -0,0 +1,20 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef REMOTING_HOST_INPUT_MONITOR_LOCAL_INPUT_MONITOR_X11_COMMON_H_ +#define REMOTING_HOST_INPUT_MONITOR_LOCAL_INPUT_MONITOR_X11_COMMON_H_ + +#include "ui/events/devices/x11/xinput_util.h" +#include "ui/gfx/x/xinput.h" + +namespace remoting { + +// Returns the input event mask used by all the X11 local input monitors. +// Since the mask is set for the root window, each input monitor must use +// the same mask. +x11::Input::XIEventMask CommonXIEventMaskForRootWindow(); + +} // namespace remoting + +#endif // REMOTING_HOST_INPUT_MONITOR_LOCAL_INPUT_MONITOR_X11_COMMON_H_
diff --git a/remoting/host/input_monitor/local_mouse_input_monitor_x11.cc b/remoting/host/input_monitor/local_mouse_input_monitor_x11.cc index 280ef6ee..46ae482 100644 --- a/remoting/host/input_monitor/local_mouse_input_monitor_x11.cc +++ b/remoting/host/input_monitor/local_mouse_input_monitor_x11.cc
@@ -18,8 +18,8 @@ #include "base/macros.h" #include "base/sequence_checker.h" #include "base/single_thread_task_runner.h" +#include "remoting/host/input_monitor/local_input_monitor_x11_common.h" #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h" -#include "ui/events/devices/x11/xinput_util.h" #include "ui/events/event.h" #include "ui/gfx/x/connection.h" #include "ui/gfx/x/event.h" @@ -77,7 +77,7 @@ // Controls watching X events. std::unique_ptr<base::FileDescriptorWatcher::Controller> controller_; - std::unique_ptr<x11::Connection> connection_; + x11::Connection* connection_ = nullptr; DISALLOW_COPY_AND_ASSIGN(Core); }; @@ -128,28 +128,24 @@ base::BindOnce(&Core::StopOnInputThread, this)); } -LocalMouseInputMonitorX11::Core::~Core() { - DCHECK(!connection_); -} +LocalMouseInputMonitorX11::Core::~Core() = default; void LocalMouseInputMonitorX11::Core::StartOnInputThread() { DCHECK(input_task_runner_->BelongsToCurrentThread()); DCHECK(!connection_); - // TODO(jamiewalch): We should pass the connection in. - connection_ = std::make_unique<x11::Connection>(); + connection_ = x11::Connection::Get(); connection_->AddEventObserver(this); if (!connection_->xinput().present()) { - LOG(ERROR) << "X Record extension not available."; + LOG(ERROR) << "X Input extension not available."; return; } // Let the server know the client XInput version. connection_->xinput().XIQueryVersion( {x11::Input::major_version, x11::Input::minor_version}); - x11::Input::XIEventMask mask{}; - ui::SetXinputMask(&mask, x11::Input::RawDeviceEvent::RawMotion); + auto mask = CommonXIEventMaskForRootWindow(); connection_->xinput().XISelectEvents( {connection_->default_root(), {{x11::Input::DeviceId::AllMaster, {mask}}}}); @@ -168,7 +164,6 @@ void LocalMouseInputMonitorX11::Core::StopOnInputThread() { DCHECK(input_task_runner_->BelongsToCurrentThread()); controller_.reset(); - connection_.reset(); } void LocalMouseInputMonitorX11::Core::OnConnectionData() { @@ -184,7 +179,8 @@ // selected them. if (!raw) return; - DCHECK(raw->opcode == x11::Input::RawDeviceEvent::RawMotion); + if (raw->opcode != x11::Input::RawDeviceEvent::RawMotion) + return; connection_->QueryPointer({connection_->default_root()}) .OnResponse(base::BindOnce(
diff --git a/remoting/host/installer/linux/build_deb.py b/remoting/host/installer/linux/build_deb.py index 3be7c421..62c9e965 100644 --- a/remoting/host/installer/linux/build_deb.py +++ b/remoting/host/installer/linux/build_deb.py
@@ -14,7 +14,7 @@ proc = subprocess.Popen([build_deb_script] + sys.argv[1:], stdout=subprocess.PIPE) out, _ = proc.communicate() - sys.stdout.write(out.strip()) + sys.stdout.write(out.decode('utf8').strip()) return proc.returncode
diff --git a/sandbox/policy/features.cc b/sandbox/policy/features.cc index 255bab5..8ba5f50 100644 --- a/sandbox/policy/features.cc +++ b/sandbox/policy/features.cc
@@ -35,6 +35,11 @@ // Enables GPU Low Privilege AppContainer when combined with kGpuAppContainer. const base::Feature kGpuLPAC{"GpuLPAC", base::FEATURE_ENABLED_BY_DEFAULT}; + +// Use LPAC for network sandbox instead of restricted token. Relies on +// NetworkServiceSandbox being also enabled. +const base::Feature kNetworkServiceSandboxLPAC{ + "NetworkServiceSandboxLPAC", base::FEATURE_DISABLED_BY_DEFAULT}; #endif // defined(OS_WIN) #if !defined(OS_ANDROID)
diff --git a/sandbox/policy/features.h b/sandbox/policy/features.h index d26e0d1..6de7bbd6 100644 --- a/sandbox/policy/features.h +++ b/sandbox/policy/features.h
@@ -26,6 +26,7 @@ SANDBOX_POLICY_EXPORT extern const base::Feature kWinSboxDisableExtensionPoints; SANDBOX_POLICY_EXPORT extern const base::Feature kGpuAppContainer; SANDBOX_POLICY_EXPORT extern const base::Feature kGpuLPAC; +SANDBOX_POLICY_EXPORT extern const base::Feature kNetworkServiceSandboxLPAC; #endif // defined(OS_WIN) #if !defined(OS_ANDROID)
diff --git a/sandbox/policy/win/sandbox_win.cc b/sandbox/policy/win/sandbox_win.cc index 8a1639d..3f826df 100644 --- a/sandbox/policy/win/sandbox_win.cc +++ b/sandbox/policy/win/sandbox_win.cc
@@ -631,6 +631,9 @@ case SandboxType::kMediaFoundationCdm: sandbox_base_name = std::string("cr.sb.cdm"); break; + case SandboxType::kNetwork: + sandbox_base_name = std::string("cr.sb.net"); + break; default: DCHECK(0); } @@ -651,9 +654,13 @@ SandboxType sandbox_type) { if (sandbox_type != SandboxType::kMediaFoundationCdm && sandbox_type != SandboxType::kGpu && - sandbox_type != SandboxType::kXrCompositing) + sandbox_type != SandboxType::kXrCompositing && + sandbox_type != SandboxType::kNetwork) return SBOX_ERROR_UNSUPPORTED; + DCHECK(sandbox_type != SandboxType::kNetwork || + base::FeatureList::IsEnabled(features::kNetworkServiceSandboxLPAC)); + if (sandbox_type == SandboxType::kGpu && !profile->AddImpersonationCapability(L"chromeInstallFiles")) { DLOG(ERROR) << "AppContainerProfile::AddImpersonationCapability(" @@ -738,6 +745,18 @@ profile->SetEnableLowPrivilegeAppContainer(true); } + // Enable LPAC for Network service. + if (sandbox_type == SandboxType::kNetwork) { + profile->AddCapability( + sandbox::WellKnownCapabilities::kPrivateNetworkClientServer); + profile->AddCapability(sandbox::WellKnownCapabilities::kInternetClient); + profile->AddCapability( + sandbox::WellKnownCapabilities::kEnterpriseAuthentication); + profile->AddCapability(L"lpacIdentityServices"); + profile->AddCapability(L"lpacCryptoServices"); + profile->SetEnableLowPrivilegeAppContainer(true); + } + if (sandbox_type == SandboxType::kMediaFoundationCdm) profile->SetEnableLowPrivilegeAppContainer(true); @@ -900,9 +919,13 @@ if (sandbox_type == SandboxType::kMediaFoundationCdm) return true; - if (sandbox_type != SandboxType::kGpu) - return false; - return base::FeatureList::IsEnabled(features::kGpuAppContainer); + if (sandbox_type == SandboxType::kGpu) + return base::FeatureList::IsEnabled(features::kGpuAppContainer); + + if (sandbox_type == SandboxType::kNetwork) + return base::FeatureList::IsEnabled(features::kNetworkServiceSandboxLPAC); + + return false; } // static
diff --git a/services/device/generic_sensor/sensor_provider_impl.cc b/services/device/generic_sensor/sensor_provider_impl.cc index 98428659..4b7f64f 100644 --- a/services/device/generic_sensor/sensor_provider_impl.cc +++ b/services/device/generic_sensor/sensor_provider_impl.cc
@@ -9,7 +9,6 @@ #include "base/bind.h" #include "base/feature_list.h" #include "base/memory/ptr_util.h" -#include "base/threading/thread_task_runner_handle.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "services/device/generic_sensor/platform_sensor_provider.h" #include "services/device/generic_sensor/sensor_impl.h"
diff --git a/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.cc b/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.cc index 3ed89e3..b0460b3 100644 --- a/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.cc +++ b/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.cc
@@ -897,7 +897,7 @@ CounterDescriptor* counter = track_descriptor->set_counter(); if (counter_type != CounterDescriptor::COUNTER_UNSPECIFIED) { - counter->set_type(CounterDescriptor::COUNTER_THREAD_TIME_NS); + counter->set_type(counter_type); } if (unit_multiplier) { counter->set_unit_multiplier(unit_multiplier);
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json index ad7a217d..ae0701c 100644 --- a/testing/buildbot/chromium.android.fyi.json +++ b/testing/buildbot/chromium.android.fyi.json
@@ -533,7 +533,8 @@ "args": [ "--gs-results-bucket=chromium-result-details", "--recover-devices", - "--avd-config=../../tools/android/avd/proto/generic_android30.textpb" + "--avd-config=../../tools/android/avd/proto/generic_android30.textpb", + "--gtest_filter=-HarfBuzzShaperTest.EmojiPercentage" ], "merge": { "args": [ @@ -1377,7 +1378,8 @@ "args": [ "--gs-results-bucket=chromium-result-details", "--recover-devices", - "--avd-config=../../tools/android/avd/proto/generic_android30.textpb" + "--avd-config=../../tools/android/avd/proto/generic_android30.textpb", + "--gtest_filter=-FontUniqueNameLookupTest.TestMatchPostScriptNameTtc" ], "merge": { "args": [
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl index 4d0980f3..a849004 100644 --- a/testing/buildbot/gn_isolate_map.pyl +++ b/testing/buildbot/gn_isolate_map.pyl
@@ -1451,7 +1451,7 @@ }, "performance_web_engine_test_suite": { "args": [ - "../../content/test/run_gpu_integration_test_fuchsia.py", + "../../content/test/gpu/run_telemetry_benchmark_fuchsia.py", ], "label": "//content/test:performance_web_engine_test_suite", "script": "//testing/scripts/run_performance_tests.py",
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index 9caaa76f..a688cba 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -179,6 +179,12 @@ }, 'blink_platform_unittests': { 'modifications': { + # TODO(crbug.com/1189336): Remove the filter once the issue is fixed. + 'android-11-x86-fyi-rel': { + 'args': [ + '--gtest_filter=-HarfBuzzShaperTest.EmojiPercentage', + ], + }, # TODO(crbug.com/1108121): Remove this filter 'android-nougat-arm64-rel': { 'args': [ @@ -1258,6 +1264,12 @@ 'shards': 2, }, }, + # TODO(crbug.com/1189344): Remove the filter once the issue is fixed. + 'android-11-x86-fyi-rel': { + 'args': [ + '--gtest_filter=-FontUniqueNameLookupTest.TestMatchPostScriptNameTtc', + ], + }, }, }, 'context_lost_passthrough_tests': {
diff --git a/testing/scripts/run_android_wpt.py b/testing/scripts/run_android_wpt.py index 99815b9..b6f2fcb 100755 --- a/testing/scripts/run_android_wpt.py +++ b/testing/scripts/run_android_wpt.py
@@ -119,9 +119,6 @@ # Here we add all of the arguments required to run WPT tests on Android. rest_args.extend([self.options.wpt_path]) - # TODO(crbug.com/1166741): We should be running WPT under Python 3. - rest_args.extend(["--py2"]) - # vpython has packages needed by wpt, so force it to skip the setup rest_args.extend(["--venv=../../", "--skip-venv-setup"])
diff --git a/testing/scripts/run_wpt_tests.py b/testing/scripts/run_wpt_tests.py index 88ce325..c762579 100755 --- a/testing/scripts/run_wpt_tests.py +++ b/testing/scripts/run_wpt_tests.py
@@ -73,8 +73,6 @@ WPT_BINARY, "--venv=" + SRC_DIR, "--skip-venv-setup", - # TODO(crbug.com/1166741): We should be running WPT under Python 3. - "--py3", "run", "chrome" ] + self.options.test_list + [
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 20481cf..a3e960e 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -2631,6 +2631,21 @@ ] } ], + "DisableCryptAuthV1DeviceSync": [ + { + "platforms": [ + "chromeos" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "DisableCryptAuthV1DeviceSync" + ] + } + ] + } + ], "DisableGles2ForOopR": [ { "platforms": [
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index 47363b6..0687092d 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc
@@ -888,5 +888,8 @@ kBackgroundTracingPerformanceMark_AllowList{ &kBackgroundTracingPerformanceMark, "allow_list", ""}; +const base::Feature kCLSM91Improvements{"CLSM91Improvements", + base::FEATURE_ENABLED_BY_DEFAULT}; + } // namespace features } // namespace blink
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h index 57468e1..e439a1a7 100644 --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h
@@ -367,6 +367,8 @@ BLINK_COMMON_EXPORT extern const base::FeatureParam<std::string> kBackgroundTracingPerformanceMark_AllowList; +BLINK_COMMON_EXPORT extern const base::Feature kCLSM91Improvements; + } // namespace features } // namespace blink
diff --git a/third_party/blink/public/common/permissions_policy/permissions_policy.h b/third_party/blink/public/common/permissions_policy/permissions_policy.h index 05daf7fe..68caa8a 100644 --- a/third_party/blink/public/common/permissions_policy/permissions_policy.h +++ b/third_party/blink/public/common/permissions_policy/permissions_policy.h
@@ -129,10 +129,10 @@ class BLINK_COMMON_EXPORT PermissionsPolicy { public: - // Represents a collection of origins which make up an allowlist in a feature - // policy. This collection may be set to match every origin (corresponding to - // the "*" syntax in the policy string, in which case the Contains() method - // will always return true. + // Represents a collection of origins which make up an allowlist in a + // permissions policy. This collection may be set to match every origin + // (corresponding to the "*" syntax in the policy string, in which case the + // Contains() method will always return true. class BLINK_COMMON_EXPORT Allowlist final { public: Allowlist();
diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn index 75c53038..5864a823 100644 --- a/third_party/blink/public/mojom/BUILD.gn +++ b/third_party/blink/public/mojom/BUILD.gn
@@ -170,6 +170,7 @@ "service_worker/service_worker_stream_handle.mojom", "site_engagement/site_engagement.mojom", "sms/webotp_service.mojom", + "speculation_rules/speculation_rules.mojom", "speech/speech_recognition_error.mojom", "speech/speech_recognition_error_code.mojom", "speech/speech_recognition_grammar.mojom",
diff --git a/third_party/blink/public/mojom/speculation_rules/OWNERS b/third_party/blink/public/mojom/speculation_rules/OWNERS new file mode 100644 index 0000000..263f96d --- /dev/null +++ b/third_party/blink/public/mojom/speculation_rules/OWNERS
@@ -0,0 +1,4 @@ +file://third_party/blink/renderer/core/speculation_rules/OWNERS + +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/third_party/blink/public/mojom/speculation_rules/README.md b/third_party/blink/public/mojom/speculation_rules/README.md new file mode 100644 index 0000000..a65212f --- /dev/null +++ b/third_party/blink/public/mojom/speculation_rules/README.md
@@ -0,0 +1 @@ +See `third_party/blink/renderer/core/speculation_rules/`.
diff --git a/third_party/blink/public/mojom/speculation_rules/speculation_rules.mojom b/third_party/blink/public/mojom/speculation_rules/speculation_rules.mojom new file mode 100644 index 0000000..a37f2d8 --- /dev/null +++ b/third_party/blink/public/mojom/speculation_rules/speculation_rules.mojom
@@ -0,0 +1,51 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module blink.mojom; + +import "url/mojom/url.mojom"; + +// See also third_party/blink/renderer/core/speculation_rules/README.md. + +// Browser process interface for receiving information about proposed +// speculation from the renderer process. +// +// At the moment these updates are not incremental -- the renderer updates the +// entire set of speculation candidates at once. This is probably fine as long +// as it's occasional (i.e., the renderer buffers these updates somewhat) and +// the set of candidates is not unmanageably large. If so we may need to +// re-evaluate. +interface SpeculationHost { + // Pushes a new set of speculation candidates, which replaces any previously + // sent. + // + // [[[ WARNING ]]] + // Not yet implemented in the browser process. + // Security reviewer approval for this has not yet been granted. + // The CL which lands a browser process implementation of this should rename + // this and seek ipc/SECURITY_OWNERS approval. + UpdateSpeculationCandidates_PendingSecurityReview( + array<SpeculationCandidate> candidates); +}; + +// The action that is proposed. +enum SpeculationAction { + kPrefetch, + kPrefetchWithSubresources, +}; + +// A single candidate: a URL, an action, and any associated metadata that +// might be needed to make a decision. +struct SpeculationCandidate { + // The URL which is eligible for some action. + url.mojom.Url url; + + // The action which is proposed for that URL. + SpeculationAction action = kPrefetch; + + // If true, cross-origin requests associated with this speculation must be + // made in a manner which anonymizes the client IP. If this is not possible, + // this candidate must be discarded. + bool requires_anonymous_client_ip_when_cross_origin = false; +};
diff --git a/third_party/blink/renderer/bindings/core/v8/binding_security.cc b/third_party/blink/renderer/bindings/core/v8/binding_security.cc index f53cd6a..44e99dda 100644 --- a/third_party/blink/renderer/bindings/core/v8/binding_security.cc +++ b/third_party/blink/renderer/bindings/core/v8/binding_security.cc
@@ -146,7 +146,7 @@ : WebFeature::kDocumentDomainBlockedCrossOriginAccess); } if (!can_access) { - // Ensure that if we got a cluster mismatch that it was due to a feature + // Ensure that if we got a cluster mismatch that it was due to a permissions // policy being enabled and not a logic bug. if (detail == SecurityOrigin::AccessResultDomainDetail:: kDomainNotRelevantAgentClusterMismatch) {
diff --git a/third_party/blink/renderer/build/scripts/templates/policy_helper.cc.tmpl b/third_party/blink/renderer/build/scripts/templates/policy_helper.cc.tmpl index 7e99ab6..5ee61d5 100644 --- a/third_party/blink/renderer/build/scripts/templates/policy_helper.cc.tmpl +++ b/third_party/blink/renderer/build/scripts/templates/policy_helper.cc.tmpl
@@ -27,9 +27,10 @@ // add their feature names to this map unconditionally, as the trial token could // be added after the HTTP header needs to be parsed. This also means that // top-level documents which simply want to embed another page which uses an -// origin trial feature, without using the feature themselves, can use feature -// policy to allow use of the feature in subframes (The framed document will -// still require a valid origin trial token to use the feature in this scenario). +// origin trial feature, without using the feature themselves, can use +// permissions policy to allow use of the feature in subframes (The framed +// document will still require a valid origin trial token to use the feature in +// this scenario). const FeatureNameMap& GetDefaultFeatureNameMap() { DEFINE_STATIC_LOCAL(FeatureNameMap, default_feature_name_map, ()); if (default_feature_name_map.IsEmpty()) {
diff --git a/third_party/blink/renderer/core/OWNERS b/third_party/blink/renderer/core/OWNERS index c9bdfac..400137a 100644 --- a/third_party/blink/renderer/core/OWNERS +++ b/third_party/blink/renderer/core/OWNERS
@@ -49,7 +49,7 @@ kinuko@chromium.org kojii@chromium.org kouhei@chromium.org -masonfreed@chromium.org +masonf@chromium.org mkwst@chromium.org mstensho@chromium.org nhiroki@chromium.org
diff --git a/third_party/blink/renderer/core/dom/OWNERS b/third_party/blink/renderer/core/dom/OWNERS index 9f2610d..7a0ec122 100644 --- a/third_party/blink/renderer/core/dom/OWNERS +++ b/third_party/blink/renderer/core/dom/OWNERS
@@ -1,4 +1,4 @@ -masonfreed@chromium.org +masonf@chromium.org per-file *_mojom_traits*.*=set noparent per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
diff --git a/third_party/blink/renderer/core/dom/README.md b/third_party/blink/renderer/core/dom/README.md index c6e4107..beb2f56 100644 --- a/third_party/blink/renderer/core/dom/README.md +++ b/third_party/blink/renderer/core/dom/README.md
@@ -730,7 +730,7 @@ Since `Node::UpdateDistributionForFlatTreeTraversal` can take O(N) in the worst case (_even if the distribution flag is clean!_), you should be careful not to call it in hot code paths. If you are not sure, please contact -dom-dev@chromium.org, or add masonfreed@chromium.org to reviewers. +dom-dev@chromium.org, or add masonf@chromium.org to reviewers. Once Blink removes Shadow DOM v0 in the future, you don't need to call `Node::UpdateDistributionForFlatTreeTraversal` before using `FlatTreeTraversal`
diff --git a/third_party/blink/renderer/core/execution_context/window_agent_factory.cc b/third_party/blink/renderer/core/execution_context/window_agent_factory.cc index f49519d..1f10e47 100644 --- a/third_party/blink/renderer/core/execution_context/window_agent_factory.cc +++ b/third_party/blink/renderer/core/execution_context/window_agent_factory.cc
@@ -16,11 +16,10 @@ WindowAgentFactory::WindowAgentFactory() = default; WindowAgent* WindowAgentFactory::GetAgentForOrigin( - bool has_potential_universal_access_privilege, v8::Isolate* isolate, const SecurityOrigin* origin, bool is_origin_agent_cluster) { - if (has_potential_universal_access_privilege) { + if (origin->IsGrantedUniversalAccess()) { if (!universal_access_agent_) { universal_access_agent_ = MakeGarbageCollected<WindowAgent>(isolate); }
diff --git a/third_party/blink/renderer/core/execution_context/window_agent_factory.h b/third_party/blink/renderer/core/execution_context/window_agent_factory.h index 33d750e..b62c64a 100644 --- a/third_party/blink/renderer/core/execution_context/window_agent_factory.h +++ b/third_party/blink/renderer/core/execution_context/window_agent_factory.h
@@ -44,15 +44,7 @@ // If |is_origin_agent_cluster| is true though, then the same instance will // only return the same instance for an exact match (scheme, host, port) to // |origin|. - // - // Set |has_potential_universal_access_privilege| if an agent may be able to - // access all other agents synchronously. - // I.e. pass true to if either: - // * --disable-web-security is set, - // * --run-web-tests is set, - // * or, the Blink instance is running for Android WebView. - WindowAgent* GetAgentForOrigin(bool has_potential_universal_access_privilege, - v8::Isolate* isolate, + WindowAgent* GetAgentForOrigin(v8::Isolate* isolate, const SecurityOrigin* origin, bool is_origin_agent_cluster);
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc index 65f3e30..ffcc217 100644 --- a/third_party/blink/renderer/core/frame/local_frame.cc +++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -1829,7 +1829,9 @@ String destination_domain = network_utils::GetDomainAndRegistry( destination_url.Host(), network_utils::kIncludePrivateRegistries); if (!target_domain.IsEmpty() && !destination_domain.IsEmpty() && - target_domain == destination_domain) { + target_domain == destination_domain && + target_frame.GetSecurityContext()->GetSecurityOrigin()->Protocol() == + destination_url.Protocol()) { return true; }
diff --git a/third_party/blink/renderer/core/html/forms/OWNERS b/third_party/blink/renderer/core/html/forms/OWNERS index e69f365..b80d6277 100644 --- a/third_party/blink/renderer/core/html/forms/OWNERS +++ b/third_party/blink/renderer/core/html/forms/OWNERS
@@ -1,3 +1,3 @@ keishi@chromium.org tkent@chromium.org -masonfreed@chromium.org +masonf@chromium.org
diff --git a/third_party/blink/renderer/core/html/parser/OWNERS b/third_party/blink/renderer/core/html/parser/OWNERS index c0b826f5..506b856 100644 --- a/third_party/blink/renderer/core/html/parser/OWNERS +++ b/third_party/blink/renderer/core/html/parser/OWNERS
@@ -1,4 +1,4 @@ csharrison@chromium.org kouhei@chromium.org -masonfreed@chromium.org +masonf@chromium.org yoavweiss@chromium.org
diff --git a/third_party/blink/renderer/core/input/touch_event_manager.h b/third_party/blink/renderer/core/input/touch_event_manager.h index 46deb25..dcba6d3 100644 --- a/third_party/blink/renderer/core/input/touch_event_manager.h +++ b/third_party/blink/renderer/core/input/touch_event_manager.h
@@ -128,13 +128,13 @@ // that only horizontal scrolling is blocked. bool should_enforce_vertical_scroll_ = false; // When set to a value, the effective touch-action is sent to the browser - // after all 'touchstart' handlers have been invoked. This is used by feature - // policy to enforce specific directions of scroll in spite of scroll-blocking - // events being prevent defaulted. When multiple pointer down events occur - // during the same touch sequence, the value of effective touch action which - // is sent to the browser after handling each dispatched 'touchstart' is the - // intersection of all the previously calculated effective touch action values - // during the sequence. + // after all 'touchstart' handlers have been invoked. This is used by + // permissions policy to enforce specific directions of scroll in spite of + // scroll-blocking events being prevent defaulted. When multiple pointer down + // events occur during the same touch sequence, the value of effective touch + // action which is sent to the browser after handling each dispatched + // 'touchstart' is the intersection of all the previously calculated effective + // touch action values during the sequence. base::Optional<TouchAction> delayed_effective_touch_action_; };
diff --git a/third_party/blink/renderer/core/inspector/inspector_trace_events.cc b/third_party/blink/renderer/core/inspector/inspector_trace_events.cc index 3debd5c..62d33f8 100644 --- a/third_party/blink/renderer/core/inspector/inspector_trace_events.cc +++ b/third_party/blink/renderer/core/inspector/inspector_trace_events.cc
@@ -263,12 +263,11 @@ void SetNodeInfo(perfetto::TracedDictionary& dict, Node* node, - const char* id_field_name, - const char* name_field_name = nullptr) { - dict.Add(perfetto::StaticString{id_field_name}, - IdentifiersFactory::IntIdForNode(node)); - if (name_field_name) - dict.Add(perfetto::DynamicString{name_field_name}, node->DebugName()); + perfetto::StaticString id_field_name, + perfetto::StaticString name_field_name = nullptr) { + dict.Add(id_field_name, IdentifiersFactory::IntIdForNode(node)); + if (name_field_name.value) + dict.Add(name_field_name, node->DebugName()); } const char* PseudoTypeToString(CSSSelector::PseudoType pseudo_type) { @@ -674,10 +673,11 @@ array.Append(quad.P4().Y()); } -static void SetGeneratingNodeInfo(perfetto::TracedDictionary& dict, - const LayoutObject* layout_object, - const char* id_field_name, - const char* name_field_name = nullptr) { +static void SetGeneratingNodeInfo( + perfetto::TracedDictionary& dict, + const LayoutObject* layout_object, + perfetto::StaticString id_field_name, + perfetto::StaticString name_field_name = nullptr) { Node* node = nullptr; for (; layout_object && !node; layout_object = layout_object->Parent()) node = layout_object->GeneratingNode();
diff --git a/third_party/blink/renderer/core/layout/layout_shift_tracker.cc b/third_party/blink/renderer/core/layout/layout_shift_tracker.cc index 99f3220..3b10e544 100644 --- a/third_party/blink/renderer/core/layout/layout_shift_tracker.cc +++ b/third_party/blink/renderer/core/layout/layout_shift_tracker.cc
@@ -7,6 +7,7 @@ #include "cc/layers/heads_up_display_layer.h" #include "cc/layers/picture_layer.h" #include "cc/trees/layer_tree_host.h" +#include "third_party/blink/public/common/features.h" #include "third_party/blink/public/common/input/web_pointer_event.h" #include "third_party/blink/renderer/core/dom/dom_node_ids.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h" @@ -142,6 +143,8 @@ // SVGImage::DataChanged. is_active_( !frame_view->GetFrame().GetChromeClient().IsSVGImageChromeClient()), + enable_m91_improvements_( + base::FeatureList::IsEnabled(features::kCLSM91Improvements)), score_(0.0), weighted_score_(0.0), timer_(frame_view->GetFrame().GetTaskRunner(TaskType::kInternalDefault), @@ -172,11 +175,13 @@ return false; if (object.IsBR()) return false; - if (To<LayoutText>(object).ContainsOnlyWhitespaceOrNbsp() == - OnlyWhitespaceOrNbsp::kYes) - return false; - if (object.StyleRef().GetFont().ShouldSkipDrawing()) - return false; + if (enable_m91_improvements_) { + if (To<LayoutText>(object).ContainsOnlyWhitespaceOrNbsp() == + OnlyWhitespaceOrNbsp::kYes) + return false; + if (object.StyleRef().GetFont().ShouldSkipDrawing()) + return false; + } return true; } @@ -211,7 +216,7 @@ return false; } - if (box.IsLayoutBlock()) { + if (enable_m91_improvements_ && box.IsLayoutBlock()) { // Just check the simplest case. For more complex cases, we should suggest // the developer to use visibility:hidden. if (To<LayoutBlock>(box).FirstChild()) @@ -241,22 +246,25 @@ float threshold_physical_px = kMovementThreshold * object.StyleRef().EffectiveZoom(); - // Check shift of starting point, including 2d-translation and scroll deltas. - if (EqualWithinMovementThreshold(old_starting_point, new_starting_point, - threshold_physical_px)) - return; + if (enable_m91_improvements_) { + // Check shift of starting point, including 2d-translation and scroll + // deltas. + if (EqualWithinMovementThreshold(old_starting_point, new_starting_point, + threshold_physical_px)) + return; - // Check shift of 2d-translation-indifferent starting point. - if (!translation_delta.IsZero() && - EqualWithinMovementThreshold(old_starting_point + translation_delta, - new_starting_point, threshold_physical_px)) - return; + // Check shift of 2d-translation-indifferent starting point. + if (!translation_delta.IsZero() && + EqualWithinMovementThreshold(old_starting_point + translation_delta, + new_starting_point, threshold_physical_px)) + return; - // Check shift of scroll-indifferent starting point. - if (!scroll_delta.IsZero() && - EqualWithinMovementThreshold(old_starting_point + scroll_delta, - new_starting_point, threshold_physical_px)) - return; + // Check shift of scroll-indifferent starting point. + if (!scroll_delta.IsZero() && + EqualWithinMovementThreshold(old_starting_point + scroll_delta, + new_starting_point, threshold_physical_px)) + return; + } // Check shift of 2d-translation-and-scroll-indifferent starting point. FloatSize translation_and_scroll_delta = scroll_delta + translation_delta; @@ -285,8 +293,9 @@ property_tree_state.Transform(), root_state.Transform()); // TODO(crbug.com/1187979): Shift by |scroll_delta| to keep backward // compatibility in https://crrev.com/c/2754969. See the bug for details. - FloatPoint old_starting_point_in_root = - transform.MapPoint(old_starting_point + scroll_delta); + FloatPoint old_starting_point_in_root = transform.MapPoint( + old_starting_point + + (enable_m91_improvements_ ? scroll_delta : translation_and_scroll_delta)); FloatPoint new_starting_point_in_root = transform.MapPoint(new_starting_point); @@ -295,10 +304,22 @@ threshold_physical_px)) return; + if (enable_m91_improvements_) { + DCHECK(frame_scroll_delta_.IsZero()); + } else if (EqualWithinMovementThreshold( + old_starting_point_in_root + frame_scroll_delta_, + new_starting_point_in_root, threshold_physical_px)) { + // TODO(skobes): Checking frame_scroll_delta_ is an imperfect solution to + // allowing counterscrolled layout shifts. Ideally, we would map old_rect + // to viewport coordinates using the previous frame's scroll tree. + return; + } + FloatRect old_rect_in_root(old_rect); // TODO(crbug.com/1187979): Shift by |scroll_delta| to keep backward // compatibility in https://crrev.com/c/2754969. See the bug for details. - old_rect_in_root.Move(scroll_delta); + old_rect_in_root.Move( + enable_m91_improvements_ ? scroll_delta : translation_and_scroll_delta); transform.MapRect(old_rect_in_root); FloatRect new_rect_in_root(new_rect); transform.MapRect(new_rect_in_root); @@ -312,7 +333,8 @@ // If the object moved from or to out of view, ignore the shift if it's in // the inline direction only. - if (visible_old_rect.IsEmpty() || visible_new_rect.IsEmpty()) { + if (enable_m91_improvements_ && + (visible_old_rect.IsEmpty() || visible_new_rect.IsEmpty())) { FloatPoint old_inline_direction_indifferent_starting_point_in_root = old_starting_point_in_root; if (object.IsHorizontalWritingMode()) { @@ -539,6 +561,7 @@ // Reset accumulated state. region_.Reset(); frame_max_distance_ = 0.0; + frame_scroll_delta_ = ScrollOffset(); attributions_.fill(Attribution()); } @@ -654,7 +677,11 @@ frame.Client()->DidObserveInputForLayoutShiftTracking(timestamp); } -void LayoutShiftTracker::NotifyScroll(mojom::blink::ScrollType scroll_type) { +void LayoutShiftTracker::NotifyScroll(mojom::blink::ScrollType scroll_type, + ScrollOffset delta) { + if (!enable_m91_improvements_) + frame_scroll_delta_ += delta; + // Only set observed_input_or_scroll_ for user-initiated scrolls, and not // other scrolls such as hash fragment navigations. if (scroll_type == mojom::blink::ScrollType::kUser ||
diff --git a/third_party/blink/renderer/core/layout/layout_shift_tracker.h b/third_party/blink/renderer/core/layout/layout_shift_tracker.h index cf164d8..b48bef4 100644 --- a/third_party/blink/renderer/core/layout/layout_shift_tracker.h +++ b/third_party/blink/renderer/core/layout/layout_shift_tracker.h
@@ -73,7 +73,7 @@ void NotifyPrePaintFinished(); void NotifyInput(const WebInputEvent&); - void NotifyScroll(mojom::blink::ScrollType); + void NotifyScroll(mojom::blink::ScrollType, ScrollOffset delta); void NotifyViewportSizeChanged(); void NotifyFindInPageInput(); void NotifyChangeEvent(); @@ -183,6 +183,7 @@ Member<LocalFrameView> frame_view_; bool is_active_; + bool enable_m91_improvements_; // The document cumulative layout shift (DCLS) score for this LocalFrame, // unweighted, with move distance applied. @@ -226,6 +227,10 @@ // frames. float overall_max_distance_; + // Sum of all scroll deltas that occurred in the current animation frame. + // TODO(wangxianzhu): Remove when enabling CLSM91Improvements permanently. + ScrollOffset frame_scroll_delta_; + // Whether either a user input or document scroll have been observed during // the session. (This is only tracked so UkmPageLoadMetricsObserver to report // LayoutInstability.CumulativeShiftScore.MainFrame.BeforeInputOrScroll. It's
diff --git a/third_party/blink/renderer/core/layout/ng/custom/css_layout_definition.cc b/third_party/blink/renderer/core/layout/ng/custom/css_layout_definition.cc index d939dae..6788b79 100644 --- a/third_party/blink/renderer/core/layout/ng/custom/css_layout_definition.cc +++ b/third_party/blink/renderer/core/layout/ng/custom/css_layout_definition.cc
@@ -222,7 +222,7 @@ const NGBlockNode& node, const LogicalSize& border_box_size, const NGBoxStrut& border_scrollbar_padding, - const LayoutUnit child_percentage_resolution_block_size_for_min_max, + const LayoutUnit child_available_block_size, CustomLayoutScope* custom_layout_scope, IntrinsicSizesResultOptions** intrinsic_sizes_result_options, bool* child_depends_on_percentage_block_size) { @@ -276,8 +276,7 @@ // The queue may mutate (re-allocating the vector) while running a task. for (wtf_size_t index = 0; index < queue.size(); ++index) { auto task = queue[index]; - task->Run(space, node.Style(), - child_percentage_resolution_block_size_for_min_max, + task->Run(space, node.Style(), child_available_block_size, child_depends_on_percentage_block_size); } queue.clear();
diff --git a/third_party/blink/renderer/core/layout/ng/custom/css_layout_definition.h b/third_party/blink/renderer/core/layout/ng/custom/css_layout_definition.h index 5596cc1..976fabd 100644 --- a/third_party/blink/renderer/core/layout/ng/custom/css_layout_definition.h +++ b/third_party/blink/renderer/core/layout/ng/custom/css_layout_definition.h
@@ -67,16 +67,15 @@ // Runs the web developer defined intrinsicSizes, returns true if everything // succeeded. It populates the IntrinsicSizesResultOptions dictionary. - bool IntrinsicSizes( - const NGConstraintSpace&, - const Document&, - const NGBlockNode&, - const LogicalSize& border_box_size, - const NGBoxStrut& border_scrollbar_padding, - const LayoutUnit child_percentage_resolution_block_size_for_min_max, - CustomLayoutScope*, - IntrinsicSizesResultOptions**, - bool* child_depends_on_percentage_block_size); + bool IntrinsicSizes(const NGConstraintSpace&, + const Document&, + const NGBlockNode&, + const LogicalSize& border_box_size, + const NGBoxStrut& border_scrollbar_padding, + const LayoutUnit child_available_block_size, + CustomLayoutScope*, + IntrinsicSizesResultOptions**, + bool* child_depends_on_percentage_block_size); void Trace(Visitor*) const;
diff --git a/third_party/blink/renderer/core/layout/ng/custom/custom_layout_work_task.cc b/third_party/blink/renderer/core/layout/ng/custom/custom_layout_work_task.cc index 0dd3687b..6748d3b 100644 --- a/third_party/blink/renderer/core/layout/ng/custom/custom_layout_work_task.cc +++ b/third_party/blink/renderer/core/layout/ng/custom/custom_layout_work_task.cc
@@ -47,18 +47,16 @@ visitor->Trace(options_); } -void CustomLayoutWorkTask::Run( - const NGConstraintSpace& parent_space, - const ComputedStyle& parent_style, - const LayoutUnit child_percentage_resolution_block_size_for_min_max, - bool* child_depends_on_percentage_block_size) { +void CustomLayoutWorkTask::Run(const NGConstraintSpace& parent_space, + const ComputedStyle& parent_style, + const LayoutUnit child_available_block_size, + bool* child_depends_on_percentage_block_size) { DCHECK(token_->IsValid()); NGLayoutInputNode child = child_->GetLayoutNode(); if (type_ == CustomLayoutWorkTask::TaskType::kIntrinsicSizes) { - RunIntrinsicSizesTask(parent_style, - child_percentage_resolution_block_size_for_min_max, - child, child_depends_on_percentage_block_size); + RunIntrinsicSizesTask(parent_style, child_available_block_size, child, + child_depends_on_percentage_block_size); } else { DCHECK_EQ(type_, CustomLayoutWorkTask::TaskType::kLayoutFragment); RunLayoutFragmentTask(parent_space, parent_style, child); @@ -148,13 +146,13 @@ void CustomLayoutWorkTask::RunIntrinsicSizesTask( const ComputedStyle& parent_style, - const LayoutUnit child_percentage_resolution_block_size_for_min_max, + const LayoutUnit child_available_block_size, NGLayoutInputNode child, bool* child_depends_on_percentage_block_size) { DCHECK_EQ(type_, CustomLayoutWorkTask::TaskType::kIntrinsicSizes); DCHECK(resolver_); - MinMaxSizesInput input(child_percentage_resolution_block_size_for_min_max); + MinMaxSizesInput input(child_available_block_size); MinMaxSizesResult result = ComputeMinAndMaxContentContribution( parent_style, To<NGBlockNode>(child), input); resolver_->Resolve(MakeGarbageCollected<CustomIntrinsicSizes>(
diff --git a/third_party/blink/renderer/core/layout/ng/custom/custom_layout_work_task.h b/third_party/blink/renderer/core/layout/ng/custom/custom_layout_work_task.h index de7610a..eef26c8 100644 --- a/third_party/blink/renderer/core/layout/ng/custom/custom_layout_work_task.h +++ b/third_party/blink/renderer/core/layout/ng/custom/custom_layout_work_task.h
@@ -50,7 +50,7 @@ // Runs this work task. void Run(const NGConstraintSpace& parent_space, const ComputedStyle& parent_style, - const LayoutUnit child_percentage_resolution_block_size_for_min_max, + const LayoutUnit child_available_block_size, bool* child_depends_on_percentage_block_size = nullptr); private: @@ -64,11 +64,10 @@ void RunLayoutFragmentTask(const NGConstraintSpace& parent_space, const ComputedStyle& parent_style, NGLayoutInputNode child); - void RunIntrinsicSizesTask( - const ComputedStyle& parent_style, - const LayoutUnit child_percentage_resolution_block_size_for_min_max, - NGLayoutInputNode child, - bool* child_depends_on_percentage_block_size); + void RunIntrinsicSizesTask(const ComputedStyle& parent_style, + const LayoutUnit child_available_block_size, + NGLayoutInputNode child, + bool* child_depends_on_percentage_block_size); }; } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_fraction_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_fraction_layout_algorithm.cc index ce7d99d..64c2c989 100644 --- a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_fraction_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_fraction_layout_algorithm.cc
@@ -281,10 +281,10 @@ child = child.NextSibling()) { if (child.IsOutOfFlowPositioned()) continue; - auto child_result = ComputeMinAndMaxContentContribution( - Style(), To<NGBlockNode>(child), child_input); - NGBoxStrut margins = ComputeMinMaxMargins(Style(), child); - child_result.sizes += margins.InlineSum(); + + const auto child_result = ComputeMinAndMaxContentContributionForMathChild( + Style(), ConstraintSpace(), To<NGBlockNode>(child), + child_input.percentage_resolution_block_size); sizes.Encompass(child_result.sizes); depends_on_percentage_block_size |=
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.cc b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.cc index 46c2de49..7a499c3 100644 --- a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.cc +++ b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.cc
@@ -38,6 +38,22 @@ return space_builder.ToConstraintSpace(); } +MinMaxSizesResult ComputeMinAndMaxContentContributionForMathChild( + const ComputedStyle& parent_style, + const NGConstraintSpace& parent_space, + const NGBlockNode& child, + LayoutUnit child_available_block_size) { + DCHECK(child.CreatesNewFormattingContext()); + + MinMaxSizesInput input(child_available_block_size); + auto result = ComputeMinAndMaxContentContribution(parent_style, child, input); + + // Add margins directly here. + result.sizes += ComputeMinMaxMargins(parent_style, child).InlineSum(); + + return result; +} + NGLayoutInputNode FirstChildInFlow(const NGBlockNode& node) { NGLayoutInputNode child = node.FirstChild(); while (child && child.IsOutOfFlowPositioned())
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.h b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.h index 26de1169..bd1604d0 100644 --- a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.h +++ b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.h
@@ -12,6 +12,7 @@ struct LogicalSize; struct MinMaxSizes; +struct MinMaxSizesResult; class NGBlockNode; class NGConstraintSpace; class NGLayoutInputNode; @@ -24,6 +25,12 @@ const NGConstraintSpace& parent_constraint_space, const NGLayoutInputNode&); +MinMaxSizesResult ComputeMinAndMaxContentContributionForMathChild( + const ComputedStyle& parent_style, + const NGConstraintSpace& parent_constraint_space, + const NGBlockNode& child, + LayoutUnit child_available_block_size); + NGLayoutInputNode FirstChildInFlow(const NGBlockNode&); NGLayoutInputNode NextSiblingInFlow(const NGBlockNode&);
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_padded_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_padded_layout_algorithm.cc index a695c14..352ce2bd 100644 --- a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_padded_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_padded_layout_algorithm.cc
@@ -124,10 +124,9 @@ NGBlockNode content = nullptr; GatherChildren(&content); - MinMaxSizesResult content_result = - ComputeMinAndMaxContentContribution(Style(), content, input); - NGBoxStrut content_margins = ComputeMinMaxMargins(Style(), content); - content_result.sizes += content_margins.InlineSum(); + const auto content_result = ComputeMinAndMaxContentContributionForMathChild( + Style(), ConstraintSpace(), content, + input.percentage_resolution_block_size); bool depends_on_percentage_block_size = content_result.depends_on_percentage_block_size;
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_radical_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_radical_layout_algorithm.cc index 94ac80db..6d5e13b 100644 --- a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_radical_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_radical_layout_algorithm.cc
@@ -204,15 +204,16 @@ MinMaxSizes sizes; bool depends_on_percentage_block_size = false; if (index) { - auto horizontal = GetRadicalHorizontalParameters(Style()); + const auto horizontal = GetRadicalHorizontalParameters(Style()); sizes += horizontal.kern_before_degree.ClampNegativeToZero(); - MinMaxSizesResult index_result = - ComputeMinAndMaxContentContribution(Style(), index, input); - NGBoxStrut index_margins = ComputeMinMaxMargins(Style(), index); - index_result.sizes += index_margins.InlineSum(); + + const auto index_result = ComputeMinAndMaxContentContributionForMathChild( + Style(), ConstraintSpace(), index, + input.percentage_resolution_block_size); depends_on_percentage_block_size |= index_result.depends_on_percentage_block_size; sizes += index_result.sizes; + // kern_after_degree decreases the inline size, but is capped by the index // content inline size. sizes.min_size += @@ -225,10 +226,9 @@ sizes += GetMinMaxSizesForVerticalStretchyOperator(Style(), kSquareRootCharacter); } - MinMaxSizesResult base_result = - ComputeMinAndMaxContentContribution(Style(), base, input); - NGBoxStrut base_margins = ComputeMinMaxMargins(Style(), base); - base_result.sizes += base_margins.InlineSum(); + const auto base_result = ComputeMinAndMaxContentContributionForMathChild( + Style(), ConstraintSpace(), base, + input.percentage_resolution_block_size); depends_on_percentage_block_size |= base_result.depends_on_percentage_block_size; sizes += base_result.sizes;
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_row_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_row_layout_algorithm.cc index 6684a0f..42052bc 100644 --- a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_row_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_row_layout_algorithm.cc
@@ -166,11 +166,9 @@ child = child.NextSibling()) { if (child.IsOutOfFlowPositioned()) continue; - MinMaxSizesResult child_result = ComputeMinAndMaxContentContribution( - Style(), To<NGBlockNode>(child), child_input); - NGBoxStrut child_margins = ComputeMinMaxMargins(Style(), child); - child_result.sizes += child_margins.InlineSum(); - + const auto child_result = ComputeMinAndMaxContentContributionForMathChild( + Style(), ConstraintSpace(), To<NGBlockNode>(child), + child_input.percentage_resolution_block_size); sizes += child_result.sizes; LayoutUnit lspace, rspace;
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_scripts_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_scripts_layout_algorithm.cc index 54a1782..84ffef60 100644 --- a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_scripts_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_scripts_layout_algorithm.cc
@@ -426,9 +426,9 @@ // TODO(layout-dev): Determine the italic-correction without calling layout // within ComputeMinMaxSizes, (or setup in an interoperable constraint-space). LayoutUnit base_italic_correction; - MinMaxSizesResult base_result = - ComputeMinAndMaxContentContribution(Style(), base, child_input); - base_result.sizes += ComputeMinMaxMargins(Style(), base).InlineSum(); + const auto base_result = ComputeMinAndMaxContentContributionForMathChild( + Style(), ConstraintSpace(), base, + child_input.percentage_resolution_block_size); sizes = base_result.sizes; depends_on_percentage_block_size |= @@ -440,13 +440,13 @@ case MathScriptType::kUnder: case MathScriptType::kOver: case MathScriptType::kSuper: { - NGBlockNode sub = sub_sup_pairs[0].sub; - NGBlockNode sup = sub_sup_pairs[0].sup; - auto first_post_script = sub ? sub : sup; - auto first_post_script_result = ComputeMinAndMaxContentContribution( - Style(), first_post_script, child_input); - first_post_script_result.sizes += - ComputeMinMaxMargins(Style(), first_post_script).InlineSum(); + const NGBlockNode sub = sub_sup_pairs[0].sub; + const NGBlockNode sup = sub_sup_pairs[0].sup; + const auto first_post_script = sub ? sub : sup; + const auto first_post_script_result = + ComputeMinAndMaxContentContributionForMathChild( + Style(), ConstraintSpace(), first_post_script, + child_input.percentage_resolution_block_size); sizes += first_post_script_result.sizes; if (sub) @@ -462,21 +462,21 @@ MinMaxSizes sub_sup_pair_size; unsigned index = 0; do { - auto sub = sub_sup_pairs[index].sub; + const auto sub = sub_sup_pairs[index].sub; if (!sub) continue; - auto sub_result = - ComputeMinAndMaxContentContribution(Style(), sub, child_input); - sub_result.sizes += ComputeMinMaxMargins(Style(), sub).InlineSum(); + auto sub_result = ComputeMinAndMaxContentContributionForMathChild( + Style(), ConstraintSpace(), sub, + child_input.percentage_resolution_block_size); sub_result.sizes -= base_italic_correction; sub_sup_pair_size.Encompass(sub_result.sizes); - auto sup = sub_sup_pairs[index].sup; + const auto sup = sub_sup_pairs[index].sup; if (!sup) continue; - auto sup_result = - ComputeMinAndMaxContentContribution(Style(), sup, child_input); - sup_result.sizes += ComputeMinMaxMargins(Style(), sup).InlineSum(); + const auto sup_result = ComputeMinAndMaxContentContributionForMathChild( + Style(), ConstraintSpace(), sup, + child_input.percentage_resolution_block_size); sub_sup_pair_size.Encompass(sup_result.sizes); sizes += sub_sup_pair_size;
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_under_over_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_under_over_layout_algorithm.cc index 539a1f1..fb4cc7e 100644 --- a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_under_over_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_under_over_layout_algorithm.cc
@@ -341,10 +341,9 @@ if (child.IsOutOfFlowPositioned()) continue; // TODO(crbug.com/1125136): take into account italic correction. - auto child_result = ComputeMinAndMaxContentContribution( - Style(), To<NGBlockNode>(child), child_input); - NGBoxStrut margins = ComputeMinMaxMargins(Style(), child); - child_result.sizes += margins.InlineSum(); + const auto child_result = ComputeMinAndMaxContentContributionForMathChild( + Style(), ConstraintSpace(), To<NGBlockNode>(child), + child_input.percentage_resolution_block_size); sizes.Encompass(child_result.sizes); depends_on_percentage_block_size |=
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc index 014deb716..99e49862 100644 --- a/third_party/blink/renderer/core/loader/document_loader.cc +++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -738,7 +738,8 @@ // We want to allow same-document text fragment navigations if they're coming // from the browser. Do this only on a standard navigation so that we don't // clobber the token when this is called from e.g. history.replaceState. - if (type == WebFrameLoadType::kStandard) { + if (type == WebFrameLoadType::kStandard || + same_document_navigation_source == kSameDocumentNavigationDefault) { has_text_fragment_token_ = TextFragmentAnchor::GenerateNewTokenForSameDocument( new_url.FragmentIdentifier(), type, is_content_initiated, @@ -1823,13 +1824,7 @@ WindowAgent* GetWindowAgentForOrigin(LocalFrame* frame, SecurityOrigin* origin, bool is_origin_keyed) { - // TODO(keishi): Also check if AllowUniversalAccessFromFileURLs might - // dynamically change. - bool has_potential_universal_access_privilege = - !frame->GetSettings()->GetWebSecurityEnabled() || - frame->GetSettings()->GetAllowUniversalAccessFromFileURLs(); return frame->window_agent_factory().GetAgentForOrigin( - has_potential_universal_access_privilege, V8PerIsolateData::MainThreadIsolate(), origin, is_origin_keyed); }
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.cc b/third_party/blink/renderer/core/loader/frame_fetch_context.cc index 9102a14..f766ecf 100644 --- a/third_party/blink/renderer/core/loader/frame_fetch_context.cc +++ b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
@@ -444,7 +444,7 @@ if (!AllowScriptFromSourceWithoutNotifying(request.Url())) return; - // When the runtime flag "FeaturePolicyForClientHints" is enabled, feature + // When the runtime flag "FeaturePolicyForClientHints" is enabled, permissions // policy is used to enable hints for all subresources, based on the policy of // the requesting document, and the origin of the resource. const PermissionsPolicy* policy =
diff --git a/third_party/blink/renderer/core/page/context_menu_controller.cc b/third_party/blink/renderer/core/page/context_menu_controller.cc index ee24dee9..37839a2 100644 --- a/third_party/blink/renderer/core/page/context_menu_controller.cc +++ b/third_party/blink/renderer/core/page/context_menu_controller.cc
@@ -634,30 +634,39 @@ // spelling marker on the word instead of spellchecking it. std::pair<String, String> misspelled_word_and_description = spell_checker.SelectMisspellingAsync(); - data.misspelled_word = - WebString::FromUTF8(misspelled_word_and_description.first.Utf8()) - .Utf16(); - const String& description = misspelled_word_and_description.second; - if (description.length()) { - Vector<String> suggestions; - description.Split('\n', suggestions); - WebVector<std::u16string> web_suggestions(suggestions.size()); - std::transform(suggestions.begin(), suggestions.end(), - web_suggestions.begin(), [](const String& s) { - return WebString::FromUTF8(s.Utf8()).Utf16(); - }); - data.dictionary_suggestions = web_suggestions.ReleaseVector(); - } else if (spell_checker.GetTextCheckerClient()) { - size_t misspelled_offset, misspelled_length; - WebVector<WebString> web_suggestions; - spell_checker.GetTextCheckerClient()->CheckSpelling( - WebString::FromUTF16(data.misspelled_word), misspelled_offset, - misspelled_length, &web_suggestions); - WebVector<std::u16string> suggestions(web_suggestions.size()); - std::transform(web_suggestions.begin(), web_suggestions.end(), - suggestions.begin(), - [](const WebString& s) { return s.Utf16(); }); - data.dictionary_suggestions = suggestions.ReleaseVector(); + const String& misspelled_word = misspelled_word_and_description.first; + if (misspelled_word.length()) { + data.misspelled_word = + WebString::FromUTF8(misspelled_word.Utf8()).Utf16(); + const String& description = misspelled_word_and_description.second; + if (description.length()) { + // Suggestions were cached for the misspelled word (won't be true for + // Hunspell, or Windows platform spellcheck if the + // kWinRetrieveSuggestionsOnlyOnDemand feature flag is set). + Vector<String> suggestions; + description.Split('\n', suggestions); + WebVector<std::u16string> web_suggestions(suggestions.size()); + std::transform(suggestions.begin(), suggestions.end(), + web_suggestions.begin(), [](const String& s) { + return WebString::FromUTF8(s.Utf8()).Utf16(); + }); + data.dictionary_suggestions = web_suggestions.ReleaseVector(); + } else if (spell_checker.GetTextCheckerClient()) { + // No suggestions cached for the misspelled word. Retrieve suggestions + // for it (Windows platform spellchecker will do this later from + // SpellingMenuObserver::InitMenu on the browser process side to avoid a + // blocking IPC here). + size_t misspelled_offset, misspelled_length; + WebVector<WebString> web_suggestions; + spell_checker.GetTextCheckerClient()->CheckSpelling( + WebString::FromUTF16(data.misspelled_word), misspelled_offset, + misspelled_length, &web_suggestions); + WebVector<std::u16string> suggestions(web_suggestions.size()); + std::transform(web_suggestions.begin(), web_suggestions.end(), + suggestions.begin(), + [](const WebString& s) { return s.Utf16(); }); + data.dictionary_suggestions = suggestions.ReleaseVector(); + } } }
diff --git a/third_party/blink/renderer/core/permissions_policy/layout_animations_policy.h b/third_party/blink/renderer/core/permissions_policy/layout_animations_policy.h index 4ed80b1..77e0b1f9 100644 --- a/third_party/blink/renderer/core/permissions_policy/layout_animations_policy.h +++ b/third_party/blink/renderer/core/permissions_policy/layout_animations_policy.h
@@ -14,13 +14,13 @@ class CSSProperty; class ExecutionContext; -// Helper methods for for 'layout-animations' (kLayoutAnimations) feature +// Helper methods for for 'layout-animations' (kLayoutAnimations) permissions // policy. class LayoutAnimationsPolicy { DISALLOW_NEW(); public: - // Returns a set of the CSS properties which are affected by the feature + // Returns a set of the CSS properties which are affected by the permissions // policy 'layout-animations'. static const HashSet<const CSSProperty*>& AffectedCSSProperties();
diff --git a/third_party/blink/renderer/core/permissions_policy/permissions_policy_test.cc b/third_party/blink/renderer/core/permissions_policy/permissions_policy_test.cc index ee34bd9..ae4ba8b0 100644 --- a/third_party/blink/renderer/core/permissions_policy/permissions_policy_test.cc +++ b/third_party/blink/renderer/core/permissions_policy/permissions_policy_test.cc
@@ -649,7 +649,7 @@ PolicyParserMessageBuffer permissions_policy_logger("Permissions Policy: "); // 'geolocation' in permissions policy has a invalid allowlist item, which - // results in an empty allowlist, which is equivalent to 'none' in feature + // results in an empty allowlist, which is equivalent to "()" in permissions // policy syntax. CheckParsedPolicy( PermissionsPolicyParser::ParseHeader(
diff --git a/third_party/blink/renderer/core/scroll/scrollable_area.cc b/third_party/blink/renderer/core/scroll/scrollable_area.cc index c9914bbf..6576988 100644 --- a/third_party/blink/renderer/core/scroll/scrollable_area.cc +++ b/third_party/blink/renderer/core/scroll/scrollable_area.cc
@@ -436,7 +436,7 @@ if (offset_changed && GetLayoutBox() && GetLayoutBox()->GetFrameView()) { GetLayoutBox()->GetFrameView()->GetLayoutShiftTracker().NotifyScroll( - scroll_type); + scroll_type, delta); } GetScrollAnimator().SetCurrentOffset(offset);
diff --git a/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc b/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc index 320598e3..770c2a9 100644 --- a/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc +++ b/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc
@@ -3,6 +3,9 @@ // found in the LICENSE file. #include "third_party/blink/renderer/core/speculation_rules/document_speculation_rules.h" +#include "third_party/blink/public/common/browser_interface_broker_proxy.h" +#include "third_party/blink/renderer/core/execution_context/execution_context.h" +#include "third_party/blink/renderer/platform/wtf/vector.h" namespace blink { @@ -27,15 +30,74 @@ } DocumentSpeculationRules::DocumentSpeculationRules(Document& document) - : Supplement(document) {} + : Supplement(document), host_(document.GetExecutionContext()) {} void DocumentSpeculationRules::AddRuleSet(SpeculationRuleSet* rule_set) { rule_sets_.push_back(rule_set); + + if (!has_pending_update_) { + has_pending_update_ = true; + auto task_runner = + GetSupplementable()->GetExecutionContext()->GetTaskRunner( + TaskType::kIdleTask); + task_runner->PostTask( + base::Location::Current(), + WTF::Bind(&DocumentSpeculationRules::UpdateSpeculationCandidates, + WrapWeakPersistent(this))); + } } void DocumentSpeculationRules::Trace(Visitor* visitor) const { Supplement::Trace(visitor); visitor->Trace(rule_sets_); + visitor->Trace(host_); +} + +mojom::blink::SpeculationHost* DocumentSpeculationRules::GetHost() { + if (!host_.is_bound()) { + auto* execution_context = GetSupplementable()->GetExecutionContext(); + if (!execution_context) + return nullptr; + execution_context->GetBrowserInterfaceBroker().GetInterface( + host_.BindNewPipeAndPassReceiver( + execution_context->GetTaskRunner(TaskType::kInternalDefault))); + } + return host_.get(); +} + +void DocumentSpeculationRules::UpdateSpeculationCandidates() { + has_pending_update_ = false; + + mojom::blink::SpeculationHost* host = GetHost(); + if (!host) + return; + + Vector<mojom::blink::SpeculationCandidatePtr> candidates; + auto push_candidates = [&candidates]( + mojom::blink::SpeculationAction action, + const HeapVector<Member<SpeculationRule>>& rules) { + for (SpeculationRule* rule : rules) { + mojom::blink::SpeculationCandidate candidate; + candidate.action = action; + candidate.requires_anonymous_client_ip_when_cross_origin = + rule->requires_anonymous_client_ip_when_cross_origin(); + for (const KURL& url : rule->urls()) { + candidate.url = url; + candidates.push_back( + mojom::blink::SpeculationCandidate::New(candidate)); + } + } + }; + + for (SpeculationRuleSet* rule_set : rule_sets_) { + push_candidates(mojom::blink::SpeculationAction::kPrefetch, + rule_set->prefetch_rules()); + push_candidates(mojom::blink::SpeculationAction::kPrefetchWithSubresources, + rule_set->prefetch_with_subresources_rules()); + } + + host->UpdateSpeculationCandidates_PendingSecurityReview( + std::move(candidates)); } } // namespace blink
diff --git a/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.h b/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.h index 60f861a..d4b4b19e 100644 --- a/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.h +++ b/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.h
@@ -5,17 +5,21 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SPECULATION_RULES_DOCUMENT_SPECULATION_RULES_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_SPECULATION_RULES_DOCUMENT_SPECULATION_RULES_H_ +#include "third_party/blink/public/mojom/speculation_rules/speculation_rules.mojom-blink.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/speculation_rules/speculation_rule_set.h" #include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" #include "third_party/blink/renderer/platform/heap/heap.h" +#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h" #include "third_party/blink/renderer/platform/supplementable.h" namespace blink { // This corresponds to the document's list of speculation rule sets. +// +// Updates are pushed asynchronously. class CORE_EXPORT DocumentSpeculationRules : public GarbageCollected<DocumentSpeculationRules>, public Supplement<Document> { @@ -37,7 +41,16 @@ void Trace(Visitor*) const override; private: + // Retrieves a valid proxy to the speculation host in the browser. + // May be null if the execution context does not exist. + mojom::blink::SpeculationHost* GetHost(); + + // Pushes the current speculation candidates to the browser, immediately. + void UpdateSpeculationCandidates(); + HeapVector<Member<SpeculationRuleSet>> rule_sets_; + HeapMojoRemote<mojom::blink::SpeculationHost> host_; + bool has_pending_update_ = false; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/speculation_rules/speculation_rule_set_test.cc b/third_party/blink/renderer/core/speculation_rules/speculation_rule_set_test.cc index fc14dd9..80bbaca 100644 --- a/third_party/blink/renderer/core/speculation_rules/speculation_rule_set_test.cc +++ b/third_party/blink/renderer/core/speculation_rules/speculation_rule_set_test.cc
@@ -1,7 +1,14 @@ #include "third_party/blink/renderer/core/speculation_rules/speculation_rule_set.h" +#include "base/bind.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "mojo/public/cpp/system/message_pipe.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/browser_interface_broker_proxy.h" +#include "third_party/blink/public/mojom/speculation_rules/speculation_rules.mojom-blink.h" +#include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/settings.h" #include "third_party/blink/renderer/core/html/html_head_element.h" @@ -9,6 +16,7 @@ #include "third_party/blink/renderer/core/speculation_rules/document_speculation_rules.h" #include "third_party/blink/renderer/core/testing/dummy_page_holder.h" #include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h" +#include "third_party/blink/renderer/platform/wtf/vector.h" namespace blink { namespace { @@ -228,5 +236,92 @@ ElementsAre(MatchesListOfURLs("https://example.com/foo"))); } +class StubSpeculationHost : public mojom::blink::SpeculationHost { + public: + using Candidates = Vector<mojom::blink::SpeculationCandidatePtr>; + + const Candidates& candidates() const { return candidates_; } + void SetDoneClosure(base::OnceClosure done) { + done_closure_ = std::move(done); + } + + void BindUnsafe(mojo::ScopedMessagePipeHandle handle) { + Bind(mojo::PendingReceiver<SpeculationHost>(std::move(handle))); + } + + void Bind(mojo::PendingReceiver<SpeculationHost> receiver) { + receiver_.Bind(std::move(receiver)); + receiver_.set_disconnect_handler(base::BindOnce( + &StubSpeculationHost::OnConnectionLost, base::Unretained(this))); + } + + void UpdateSpeculationCandidates_PendingSecurityReview( + Candidates candidates) override { + candidates_ = std::move(candidates); + if (done_closure_) + std::move(done_closure_).Run(); + } + + void OnConnectionLost() { + if (done_closure_) + std::move(done_closure_).Run(); + } + + private: + mojo::Receiver<SpeculationHost> receiver_{this}; + Vector<mojom::blink::SpeculationCandidatePtr> candidates_; + base::OnceClosure done_closure_; +}; + +TEST_F(SpeculationRuleSetTest, PropagatesToBrowser) { + // A <script> with a case-insensitive type match should be propagated to the + // browser via Mojo. + // TODO(jbroman): Should we need to enable script? Should that be bypassed? + DummyPageHolder page_holder; + page_holder.GetFrame().GetSettings()->SetScriptEnabled(true); + + StubSpeculationHost speculation_host; + page_holder.GetFrame() + .DomWindow() + ->GetBrowserInterfaceBroker() + .SetBinderForTesting( + mojom::blink::SpeculationHost::Name_, + WTF::BindRepeating(&StubSpeculationHost::BindUnsafe, + WTF::Unretained(&speculation_host))); + + base::RunLoop run_loop; + speculation_host.SetDoneClosure(run_loop.QuitClosure()); + + Document& document = page_holder.GetDocument(); + HTMLScriptElement* script = + MakeGarbageCollected<HTMLScriptElement>(document, CreateElementFlags()); + script->setAttribute(html_names::kTypeAttr, "SpEcUlAtIoNrUlEs"); + script->setText( + R"({"prefetch_with_subresources": [ + {"source": "list", + "urls": ["https://example.com/foo", "https://example.com/bar"], + "requires": ["anonymous-client-ip-when-cross-origin"]} + ]})"); + document.head()->appendChild(script); + run_loop.Run(); + + const auto& candidates = speculation_host.candidates(); + ASSERT_EQ(candidates.size(), 2u); + { + const auto& candidate = candidates[0]; + EXPECT_EQ(candidate->action, + mojom::blink::SpeculationAction::kPrefetchWithSubresources); + EXPECT_EQ(candidate->url, "https://example.com/foo"); + EXPECT_TRUE(candidate->requires_anonymous_client_ip_when_cross_origin); + } + { + const auto& candidate = candidates[1]; + EXPECT_EQ(candidate->action, + mojom::blink::SpeculationAction::kPrefetchWithSubresources); + EXPECT_EQ(candidate->url, "https://example.com/bar"); + EXPECT_TRUE(candidate->requires_anonymous_client_ip_when_cross_origin); + } +} + } // namespace } // namespace blink
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc index 7a0d03c1..7b00990 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -1230,9 +1230,7 @@ if (child_token && !(IsDetached() || ChildCountIncludingIgnored())) { ui::AXTreeID child_tree_id = ui::AXTreeID::FromToken(child_token.value()); - node_data->AddStringAttribute( - ax::mojom::blink::StringAttribute::kChildTreeId, - child_tree_id.ToString()); + node_data->AddChildTreeId(child_tree_id); } } }
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index c9ba35b..970fb52 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -633,7 +633,7 @@ }, { name: "CSSPseudoDir", - status: "stable", + status: "experimental", }, { name: "CSSPseudoIs",
diff --git a/third_party/blink/web_tests/css3/filters/backdrop-filter-clip-radius-zoom.html b/third_party/blink/web_tests/css3/filters/backdrop-filter-clip-radius-zoom.html index 7cd3464..b694e342 100644 --- a/third_party/blink/web_tests/css3/filters/backdrop-filter-clip-radius-zoom.html +++ b/third_party/blink/web_tests/css3/filters/backdrop-filter-clip-radius-zoom.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>Backdrop filter clipping radius with zoom</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <!--You should see two completely filled black rectangles with rounded corners.-->
diff --git a/third_party/blink/web_tests/css3/filters/backdrop-filter-clip-rect-zoom.html b/third_party/blink/web_tests/css3/filters/backdrop-filter-clip-rect-zoom.html index 645198b..f51eef0 100644 --- a/third_party/blink/web_tests/css3/filters/backdrop-filter-clip-rect-zoom.html +++ b/third_party/blink/web_tests/css3/filters/backdrop-filter-clip-rect-zoom.html
@@ -2,7 +2,7 @@ <html style="zoom:5"> <meta charset="utf-8"> <title>backdrop-filter: Clip the filter at border box of element</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="backdrop-filter-clip-rect-zoom-ref.html">
diff --git a/third_party/blink/web_tests/css3/filters/backdrop-filter-edge-clipping-2.html b/third_party/blink/web_tests/css3/filters/backdrop-filter-edge-clipping-2.html index dea3aeb..12fc3b7 100644 --- a/third_party/blink/web_tests/css3/filters/backdrop-filter-edge-clipping-2.html +++ b/third_party/blink/web_tests/css3/filters/backdrop-filter-edge-clipping-2.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: Filter input is at element bounds</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="backdrop-filter-edge-clipping-2-ref.html">
diff --git a/third_party/blink/web_tests/css3/filters/backdrop-filter-plus-mask-large.html b/third_party/blink/web_tests/css3/filters/backdrop-filter-plus-mask-large.html index 2706b3d..03c0194 100644 --- a/third_party/blink/web_tests/css3/filters/backdrop-filter-plus-mask-large.html +++ b/third_party/blink/web_tests/css3/filters/backdrop-filter-plus-mask-large.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: Correctly apply masks/clips to backdrop-filter content</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="backdrop-filter-plus-mask-ref.html">
diff --git a/third_party/blink/web_tests/css3/filters/backdrop-filter-plus-mask.html b/third_party/blink/web_tests/css3/filters/backdrop-filter-plus-mask.html index 9909d66f..f0d5359 100644 --- a/third_party/blink/web_tests/css3/filters/backdrop-filter-plus-mask.html +++ b/third_party/blink/web_tests/css3/filters/backdrop-filter-plus-mask.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: Correctly apply masks/clips to backdrop-filter content</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="backdrop-filter-plus-mask-ref.html">
diff --git a/third_party/blink/web_tests/dom/attr/id-update-map-crash.html b/third_party/blink/web_tests/dom/attr/id-update-map-crash.html index 60ade88..48c0d6c 100644 --- a/third_party/blink/web_tests/dom/attr/id-update-map-crash.html +++ b/third_party/blink/web_tests/dom/attr/id-update-map-crash.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset="utf-8"> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://crbug.com/1178302"> <meta name="assert" content="The renderer should not crash.">
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/fixed-z-index-blend-ref.html b/third_party/blink/web_tests/external/wpt/css/css-position/fixed-z-index-blend-ref.html index 2675401..864297b 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-position/fixed-z-index-blend-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/css-position/fixed-z-index-blend-ref.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>fixed position, z-index, and mix-blend-mode</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <div style="width: 100px; height:4000px;"></div> <div style="background: green; width: 100px; height:100px;"></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/fixed-z-index-blend.html b/third_party/blink/web_tests/external/wpt/css/css-position/fixed-z-index-blend.html index 55582286..2b0988d 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-position/fixed-z-index-blend.html +++ b/third_party/blink/web_tests/external/wpt/css/css-position/fixed-z-index-blend.html
@@ -6,7 +6,7 @@ <link rel="help" href="https://www.w3.org/TR/compositing-1/#mix-blend-mode"> <meta name="assert" content="Tests fixed, z-index, and mix-blend-mode. Passes if there is a green box when the page is scrolled to the bottom."> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="match" href="fixed-z-index-blend-ref.html"> <div class="blend"></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/sticky/position-sticky-scroll-with-clip-and-abspos-ref.html b/third_party/blink/web_tests/external/wpt/css/css-position/sticky/position-sticky-scroll-with-clip-and-abspos-ref.html index a36934e38..d9fe863 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-position/sticky/position-sticky-scroll-with-clip-and-abspos-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/css-position/sticky/position-sticky-scroll-with-clip-and-abspos-ref.html
@@ -2,7 +2,7 @@ <html class="reftest-wait"> <meta charset="utf-8"> <title>position:sticky should operate correctly</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org">
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/sticky/position-sticky-scroll-with-clip-and-abspos.html b/third_party/blink/web_tests/external/wpt/css/css-position/sticky/position-sticky-scroll-with-clip-and-abspos.html index 46085b4..fb7edfe 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-position/sticky/position-sticky-scroll-with-clip-and-abspos.html +++ b/third_party/blink/web_tests/external/wpt/css/css-position/sticky/position-sticky-scroll-with-clip-and-abspos.html
@@ -2,7 +2,7 @@ <html class="reftest-wait"> <meta charset="utf-8"> <title>position:sticky should operate correctly</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://www.w3.org/TR/css-position-3/#sticky-pos" /> <meta name="assert" content="This test checks that the combination of position:sticky, overflow clip, and out-of-flow descendants are properly displayed when scrolled" /> <link rel="match" href="position-sticky-scroll-with-clip-and-abspos-ref.html">
diff --git a/third_party/blink/web_tests/external/wpt/css/css-sizing/button-min-width.html b/third_party/blink/web_tests/external/wpt/css/css-sizing/button-min-width.html index d27d0e1..8f780ec 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-sizing/button-min-width.html +++ b/third_party/blink/web_tests/external/wpt/css/css-sizing/button-min-width.html
@@ -2,7 +2,7 @@ <html> <meta charset="utf-8"> <title>min-width: Should apply to buttons</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://www.w3.org/TR/CSS2/visudet.html#min-max-widths"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom-view/long_scroll_composited-ref.html b/third_party/blink/web_tests/external/wpt/css/cssom-view/long_scroll_composited-ref.html index 6914cba3..3278d33 100644 --- a/third_party/blink/web_tests/external/wpt/css/cssom-view/long_scroll_composited-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/cssom-view/long_scroll_composited-ref.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>Long scrolling should work properly</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org">
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom-view/long_scroll_composited.html b/third_party/blink/web_tests/external/wpt/css/cssom-view/long_scroll_composited.html index aa91023..68a468b 100644 --- a/third_party/blink/web_tests/external/wpt/css/cssom-view/long_scroll_composited.html +++ b/third_party/blink/web_tests/external/wpt/css/cssom-view/long_scroll_composited.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>Long scrolling should work properly</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://www.w3.org/TR/cssom-view/#scrolling"> <link rel="match" href="long_scroll_composited-ref.html">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-background-color-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-background-color-ref.html index a3dbad0b..4997007f 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-background-color-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-background-color-ref.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: Basic operation of filter with background color</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-background-color.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-background-color.html index c48cade..2623c11 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-background-color.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-background-color.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: Basic operation of filter with background color</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="backdrop-filter-basic-background-color-ref.html">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-opacity-2-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-opacity-2-ref.html index 1027811..3a27cf3 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-opacity-2-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-opacity-2-ref.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: Basic operation of filter with opacity</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-opacity-2.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-opacity-2.html index 8d7df67..c40e8bc0 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-opacity-2.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-opacity-2.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: Basic operation of filter with opacity</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="backdrop-filter-basic-opacity-2-ref.html">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-opacity-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-opacity-ref.html index e0c76c0..7e6d45c 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-opacity-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-opacity-ref.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: Basic operation of filter with opacity</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-opacity.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-opacity.html index 4cc5f33..52662f3 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-opacity.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-opacity.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: Basic operation of filter with opacity</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="backdrop-filter-basic-opacity-ref.html">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-ref.html index 049e7c8..71e42e5 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-ref.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: Basic operation of filter</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic.html index 711064e..d5d170d 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: Basic operation of filter</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="backdrop-filter-basic-ref.html">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-clip-rect-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-clip-rect-ref.html index 9082fa3..d1e785ec 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-clip-rect-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-clip-rect-ref.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: Clip the filter at border box of element</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-clip-rect.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-clip-rect.html index 4fc4b73..5d5c7071 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-clip-rect.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-clip-rect.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: Clip the filter at border box of element</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="backdrop-filter-clip-rect-ref.html">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-clipped-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-clipped-ref.html index 60b0b6c..5100d6a6 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-clipped-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-clipped-ref.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: Basic operation of filter</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-clipped.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-clipped.html index bc25b259..b5535a8 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-clipped.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-clipped.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: A rounded-corner clip rect parent should not form a Backdrop Root</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="backdrop-filter-clipped-ref.html">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-containing-block-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-containing-block-ref.html index f429dd9a..389802b 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-containing-block-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-containing-block-ref.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: Forms a containing block for fixed/absolute</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-containing-block.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-containing-block.html index 7300d7d..364405c 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-containing-block.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-containing-block.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: Forms a containing block for fixed/absolute</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="backdrop-filter-containing-block-ref.html">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-edge-behavior-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-edge-behavior-ref.html index 3b8a31c..b605e3251 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-edge-behavior-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-edge-behavior-ref.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: Edge behavior</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-edge-behavior.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-edge-behavior.html index 9c279c8..29f5dc51 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-edge-behavior.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-edge-behavior.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: Edge behavior</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="help" href="https://crbug.com/1165868"> <link rel="match" href="backdrop-filter-edge-behavior-ref.html">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-edge-clipping.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-edge-clipping.html index 5d09c414..f6f7d89 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-edge-clipping.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-edge-clipping.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: Filter input is at element bounds</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="backdrop-filter-paint-order-ref.html">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-edge-pixels-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-edge-pixels-ref.html index bbd5628..36c509ff 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-edge-pixels-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-edge-pixels-ref.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: Edge pixels shouldn't get filtered</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-edge-pixels.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-edge-pixels.html index c26e70c..5a70020 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-edge-pixels.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-edge-pixels.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: Edge pixels shouldn't get filtered</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="backdrop-filter-edge-pixels-ref.html">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-fixed-clip-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-fixed-clip-ref.html index 1fa5967..38a8c8b 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-fixed-clip-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-fixed-clip-ref.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: Should not filter outside of clip/scroll.</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-fixed-clip.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-fixed-clip.html index 2550eb1..346fad9 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-fixed-clip.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-fixed-clip.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: Should not filter outside of clip/scroll.</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="backdrop-filter-fixed-clip-ref.html">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-isolation-fixed.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-isolation-fixed.html index f7835a1..9954ecb 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-isolation-fixed.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-isolation-fixed.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: fixed position should not cause a backdrop root.</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="backdrop-filter-non-isolation-ref.html">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-isolation-isolate.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-isolation-isolate.html index 008f6f8..97bb7fe2 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-isolation-isolate.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-isolation-isolate.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: isolation isolate should not cause a backdrop root.</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="backdrop-filter-non-isolation-ref.html">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-isolation-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-isolation-ref.html index 470704a6..fc2bccc3 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-isolation-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-isolation-ref.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: Should not filter outside parent stacking context.</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-isolation.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-isolation.html index 500228d..06791f7 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-isolation.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-isolation.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: Should not filter outside parent stacking context.</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="backdrop-filter-isolation-ref.html">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-non-isolation-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-non-isolation-ref.html index 0453d7f..229d6b4f 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-non-isolation-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-non-isolation-ref.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: Isolation</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-paint-order-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-paint-order-ref.html index bd82e520..78b135b 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-paint-order-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-paint-order-ref.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: Only filter objects painted before</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-paint-order.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-paint-order.html index 8853153..b5499d47 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-paint-order.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-paint-order.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: Only filter objects painted before</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="backdrop-filter-paint-order-ref.html">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-plus-filter-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-plus-filter-ref.html index bf476ea..aa421fd98 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-plus-filter-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-plus-filter-ref.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: Only filter objects painted before</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-plus-filter.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-plus-filter.html index 3a2d8fe..546786d8 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-plus-filter.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-plus-filter.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: Correctly apply filters to backdrop-filter content</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="backdrop-filter-plus-filter-ref.html">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-plus-opacity-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-plus-opacity-ref.html index 347b7a6..aa7224fd 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-plus-opacity-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-plus-opacity-ref.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: Correctly apply backdrop-filter with opacity</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-plus-opacity.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-plus-opacity.html index cb189f9..4909e59 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-plus-opacity.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-plus-opacity.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: Correctly apply backdrop-filter with opacity</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="backdrop-filter-plus-opacity-ref.html">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-reference-filter.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-reference-filter.html index 6c61a96..60a51d67 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-reference-filter.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-reference-filter.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: Correctly apply reference filter</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="backdrop-filter-clip-rect-ref.html">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-update-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-update-ref.html index ec4d806..6e719b6 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-update-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-update-ref.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: Update filter value</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-update.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-update.html index de629a1..6a81fc6 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-update.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-update.html
@@ -2,7 +2,7 @@ <html class="reftest-wait"> <meta charset="utf-8"> <title>backdrop-filter: Update filter value</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="backdrop-filter-update-ref.html">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-zero-size-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-zero-size-ref.html index 05383cd..e8f5ef7 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-zero-size-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-zero-size-ref.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: Zero-size div with backdrop filter shouldn't filter anything</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-zero-size.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-zero-size.html index bcefe042..ecd7974 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-zero-size.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-zero-size.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>backdrop-filter: Zero-size div with backdrop filter shouldn't filter anything</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="backdrop-filter-zero-size-ref.html">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-brightness-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-brightness-ref.html index cb6ea67..999894eb 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-brightness-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-brightness-ref.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Brightness</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-brightness.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-brightness.html index 1cc63ed..dfb8ba2 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-brightness.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-brightness.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Brightness</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="backdrop-filters-brightness-ref.html"> <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-contrast-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-contrast-ref.html index 7978fec..01b38f7 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-contrast-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-contrast-ref.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Contrast</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-contrast.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-contrast.html index 15c97a9..e3150d1 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-contrast.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-contrast.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Contrast</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="backdrop-filters-contrast-ref.html"> <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-grayscale-001.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-grayscale-001.html index 75fe110b8..9bdcdb4 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-grayscale-001.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-grayscale-001.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters: Grayscale(50%)</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#supported-filter-functions"> <link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=831485">
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-hue-rotate-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-hue-rotate-ref.html index c70f6bc..177872c 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-hue-rotate-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-hue-rotate-ref.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Hue Rotate</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-hue-rotate.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-hue-rotate.html index 17d2a3c..203a6b7 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-hue-rotate.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-hue-rotate.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Hue-rotate</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="backdrop-filters-hue-rotate-ref.html"> <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-invert-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-invert-ref.html index ed3da42..61f2856 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-invert-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-invert-ref.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Invert</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-invert.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-invert.html index 59ec599..7e0dea6 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-invert.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-invert.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Invert</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="backdrop-filters-invert-ref.html"> <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-opacity-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-opacity-ref.html index fef130ea..acdf050 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-opacity-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-opacity-ref.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Opacity</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-opacity.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-opacity.html index 850c41d..b3703c3 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-opacity.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-opacity.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Opacity</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="backdrop-filters-opacity-ref.html"> <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-saturate-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-saturate-ref.html index d8b7234..f3407f3 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-saturate-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-saturate-ref.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Saturate</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-saturate.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-saturate.html index f131641..2b7d33b2 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-saturate.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-saturate.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Saturate</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="backdrop-filters-saturate-ref.html"> <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-sepia-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-sepia-ref.html index 624fb87..eae10fe 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-sepia-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-sepia-ref.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Sepia</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-sepia.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-sepia.html index bcfae3d2..3d10bf3 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-sepia.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-sepia.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Sepia</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="backdrop-filters-sepia-ref.html"> <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-blur-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-blur-ref.html index e433070b..643d084 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-blur-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-blur-ref.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Blur Reference</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <style> .square { position: absolute;
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-blur.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-blur.html index 3d883c2..0b3e429 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-blur.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-blur.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Blur</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="css-backdrop-filters-animation-blur-ref.html"> <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-brightness-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-brightness-ref.html index 8ba5b459..bf894ac 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-brightness-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-brightness-ref.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Brightness Reference</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <style> .square { position: absolute;
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-brightness.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-brightness.html index d377e5e..cdcd9b5 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-brightness.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-brightness.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Brightness</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="css-backdrop-filters-animation-brightness-ref.html"> <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-combined-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-combined-ref.html index b4c6bc9..575c56d 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-combined-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-combined-ref.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Combined filters 001 Reference</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <style> .square { position: absolute;
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-combined.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-combined.html index 920dc823..e8661cc 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-combined.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-combined.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Combined filters 001</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="css-backdrop-filters-animation-combined-ref.html"> <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-contrast-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-contrast-ref.html index e1bf0605..b118df6b 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-contrast-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-contrast-ref.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Contrast Reference</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <style> .square { position: absolute;
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-contrast.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-contrast.html index d9709f8..537f65cf 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-contrast.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-contrast.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Contrast</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="css-backdrop-filters-animation-contrast-ref.html"> <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-drop-shadow-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-drop-shadow-ref.html index 0b4a3f2d..4d1f437 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-drop-shadow-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-drop-shadow-ref.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Drop Shadow Reference</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <style> .square { position: absolute;
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-drop-shadow.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-drop-shadow.html index c7e19a9..c0f634a 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-drop-shadow.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-drop-shadow.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Drop Shadow</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="css-backdrop-filters-animation-drop-shadow-ref.html"> <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-grayscale-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-grayscale-ref.html index 75e457a..07265200 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-grayscale-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-grayscale-ref.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Blur Reference</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <style> .square { position: absolute;
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-grayscale.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-grayscale.html index c04118c..fe08d8f 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-grayscale.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-grayscale.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Grayscale</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="css-backdrop-filters-animation-grayscale-ref.html"> <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-hue-rotate-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-hue-rotate-ref.html index 0651e89e..f10855da 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-hue-rotate-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-hue-rotate-ref.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Hue-rotate Reference</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <style> .square { position: absolute;
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-hue-rotate.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-hue-rotate.html index e3cdd1f..3bc8fe49 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-hue-rotate.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-hue-rotate.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Hue-rotate</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="css-backdrop-filters-animation-hue-rotate-ref.html"> <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-invert-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-invert-ref.html index 50964200..9d4efb43 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-invert-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-invert-ref.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Invert Reference</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <style> .square { position: absolute;
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-invert.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-invert.html index 963ab7ed..3291fa54 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-invert.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-invert.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Invert</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="css-backdrop-filters-animation-invert-ref.html"> <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-opacity-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-opacity-ref.html index c9253d28..d95b01ab 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-opacity-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-opacity-ref.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Opacity Reference</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <style> .square { position: absolute;
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-opacity.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-opacity.html index 72078e7c..66bffefd 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-opacity.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-opacity.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Opacity</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="css-backdrop-filters-animation-opacity-ref.html"> <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-saturate-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-saturate-ref.html index 7f7b67f..572ae31 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-saturate-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-saturate-ref.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Saturate Reference</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <style> .square { position: absolute;
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-saturate.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-saturate.html index 13e2773..dda1671 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-saturate.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-saturate.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Saturate</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="css-backdrop-filters-animation-saturate-ref.html"> <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-sepia-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-sepia-ref.html index b368abb..4161d90c 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-sepia-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-sepia-ref.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Sepia Reference</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <style> .square { position: absolute;
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-sepia.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-sepia.html index 8cd9290..c28d3f9 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-sepia.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/css-backdrop-filters-animation-sepia.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Sepia</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="css-backdrop-filters-animation-sepia-ref.html"> <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/reference/backdrop-filters-grayscale-001-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/reference/backdrop-filters-grayscale-001-ref.html index eb403f16..ba01ac6 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/reference/backdrop-filters-grayscale-001-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/reference/backdrop-filters-grayscale-001-ref.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>CSS Backdrop Filters Animation: Grayscale</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <style>
diff --git a/third_party/blink/web_tests/external/wpt/custom-elements/customized-built-in-constructor-exceptions.html b/third_party/blink/web_tests/external/wpt/custom-elements/customized-built-in-constructor-exceptions.html index f9c440f..fbc1a6fd 100644 --- a/third_party/blink/web_tests/external/wpt/custom-elements/customized-built-in-constructor-exceptions.html +++ b/third_party/blink/web_tests/external/wpt/custom-elements/customized-built-in-constructor-exceptions.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>Customized built-in element constructor behavior</title> -<meta name='author' title='Mason Freed' href='mailto:masonfreed@chromium.org'> +<meta name='author' href='mailto:masonf@chromium.org'> <link rel='help' href='https://dom.spec.whatwg.org/#concept-create-element'> <script src='/resources/testharness.js'></script> <script src='/resources/testharnessreport.js'></script>
diff --git a/third_party/blink/web_tests/external/wpt/custom-elements/element-internals-shadowroot.html b/third_party/blink/web_tests/external/wpt/custom-elements/element-internals-shadowroot.html index 0afd43dd..7ec0896 100644 --- a/third_party/blink/web_tests/external/wpt/custom-elements/element-internals-shadowroot.html +++ b/third_party/blink/web_tests/external/wpt/custom-elements/element-internals-shadowroot.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>ElementInternals.shadowRoot</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://html.spec.whatwg.org/#dom-elementinternals-shadowroot"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/dom/svg-insert-crash.html b/third_party/blink/web_tests/external/wpt/dom/svg-insert-crash.html index 539fb1f..80eec1f 100644 --- a/third_party/blink/web_tests/external/wpt/dom/svg-insert-crash.html +++ b/third_party/blink/web_tests/external/wpt/dom/svg-insert-crash.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset="utf-8"> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://crbug.com/1029262"> <meta name="assert" content="The renderer should not crash."> <script src="/resources/testharness.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-page/iframe-scrolling-attribute-ref.html b/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-page/iframe-scrolling-attribute-ref.html index 5697b06..424e039e 100644 --- a/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-page/iframe-scrolling-attribute-ref.html +++ b/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-page/iframe-scrolling-attribute-ref.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>iframe: changing the scrolling attribute</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org">
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-page/iframe-scrolling-attribute-values-ref.html b/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-page/iframe-scrolling-attribute-values-ref.html index 5c416b2..2ead59a 100644 --- a/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-page/iframe-scrolling-attribute-values-ref.html +++ b/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-page/iframe-scrolling-attribute-values-ref.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>The scrolling attribute</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org">
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-page/iframe-scrolling-attribute-values.html b/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-page/iframe-scrolling-attribute-values.html index 8213b8d..997745b 100644 --- a/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-page/iframe-scrolling-attribute-values.html +++ b/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-page/iframe-scrolling-attribute-values.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>The scrolling attribute</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#the-page"> <link rel="match" href="iframe-scrolling-attribute-values-ref.html"> <meta name="fuzzy" content="maxDifference=0-1;totalPixels=0-4">
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-page/iframe-scrolling-attribute.html b/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-page/iframe-scrolling-attribute.html index 3af14871..d04e2dd5 100644 --- a/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-page/iframe-scrolling-attribute.html +++ b/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-page/iframe-scrolling-attribute.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>iframe: changing the scrolling attribute</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#the-page"> <link rel="match" href="iframe-scrolling-attribute-ref.html">
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/the-details-element/details-blockification.html b/third_party/blink/web_tests/external/wpt/html/rendering/the-details-element/details-blockification.html index cc94e92..9600748 100644 --- a/third_party/blink/web_tests/external/wpt/html/rendering/the-details-element/details-blockification.html +++ b/third_party/blink/web_tests/external/wpt/html/rendering/the-details-element/details-blockification.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>CSS Test: details children blockification</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#the-details-and-summary-elements"> <meta name="assert" content="Ensure blockification of <details> children"> <script src=/resources/testharness.js></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/document-metadata/the-style-element/style_load_event.html b/third_party/blink/web_tests/external/wpt/html/semantics/document-metadata/the-style-element/style_load_event.html index 911a088..9e19855 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/document-metadata/the-style-element/style_load_event.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/document-metadata/the-style-element/style_load_event.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>HTML Test: The style load event should fire when textContent is changed</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://html.spec.whatwg.org/multipage/semantics.html#update-a-style-block"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-0/form-double-submit-2.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-0/form-double-submit-2.html index 4c715de2..f7939e0 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-0/form-double-submit-2.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-0/form-double-submit-2.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset="utf-8"> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#form-submission-algorithm"> <script src="/resources/testharness.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-0/form-double-submit-3.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-0/form-double-submit-3.html index cdb50d2..fbb6a42 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-0/form-double-submit-3.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-0/form-double-submit-3.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset="utf-8"> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#form-submission-algorithm"> <script src="/resources/testharness.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-0/form-double-submit-to-different-origin-frame.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-0/form-double-submit-to-different-origin-frame.html index 17ad1b1..aee1d41 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-0/form-double-submit-to-different-origin-frame.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-0/form-double-submit-to-different-origin-frame.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset="utf-8"> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#form-submission-algorithm"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-0/form-double-submit.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-0/form-double-submit.html index 005f393..b6ea0ce 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-0/form-double-submit.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-0/form-double-submit.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset="utf-8"> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#form-submission-algorithm"> <script src="/resources/testharness.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-anchor-nesting.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-anchor-nesting.tentative.html index 00b1140..8c375124 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-anchor-nesting.tentative.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-anchor-nesting.tentative.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8" /> <title>Popup anchor nesting</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel=help href="https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/Popup/explainer.md"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-element-basic.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-element-basic.tentative.html index 0fcc7f4..9909b2f 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-element-basic.tentative.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-element-basic.tentative.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset="utf-8"> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel=help href="https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/Popup/explainer.md"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-hidden-display-ref.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-hidden-display-ref.tentative.html index 7f4ced3..e7cb73c 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-hidden-display-ref.tentative.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-hidden-display-ref.tentative.html
@@ -1,5 +1,5 @@ <!DOCTYPE html> <meta charset="utf-8"> -<link rel=author title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel=author href="mailto:masonf@chromium.org"> No popup should be displayed here.<p>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-hidden-display.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-hidden-display.tentative.html index c80aecf1..8a070b9 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-hidden-display.tentative.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-hidden-display.tentative.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset="utf-8"> -<link rel=author title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel=author href="mailto:masonf@chromium.org"> <link rel=help href="https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/Popup/explainer.md"> <link rel=match href="popup-hidden-display-ref.tentative.html">
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-inside-display-none.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-inside-display-none.tentative.html index 824e7005..745403d 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-inside-display-none.tentative.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-inside-display-none.tentative.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset="utf-8"> -<link rel=author title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel=author href="mailto:masonf@chromium.org"> <link rel=help href="https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/Popup/explainer.md"> <link rel=match href="popup-hidden-display-ref.tentative.html">
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-light-dismiss-on-scroll.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-light-dismiss-on-scroll.tentative.html index 3f35ec24..28dd4f4 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-light-dismiss-on-scroll.tentative.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-light-dismiss-on-scroll.tentative.html
@@ -2,7 +2,7 @@ <html lang="en"> <meta charset="utf-8" /> <title>Popup light dismiss on scroll</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel=help href="https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/Popup/explainer.md"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-light-dismiss.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-light-dismiss.tentative.html index f2a55aa1..613b659 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-light-dismiss.tentative.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-light-dismiss.tentative.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8" /> <title>Popup light dismiss behavior</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel=help href="https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/Popup/explainer.md"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-open-display-ref.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-open-display-ref.tentative.html index 1b06344..660c4e0 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-open-display-ref.tentative.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-open-display-ref.tentative.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset="utf-8"> -<link rel=author title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel=author href="mailto:masonf@chromium.org"> <div>This is a popup</div>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-open-display.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-open-display.tentative.html index 0f6bd93..7c5bf44b 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-open-display.tentative.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-open-display.tentative.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset="utf-8"> -<link rel=author title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel=author href="mailto:masonf@chromium.org"> <link rel=help href="https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/Popup/explainer.md"> <link rel=match href="popup-open-display-ref.tentative.html">
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-open-overflow-display-ref.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-open-overflow-display-ref.tentative.html index f324f57..dcf5998 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-open-overflow-display-ref.tentative.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-open-overflow-display-ref.tentative.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset="utf-8"> -<link rel=author title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel=author href="mailto:masonf@chromium.org"> <popup id=p1>This is popup 1<div id=anchor2></div></popup> <popup id=p2 anchor=anchor2>This is popup 2<div id=anchor3></div></popup>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-open-overflow-display.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-open-overflow-display.tentative.html index eae8288..b2780b7 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-open-overflow-display.tentative.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-open-overflow-display.tentative.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset="utf-8"> -<link rel=author title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel=author href="mailto:masonf@chromium.org"> <link rel=help href="https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/Popup/explainer.md"> <link rel=match href="popup-open-overflow-display-ref.tentative.html">
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-shadow-dom.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-shadow-dom.tentative.html index eef0309a..386d0ca 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-shadow-dom.tentative.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-shadow-dom.tentative.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset="utf-8"> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel=help href="https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/Popup/explainer.md"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-stacking.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-stacking.tentative.html index 167b350..4fccaa7 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-stacking.tentative.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-popup-element/popup-stacking.tentative.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset="utf-8"> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel=help href="https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/Popup/explainer.md"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/syntax/parsing/html_content_in_foreign_context.html b/third_party/blink/web_tests/external/wpt/html/syntax/parsing/html_content_in_foreign_context.html index a13c2fb1..7efafb4f 100644 --- a/third_party/blink/web_tests/external/wpt/html/syntax/parsing/html_content_in_foreign_context.html +++ b/third_party/blink/web_tests/external/wpt/html/syntax/parsing/html_content_in_foreign_context.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>Foreign contexts with HTML tag children</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inbody"> <link rel="help" href="https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inforeign"> <script src="/resources/testharness.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/syntax/serializing-html-fragments/escaping.html b/third_party/blink/web_tests/external/wpt/html/syntax/serializing-html-fragments/escaping.html index 1602964..7bbc556 100644 --- a/third_party/blink/web_tests/external/wpt/html/syntax/serializing-html-fragments/escaping.html +++ b/third_party/blink/web_tests/external/wpt/html/syntax/serializing-html-fragments/escaping.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>Serialization of script-disabled documents should follow escaping rules</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://html.spec.whatwg.org/multipage/parsing.html#serialising-html-fragments"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/navigator-pluginarray.html b/third_party/blink/web_tests/external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/navigator-pluginarray.html index cd5fc41..cc7664f 100644 --- a/third_party/blink/web_tests/external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/navigator-pluginarray.html +++ b/third_party/blink/web_tests/external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/navigator-pluginarray.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset=utf-8> <title>Test for empty plugins and mimeTypes arrays</title> -<link rel='author' title='Mason Freed' href='mailto:masonfreed@chromium.org'> +<link rel='author' href='mailto:masonf@chromium.org'> <link rel='help' href='https://github.com/whatwg/html/issues/6003'> <script src='/resources/testharness.js'></script> <script src='/resources/testharnessreport.js'></script>
diff --git a/third_party/blink/web_tests/external/wpt/lifecycle/set-composited-layer-position-ref.html b/third_party/blink/web_tests/external/wpt/lifecycle/set-composited-layer-position-ref.html index 217edfa..600de56 100644 --- a/third_party/blink/web_tests/external/wpt/lifecycle/set-composited-layer-position-ref.html +++ b/third_party/blink/web_tests/external/wpt/lifecycle/set-composited-layer-position-ref.html
@@ -2,7 +2,7 @@ <meta charset="utf-8"> <title>Setting composited layer position paints properly</title> -<link rel="author" title="Mason Freed" href="masonfreed@chromium.org"> +<link rel="author" href="masonf@chromium.org">
diff --git a/third_party/blink/web_tests/external/wpt/lifecycle/set-composited-layer-position.html b/third_party/blink/web_tests/external/wpt/lifecycle/set-composited-layer-position.html index 543677a..f1a3807 100644 --- a/third_party/blink/web_tests/external/wpt/lifecycle/set-composited-layer-position.html +++ b/third_party/blink/web_tests/external/wpt/lifecycle/set-composited-layer-position.html
@@ -2,7 +2,7 @@ <html class="reftest-wait"> <meta charset="utf-8"> <title>Setting composited layer position paints properly</title> -<link rel="author" title="Mason Freed" href="masonfreed@chromium.org"> +<link rel="author" href="masonf@chromium.org"> <link rel="help" href="https://drafts.csswg.org/cssom-view-1/"> <link rel="match" href="set-composited-layer-position-ref.html">
diff --git a/third_party/blink/web_tests/external/wpt/scroll-to-text-fragment/scroll-to-text-fragment-same-doc.html b/third_party/blink/web_tests/external/wpt/scroll-to-text-fragment/scroll-to-text-fragment-same-doc.html index 3bfd453..ff33952 100644 --- a/third_party/blink/web_tests/external/wpt/scroll-to-text-fragment/scroll-to-text-fragment-same-doc.html +++ b/third_party/blink/web_tests/external/wpt/scroll-to-text-fragment/scroll-to-text-fragment-same-doc.html
@@ -14,12 +14,13 @@ function checkScroll(resolve) { let position = 'unknown'; - if (window.scrollY == 0) - position = 'top'; - else if (isInView(document.getElementById('text'))) - position = 'text'; - - resolve(position); + requestAnimationFrame(() => { + if (window.scrollY == 0) + position = 'top'; + else if (isInView(document.getElementById('text'))) + position = 'text'; + resolve(position); + }); } function runTest() {
diff --git a/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/declarative-after-attachshadow.tentative.html b/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/declarative-after-attachshadow.tentative.html index a313585..3dcc099 100644 --- a/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/declarative-after-attachshadow.tentative.html +++ b/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/declarative-after-attachshadow.tentative.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>Declarative Shadow DOM after attachShadow</title> -<link rel='author' title='Mason Freed' href='mailto:masonfreed@chromium.org'> +<link rel='author' href='mailto:masonf@chromium.org'> <link rel='help' href='https://github.com/whatwg/dom/issues/831'> <script src='/resources/testharness.js'></script> <script src='/resources/testharnessreport.js'></script>
diff --git a/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/declarative-shadow-dom-attachment.tentative.html b/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/declarative-shadow-dom-attachment.tentative.html index b9033f5..081f9b2d 100644 --- a/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/declarative-shadow-dom-attachment.tentative.html +++ b/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/declarative-shadow-dom-attachment.tentative.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>Declarative Shadow DOM Element Attachment</title> -<link rel='author' title='Mason Freed' href='mailto:masonfreed@chromium.org'> +<link rel='author' href='mailto:masonf@chromium.org'> <link rel='help' href='https://github.com/whatwg/dom/issues/831'> <script src='/resources/testharness.js'></script> <script src='/resources/testharnessreport.js'></script>
diff --git a/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/declarative-shadow-dom-basic.tentative.html b/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/declarative-shadow-dom-basic.tentative.html index a03743e4..0b99376 100644 --- a/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/declarative-shadow-dom-basic.tentative.html +++ b/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/declarative-shadow-dom-basic.tentative.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>Declarative Shadow DOM</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://github.com/whatwg/dom/issues/831"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/declarative-shadow-dom-opt-in.tentative.html b/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/declarative-shadow-dom-opt-in.tentative.html index a49e759..2eec3c5 100644 --- a/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/declarative-shadow-dom-opt-in.tentative.html +++ b/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/declarative-shadow-dom-opt-in.tentative.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>Declarative Shadow DOM</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://github.com/whatwg/dom/issues/831"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/getinnerhtml.tentative.html b/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/getinnerhtml.tentative.html index bcf5471..52a4847 100644 --- a/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/getinnerhtml.tentative.html +++ b/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/getinnerhtml.tentative.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>getInnerHTML </title> -<link rel='author' title='Mason Freed' href='mailto:masonfreed@chromium.org'> +<link rel='author' href='mailto:masonf@chromium.org'> <link rel='help' href='https://github.com/whatwg/dom/issues/831'> <script src='/resources/testharness.js'></script> <script src='/resources/testharnessreport.js'></script>
diff --git a/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/innerhtml-before-closing-tag.tentative.html b/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/innerhtml-before-closing-tag.tentative.html index 653c419..9a60677 100644 --- a/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/innerhtml-before-closing-tag.tentative.html +++ b/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/innerhtml-before-closing-tag.tentative.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>Declarative Shadow DOM innerHTML</title> -<link rel='author' title='Mason Freed' href='mailto:masonfreed@chromium.org'> +<link rel='author' href='mailto:masonf@chromium.org'> <link rel='help' href='https://github.com/whatwg/dom/issues/831'> <script src='/resources/testharness.js'></script> <script src='/resources/testharnessreport.js'></script>
diff --git a/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/innerhtml-on-ordinary-template.tentative.html b/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/innerhtml-on-ordinary-template.tentative.html index 988acc0..6d01ced 100644 --- a/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/innerhtml-on-ordinary-template.tentative.html +++ b/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/innerhtml-on-ordinary-template.tentative.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>Declarative Shadow DOM innerHTML</title> -<link rel='author' title='Mason Freed' href='mailto:masonfreed@chromium.org'> +<link rel='author' href='mailto:masonf@chromium.org'> <link rel='help' href='https://github.com/whatwg/dom/issues/831'> <script src='/resources/testharness.js'></script> <script src='/resources/testharnessreport.js'></script>
diff --git a/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/move-template-before-closing-tag.tentative.html b/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/move-template-before-closing-tag.tentative.html index 88b75e7..46e6041 100644 --- a/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/move-template-before-closing-tag.tentative.html +++ b/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/move-template-before-closing-tag.tentative.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>Declarative Shadow DOM: moving the template doesn't change attachment point</title> -<link rel='author' title='Mason Freed' href='mailto:masonfreed@chromium.org'> +<link rel='author' href='mailto:masonf@chromium.org'> <link rel='help' href='https://github.com/whatwg/dom/issues/831'> <script src='/resources/testharness.js'></script> <script src='/resources/testharnessreport.js'></script>
diff --git a/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/script-access.tentative.html b/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/script-access.tentative.html index b87bb7a..66d4b948 100644 --- a/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/script-access.tentative.html +++ b/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/script-access.tentative.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>Declarative Shadow DOM</title> -<link rel='author' title='Mason Freed' href='mailto:masonfreed@chromium.org'> +<link rel='author' href='mailto:masonf@chromium.org'> <link rel='help' href='https://github.com/whatwg/dom/issues/831'> <script src='/resources/testharness.js'></script> <script src='/resources/testharnessreport.js'></script>
diff --git a/third_party/blink/web_tests/external/wpt/shadow-dom/event-on-pseudo-element-crash.html b/third_party/blink/web_tests/external/wpt/shadow-dom/event-on-pseudo-element-crash.html index 56674b6..c03f51a6 100644 --- a/third_party/blink/web_tests/external/wpt/shadow-dom/event-on-pseudo-element-crash.html +++ b/third_party/blink/web_tests/external/wpt/shadow-dom/event-on-pseudo-element-crash.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset="utf-8"> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://crbug.com/1180286"> <meta name="assert" content="The renderer should not crash.">
diff --git a/third_party/blink/web_tests/external/wpt/shadow-dom/nested-slot-remove-crash.html b/third_party/blink/web_tests/external/wpt/shadow-dom/nested-slot-remove-crash.html index d53b3b4..2930e3a2 100644 --- a/third_party/blink/web_tests/external/wpt/shadow-dom/nested-slot-remove-crash.html +++ b/third_party/blink/web_tests/external/wpt/shadow-dom/nested-slot-remove-crash.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <meta charset="utf-8"> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel="help" href="https://crbug.com/1159328"> <meta name="assert" content="The renderer should not crash.">
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/__init__.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/__init__.py
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/new_session/__init__.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/new_session/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/new_session/__init__.py
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/new_session/connect.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/new_session/connect.py new file mode 100644 index 0000000..219efdcd --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/new_session/connect.py
@@ -0,0 +1,36 @@ +import pytest +import asyncio +import websockets +import webdriver + +# classic session to enable bidi capability manually +# Intended to be the first test in this file +@pytest.mark.asyncio +@pytest.mark.capabilities({"webSocketUrl": True}) +async def test_websocket_url_connect(session): + assert not isinstance(session, webdriver.BidiSession) + websocket_url = session.capabilities["webSocketUrl"] + async with websockets.connect(websocket_url) as websocket: + await websocket.send("Hello world!") + +# test bidi_session send +# using bidi_session is the recommended way to test bidi +@pytest.mark.asyncio +async def test_bidi_session_send(bidi_session): + await bidi_session.websocket_transport.send("test_bidi_session: send") + +# bidi session following a bidi session with a different capabilities +# to test session recreation +@pytest.mark.asyncio +@pytest.mark.capabilities({"acceptInsecureCerts": True}) +async def test_bidi_session_with_different_capability(bidi_session): + await bidi_session.websocket_transport.send("test_bidi_session: different capability") + +# classic session following a bidi session to test session +# recreation +# Intended to be the last test in this file to make sure +# classic session is not impacted by bidi tests +@pytest.mark.asyncio +def test_classic_after_bidi_session(session): + assert not isinstance(session, webdriver.BidiSession) +
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/new_session/websocket_url.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/new_session/websocket_url.py new file mode 100644 index 0000000..ff6d6b32 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/new_session/websocket_url.py
@@ -0,0 +1,8 @@ +from tests.support.asserts import assert_success + +def test_websocket_url(new_session, add_browser_capabilities): + response, _ = new_session({"capabilities": { + "alwaysMatch": add_browser_capabilities({"webSocketUrl": True})}}) + value = assert_success(response) + assert value["capabilities"]["webSocketUrl"].startswith("ws://") +
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/support/fixtures.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/support/fixtures.py index 888c42b..0ecfcdb 100644 --- a/third_party/blink/web_tests/external/wpt/webdriver/tests/support/fixtures.py +++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/support/fixtures.py
@@ -2,6 +2,7 @@ import json import os +import asyncio import pytest import webdriver @@ -39,6 +40,17 @@ metafunc.parametrize("capabilities", marker.args, ids=None) +# Ensure that the event loop is restarted once per session rather than the default of once per test +# if we don't do this, tests will try to reuse a closed event loop and fail with an error that the "future +# belongs to a different loop" +@pytest.fixture(scope="session") +def event_loop(): + """Change event_loop fixture to session level.""" + loop = asyncio.get_event_loop_policy().new_event_loop() + yield loop + loop.close() + + @pytest.fixture def add_event_listeners(session): """Register listeners for tracked events on element.""" @@ -111,8 +123,23 @@ } +async def reset_current_session_if_necessary(caps, request_bidi): + global _current_session + + # If there is a session with different capabilities active or the current session + # is of different type than the one we would like to create, end it now. + if _current_session is not None: + is_bidi = isinstance(_current_session, webdriver.BidiSession) + if is_bidi != request_bidi or not _current_session.match(caps): + if is_bidi: + await _current_session.end() + else: + _current_session.end() + _current_session = None + + @pytest.fixture(scope="function") -def session(capabilities, configuration, request): +async def session(capabilities, configuration, request): """Create and start a session for a test that does not itself test session creation. By default the session will stay open after each test, but we always try to start a @@ -127,11 +154,7 @@ deep_update(caps, capabilities) caps = {"alwaysMatch": caps} - # If there is a session with different capabilities active, end it now - if _current_session is not None and ( - caps != _current_session.requested_capabilities): - _current_session.end() - _current_session = None + await reset_current_session_if_necessary(caps, False) if _current_session is None: _current_session = webdriver.Session( @@ -140,6 +163,46 @@ capabilities=caps) try: _current_session.start() + + except webdriver.error.SessionNotCreatedException: + if not _current_session.session_id: + raise + + # Enforce a fixed default window size and position + _current_session.window.size = defaults.WINDOW_SIZE + _current_session.window.position = defaults.WINDOW_POSITION + + yield _current_session + + cleanup_session(_current_session) + + +@pytest.fixture(scope="function") +async def bidi_session(capabilities, configuration, request): + """Create and start a bidi session for a test that does not itself test + bidi session creation. + By default the session will stay open after each test, but we always try to start a + new one and assume that if that fails there is already a valid session. This makes it + possible to recover from some errors that might leave the session in a bad state, but + does not demand that we start a new session per test.""" + global _current_session + + # Update configuration capabilities with custom ones from the + # capabilities fixture, which can be set by tests + caps = copy.deepcopy(configuration["capabilities"]) + deep_update(caps, capabilities) + caps = {"alwaysMatch": caps} + + await reset_current_session_if_necessary(caps, True) + + if _current_session is None: + _current_session = webdriver.BidiSession( + configuration["host"], + configuration["port"], + capabilities=caps) + try: + await _current_session.start() + except webdriver.error.SessionNotCreatedException: if not _current_session.session_id: raise
diff --git a/third_party/blink/web_tests/html/popup/popup-light-dismiss-keyboard.html b/third_party/blink/web_tests/html/popup/popup-light-dismiss-keyboard.html index f271af2..4d6cd102 100644 --- a/third_party/blink/web_tests/html/popup/popup-light-dismiss-keyboard.html +++ b/third_party/blink/web_tests/html/popup/popup-light-dismiss-keyboard.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <meta charset="utf-8" /> <title>Popup light dismiss behavior</title> -<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="author" href="mailto:masonf@chromium.org"> <link rel=help href="https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/Popup/explainer.md"> <script src='../../resources/testharness.js'></script> <script src='../../resources/testharnessreport.js'></script>
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/page/consecutive-navigate-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/page/consecutive-navigate-expected.txt new file mode 100644 index 0000000..11eed6ad --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/page/consecutive-navigate-expected.txt
@@ -0,0 +1,35 @@ +Tests that calling Page.navigate while a navigation is running cancels the previous navigation +{ + id : <number> + result : { + errorText : net::ERR_ABORTED + frameId : <string> + } + sessionId : <string> +} +{ + id : <number> + result : { + frameId : <string> + loaderId : <string> + } + sessionId : <string> +} +{ + id : <number> + result : { + errorText : net::ERR_ABORTED + frameId : <string> + loaderId : <string> + } + sessionId : <string> +} +{ + id : <number> + result : { + frameId : <string> + loaderId : <string> + } + sessionId : <string> +} +
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/page/consecutive-navigate.js b/third_party/blink/web_tests/http/tests/inspector-protocol/page/consecutive-navigate.js new file mode 100644 index 0000000..1b7e64b8 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/page/consecutive-navigate.js
@@ -0,0 +1,30 @@ +(async function(testRunner) { + var {page, session, dp} = await testRunner.startBlank( + `Tests that calling Page.navigate while a navigation is running cancels the previous navigation`); + + // Call Page.navigate() consecutively (start second navigation before first + // one has started). + await dp.Page.enable(); + const navigatePromise1 = dp.Page.navigate({ url: testRunner.url('../resources/test-page.html') }); + const navigatePromise2 = dp.Page.navigate({ url: testRunner.url('../resources/image.html') }); + const loadPromise = dp.Page.onceLoadEventFired(); + + testRunner.log(await navigatePromise1); + testRunner.log(await navigatePromise2); + + // Wait for navigation to finish in renderer. + await loadPromise; + + // Call Page.navigate() consecutively (start second navigation after first + // one has started and has sent a network request). + await dp.Fetch.enable(); + const navigatePromise3 = dp.Page.navigate({ url: testRunner.url('../resources/test-page.html')}); + await dp.Fetch.onceRequestPaused(); + const navigatePromise4 = dp.Page.navigate({ url: testRunner.url('../resources/final.html')}); + await dp.Fetch.disable(); + + testRunner.log(await navigatePromise3); + testRunner.log(await navigatePromise4); + + testRunner.completeTest(); +})
diff --git a/third_party/blink/web_tests/http/tests/security/frameNavigation/resources/iframe-that-performs-different-scheme-same-etld-plus-one-top-navigation-without-user-gesture.html b/third_party/blink/web_tests/http/tests/security/frameNavigation/resources/iframe-that-performs-different-scheme-same-etld-plus-one-top-navigation-without-user-gesture.html new file mode 100644 index 0000000..b7a676f7 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/security/frameNavigation/resources/iframe-that-performs-different-scheme-same-etld-plus-one-top-navigation-without-user-gesture.html
@@ -0,0 +1,16 @@ +<html> +<body> +The navigation should fail. This text should be visible. +<script> +window.onload = function() +{ + try { + top.location = "https://127.0.0.1:8443/security/frameNavigation/resources/navigation-changed-iframe.html"; + top.postMessage("FAIL", "*"); + } catch(e) { + top.postMessage("PASS", "*"); + } +} +</script> +</body> +</html>
diff --git a/third_party/blink/web_tests/http/tests/security/frameNavigation/xss-DENIED-different-scheme-same-etld-plus-1-top-navigation-without-user-gesture-expected.txt b/third_party/blink/web_tests/http/tests/security/frameNavigation/xss-DENIED-different-scheme-same-etld-plus-1-top-navigation-without-user-gesture-expected.txt new file mode 100644 index 0000000..ee18088 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/security/frameNavigation/xss-DENIED-different-scheme-same-etld-plus-1-top-navigation-without-user-gesture-expected.txt
@@ -0,0 +1,6 @@ + + +-------- +Frame: '<!--framePath //<!--frame0-->-->' +-------- +The navigation should fail. This text should be visible.
diff --git a/third_party/blink/web_tests/http/tests/security/frameNavigation/xss-DENIED-different-scheme-same-etld-plus-1-top-navigation-without-user-gesture.html b/third_party/blink/web_tests/http/tests/security/frameNavigation/xss-DENIED-different-scheme-same-etld-plus-1-top-navigation-without-user-gesture.html new file mode 100644 index 0000000..70c20b55 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/security/frameNavigation/xss-DENIED-different-scheme-same-etld-plus-1-top-navigation-without-user-gesture.html
@@ -0,0 +1,22 @@ +<html> +<head> + <script> + if (window.testRunner) { + testRunner.dumpAsText(); + testRunner.dumpChildFrames(); + testRunner.setDumpConsoleMessages(false); + testRunner.waitUntilDone(); + } + + window.addEventListener("message", e => { + if (e.data == "PASS") + testRunner.notifyDone(); + else + testRunner.testFailed("'top.location' didn't throw."); + }); + </script> +</head> +<body> + <iframe src="http://sub1.example.test:8000/security/frameNavigation/resources/iframe-that-performs-different-scheme-same-etld-plus-one-top-navigation-without-user-gesture.html"></iframe> +</body> +</html>
diff --git a/third_party/blink/web_tests/platform/fuchsia/fast/block/float/centered-float-avoidance-complexity-expected.png b/third_party/blink/web_tests/platform/fuchsia/fast/block/float/centered-float-avoidance-complexity-expected.png index 1606638..a839d95 100644 --- a/third_party/blink/web_tests/platform/fuchsia/fast/block/float/centered-float-avoidance-complexity-expected.png +++ b/third_party/blink/web_tests/platform/fuchsia/fast/block/float/centered-float-avoidance-complexity-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/fuchsia/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png b/third_party/blink/web_tests/platform/fuchsia/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png index 99a0709f..3ec0aa9 100644 --- a/third_party/blink/web_tests/platform/fuchsia/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png +++ b/third_party/blink/web_tests/platform/fuchsia/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/fuchsia/fast/events/reveal-link-when-focused-expected.png b/third_party/blink/web_tests/platform/fuchsia/fast/events/reveal-link-when-focused-expected.png index 9feafde..a0a023b2 100644 --- a/third_party/blink/web_tests/platform/fuchsia/fast/events/reveal-link-when-focused-expected.png +++ b/third_party/blink/web_tests/platform/fuchsia/fast/events/reveal-link-when-focused-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/fuchsia/fast/overflow/position-fixed-transform-clipping-expected.png b/third_party/blink/web_tests/platform/fuchsia/fast/overflow/position-fixed-transform-clipping-expected.png index 8cd5fdc0..e447378d 100644 --- a/third_party/blink/web_tests/platform/fuchsia/fast/overflow/position-fixed-transform-clipping-expected.png +++ b/third_party/blink/web_tests/platform/fuchsia/fast/overflow/position-fixed-transform-clipping-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/fuchsia/fast/table/border-collapsing/004-expected.png b/third_party/blink/web_tests/platform/fuchsia/fast/table/border-collapsing/004-expected.png index b64aed3d..3e7f3ea 100644 --- a/third_party/blink/web_tests/platform/fuchsia/fast/table/border-collapsing/004-expected.png +++ b/third_party/blink/web_tests/platform/fuchsia/fast/table/border-collapsing/004-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/fuchsia/tables/mozilla/bugs/bug2479-3-expected.png b/third_party/blink/web_tests/platform/fuchsia/tables/mozilla/bugs/bug2479-3-expected.png index 556a9eae..c67cf26 100644 --- a/third_party/blink/web_tests/platform/fuchsia/tables/mozilla/bugs/bug2479-3-expected.png +++ b/third_party/blink/web_tests/platform/fuchsia/tables/mozilla/bugs/bug2479-3-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/fuchsia/tables/mozilla/bugs/bug2479-4-expected.png b/third_party/blink/web_tests/platform/fuchsia/tables/mozilla/bugs/bug2479-4-expected.png index 04679ab..805a09e 100644 --- a/third_party/blink/web_tests/platform/fuchsia/tables/mozilla/bugs/bug2479-4-expected.png +++ b/third_party/blink/web_tests/platform/fuchsia/tables/mozilla/bugs/bug2479-4-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/fuchsia/tables/mozilla/core/bloomberg-expected.png b/third_party/blink/web_tests/platform/fuchsia/tables/mozilla/core/bloomberg-expected.png index 1ddf755..d1cb9a8 100644 --- a/third_party/blink/web_tests/platform/fuchsia/tables/mozilla/core/bloomberg-expected.png +++ b/third_party/blink/web_tests/platform/fuchsia/tables/mozilla/core/bloomberg-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/fuchsia/tables/mozilla_expected_failures/bugs/bug1055-2-expected.png b/third_party/blink/web_tests/platform/fuchsia/tables/mozilla_expected_failures/bugs/bug1055-2-expected.png index a24832d..0bb51b5 100644 --- a/third_party/blink/web_tests/platform/fuchsia/tables/mozilla_expected_failures/bugs/bug1055-2-expected.png +++ b/third_party/blink/web_tests/platform/fuchsia/tables/mozilla_expected_failures/bugs/bug1055-2-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/fuchsia/tables/mozilla_expected_failures/bugs/bug2479-5-expected.png b/third_party/blink/web_tests/platform/fuchsia/tables/mozilla_expected_failures/bugs/bug2479-5-expected.png index 0db6218..a48f218 100644 --- a/third_party/blink/web_tests/platform/fuchsia/tables/mozilla_expected_failures/bugs/bug2479-5-expected.png +++ b/third_party/blink/web_tests/platform/fuchsia/tables/mozilla_expected_failures/bugs/bug2479-5-expected.png Binary files differ
diff --git a/third_party/wpt_tools/PRESUBMIT.py b/third_party/wpt_tools/PRESUBMIT.py index 42e84c4..1b4418d 100644 --- a/third_party/wpt_tools/PRESUBMIT.py +++ b/third_party/wpt_tools/PRESUBMIT.py
@@ -20,7 +20,8 @@ name='web_tests/external/PRESUBMIT_test.py', cmd=[abspath_to_test], kwargs={}, - message=output_api.PresubmitError + message=output_api.PresubmitError, + python3=True ) if input_api.verbose: print('Running ' + abspath_to_test) @@ -45,7 +46,7 @@ blink_path, 'web_tests', 'external', 'wpt') try: input_api.subprocess.check_output( - ['python', wpt_exec_path, 'manifest', '--no-download', + ['python3', wpt_exec_path, 'manifest', '--no-download', '--path', f.name, '--tests-root', external_wpt]) except input_api.subprocess.CalledProcessError as exc: return [output_api.PresubmitError('wpt manifest failed:', long_text=exc.output)]
diff --git a/third_party/wpt_tools/README.chromium b/third_party/wpt_tools/README.chromium index 0d19fa9..0a9df00 100644 --- a/third_party/wpt_tools/README.chromium +++ b/third_party/wpt_tools/README.chromium
@@ -1,7 +1,7 @@ Name: web-platform-tests - Test Suites for Web Platform specifications Short Name: wpt URL: https://github.com/web-platform-tests/wpt/ -Version: 3eb2cdae07a8842112e804a59dbd0f9800c64e73 +Version: f6a1fd063fd77ea5865c82682458ae4fb7d04bb3 License: LICENSES FOR W3C TEST SUITES (https://www.w3.org/Consortium/Legal/2008/03-bsd-license.html) License File: NOT_SHIPPED Security Critical: no @@ -12,7 +12,3 @@ for more details on maintenance. Local Modifications: - Removed all files except for those listed in wpt/WPTIncludeList. -- Cherry-picked df9dc69c2340d79fbd56ee2adfa85ac8d4af0b93 temporarily to fix a - lint error blocking the importer. -- Cherry-picked 9b5f845370d7c6fe83b51ceef3f91e42aa85bbc2 temporatily to resolve - https://crbug.com/1182579
diff --git a/third_party/wpt_tools/WPTIncludeList b/third_party/wpt_tools/WPTIncludeList index 0d381c4..9b84204 100644 --- a/third_party/wpt_tools/WPTIncludeList +++ b/third_party/wpt_tools/WPTIncludeList
@@ -175,6 +175,7 @@ ./tools/third_party/webencodings/webencodings/tests.py ./tools/third_party/webencodings/webencodings/x_user_defined.py ./tools/webdriver/webdriver/__init__.py +./tools/webdriver/webdriver/bidi.py ./tools/webdriver/webdriver/client.py ./tools/webdriver/webdriver/error.py ./tools/webdriver/webdriver/protocol.py
diff --git a/third_party/wpt_tools/checkout.sh b/third_party/wpt_tools/checkout.sh index 24480dfe..ce43eb7 100755 --- a/third_party/wpt_tools/checkout.sh +++ b/third_party/wpt_tools/checkout.sh
@@ -9,7 +9,7 @@ TARGET_DIR=$DIR/wpt REMOTE_REPO="https://github.com/web-platform-tests/wpt.git" -WPT_HEAD=3eb2cdae07a8842112e804a59dbd0f9800c64e73 +WPT_HEAD=f6a1fd063fd77ea5865c82682458ae4fb7d04bb3 function clone { # Remove existing repo if already exists.
diff --git a/third_party/wpt_tools/wpt/docs/commands.json b/third_party/wpt_tools/wpt/docs/commands.json index f3494b8..55408d8 100644 --- a/third_party/wpt_tools/wpt/docs/commands.json +++ b/third_party/wpt_tools/wpt/docs/commands.json
@@ -3,7 +3,6 @@ "path": "frontend.py", "script": "build", "help": "Build documentation", - "py3only": true, "virtualenv": true, "requirements": [ "./requirements.txt"
diff --git a/third_party/wpt_tools/wpt/tools/certs/cacert.key b/third_party/wpt_tools/wpt/tools/certs/cacert.key index 6b240e5..7b9bd97 100644 --- a/third_party/wpt_tools/wpt/tools/certs/cacert.key +++ b/third_party/wpt_tools/wpt/tools/certs/cacert.key
@@ -1,30 +1,30 @@ -----BEGIN ENCRYPTED PRIVATE KEY----- -MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQI666o+tmBgXYCAggA -MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECILZgh0KpE9MBIIEyCgMCCFkSlDm -wPDpQ0rFCyQyAcdP5HMnLM/W+2z5TYDqdhtLd+XqD2lGqr4lCd33CoDubRxZoU/t -VQ0TuDQcfhCz8HG6nXMpai2NDrc5Ot29fVFdMFkk8na17RhMKUc6Gan/TDi+E4i8 -e2YakJ5JgaBUFBf/jyqJfLsYJezNFhn5+nCsz+KbZBoht2B+W/rq/FAUzwPGJ+Yc -8J2gVcuRUctXwS47yI8aklXhIhwmL89Ioad3rpypeDX3tu5TeG2nv/d1uV3/FngC -/18b4eJz6dpqdTVN5Uoa3NjHjY8a8mcBvWKBL6mWy2dTVl9W8wdgtVkvc0PsF3Pu -oJy5oeWhP6dSqAvDHTDXa38rt3H9IRmTsIXd0VVOIhFjg8tDQTBR/CyJKp4JO8Oy -y/RGZsdqcO03ujolWOlDY4Pi8e7JpHK+1kyhGOTimi/9JuWtiSp40gKDzylL1oaw -hr1UaPHl/kA/gJgpDBKT+PXQt2Gm9qje9+B/U6zj31bVd0r1S0qMlXz81t/K+BcH -u/5NaZsDXyE8rufyxAHPBKPxXMZONG7y6EbF868EHUrCAKlElfHtTnvP/k68V3eH -GnVzsId8eirzutrRdugPXS7Pg1Uj1CL6Ga8ia9MfEIbSx/g2FQ9SMnurXVeWv1qM -uMNZbRZUkkJD8T/VqB7ezrI553iTqZFGr6fQ0dyXBS0m1phPSkmPcqE42sYCIZcy -KZGYeWS1LkFRoTxoAwRS8cf14NjmoG+Aby4iyB3QiMDOmsylZDF0vsYeUbUIkxyz -GnSn2LaVpT3ZeuziLnNn3JaeIy946jEgZETvCDruurV5AoAb9pXG2Xuysevx/AuV -Owzz82PqG308kq6xhcGNK+v9FRbagHaGZ5EG+iVUTjN348NjJIriDVdrH06fBqe+ -UFD9fAnN/Kj4dIJKUCun4UZiz2jHeNnAmkLwOZn/eTK1LbUrmT0J+3eupaF7zzxo -CednARzHvAiEVAX8Wd5DauIjczesjdrO9ys7dTMeZeyV5t/s8W66TB6tVDIQwTIp -3skdhbw22zI2lcrDhZbbYhwO9R6d4liENUZ/W5ISLDXn+w8kqqh1qXoE8vR0lxpy -Oz27kg5DBqyUflx99HwLj8epMNpGzepMAeFXTd+gLFKk7gWtU/5mJItTEfBu8Iih -FT3/eesClxxzBm2Mk1viv/iKspTH92+mKEz2ng6jONWxHXkfuxNWe4wX+KmO7s7P -plzxnbr2TlNTewbuYqyKMwe9KOiXosdfxUkJq6D8R0bf+A69M/dggO7BVdxNfF71 -+xdfqjWjll/58lQ15KdlycfVlYj6iDvK1ChrK4UH2myGbmhThIItezPm8Oo4i3I6 -iPk8ns/BqfFH2raE7cw7G3Ug6cEJrc8OG4c1mfBuHPAeDrCWNu7tEqwKrGGJVA3b -1GiBo72z5XVOiP7lku708ZEfrzh2UGuSvx0gbpW3aMDNnVq2O6euIquZugeewckq -2Ox9C1vADIA8ugRdHbSVRQE33YiU1QS3MvQ9TYW/Zv7Buuhrdk2S1WLRpkWw+qR6 -62EFFAw6wjpK/vciGucrV8GyybdxPFqZPMtQkghaOPUO84Qsx2rZXAR+4/gZuHGm -v2L3tYSDEmQ+6kEynWtX/w== +MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQIy+AmMEgUCbACAggA +MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECJTlAsVqhvE6BIIEyG++PNkc48P8 +oprMaYzGL0QsYQb7xLR/JYhWB2GVUZGTTYORqiUIgKUQkayG1cxO2Jyhqb+qZfdI +gAt9x7uS6A2omVXCm0ZW1vl4NGOyNdHvTmCnf9EkCzqWYYUW0nxxdV6DsVtsOb1/ +gDJxo3n8CYue/5zGuOprQJRUZAHrvx2huKMzg3wxSzYOaRfYVy5N9dKbgroyd/Vy +05H+k9HY9+YwhRhXSTyqMRNj3ftbizdoPFyWihVABUvan6ExScuXNbfVu/qwxG86 +WRAFr6qu1EBhe5OLttHDYnhr14HjSTkTp289wKAn9fOMzvUh0NEMTx5PgF3u0AK6 +edhtDrJwjgrRc6ENJw3mM6VGa/FxR0eRyp38+/MteYyfz5eVnyPnJw22uiBd8i2j +6dzDS+zZMA3vmp2NdB3rbgleQ5sdNEqJz4GC/yqTtwGDwH+OrbMpl2BAn1ckz9R9 +2b+DYsstBtLDx+R6JOy/sOFGcZla5T5TYOVJWD5i4vnW216rK6Pi+mbXa9WzGfGH +UmghkDDh7iLYIBT3+YgEHqAeb+RKfeq7X3r6PBOAhavLp/4w2ZffywnyfxOxKQwE +nb0bU8OPkPe3by3sbfS9H17729dTMMAJ3NGVjst2rEGYbDU/OZuBZzW3fwFnwKV2 +N3BTe3nPpZ/SXip7I6Hf+b6TNGeyVZUvBzw7spGGlXbbK76EdWY3dcs2OMH6JxUW +Ib/bkNqclqSeXYFigzDozAuBJ2cM0TXxhnvLLuLLgL4+kH/d0tdCLJLNSqDy4Q+N +GOFWZGtaowGuhpblGsAC/Z2wdPJ+fVQxGbHfGOttyoxCdfNfSclk7KuJFVQCGn1H +aBvZfr1bf+o+mxuDmaDKFyb3fGQ55AgAdno5NxEInSofuopAefNxwfGzhTYmnAdF +JY6WvXisz57EW9SjEvGHJMRREYw9a8tPKCOXa9CgPFsVdhPA+cFaBI3qDoY9E6rv +cYdhXKatnORDHTQXPJz241cJK1yz6VDqAzExQlXli+dSqLl04X/3hAjIAMtDeeCc +7F3U9XLkMIAiU3GKHIA0mq8wkTucOd7EVV+TS+i4e9MBIRueNyEd4u6m04G7Y4kf +pkGowONXy1CETy4RoRNJi+nGC7TwCLzbEg6Sb9xs9q2lLh/cAiqdArPk9vLNe9Gh +YSlcwN4WSPtQTN4hjiBhWe7O9Ux6f2llptyQhCzpb58h7IOQgTUcHOENoxUnVQwS +RYsj+29aAYcLI+5NJzMwYXNR3Fdb3sDUn16f/NsfZUpxFzmu7zSrt7SJJfFasMN3 +EjwuSoEtVdwT7+IOO8A9gRuh5JRjuFYx252Mc0HY/R3qlTwrBNXyUUyFUO8t6TYN +gxpJEKFEcsgUe+O345PrwzX+lbs9Vqvz52XO+aKsVDmbjTzWV3MnSPZcBnw1GTtq +uKGJYDOCDhV7R8IElf87xQz6z6qNYDfAjlcxfeJK5V6U07Qwi4pxvoychK/4hQ7q +X8mHWDMdyTGqED191NcI0EMHu6cjm5JSs7gXQibYrRaUGXcgk50o+LE6hIyd4VC1 +vmkKK48mcfi4GFFtmfiWX4vDK8Qzs2/PZNZURc3zgXxu4CtopFnL5SX+ZOAMSWUo +DV8CBNpQbBi6sYo4aHNB3g== -----END ENCRYPTED PRIVATE KEY-----
diff --git a/third_party/wpt_tools/wpt/tools/certs/cacert.pem b/third_party/wpt_tools/wpt/tools/certs/cacert.pem index fcc977b..f7de3a3 100644 --- a/third_party/wpt_tools/wpt/tools/certs/cacert.pem +++ b/third_party/wpt_tools/wpt/tools/certs/cacert.pem
@@ -1,176 +1,176 @@ -----BEGIN CERTIFICATE----- -MIJAhzCCP2+gAwIBAgIDBlVFMA0GCSqGSIb3DQEBCwUAMB0xGzAZBgNVBAMMEndl -Yi1wbGF0Zm9ybS10ZXN0czAeFw0yMTAxMTIxNjEzMjhaFw0yMjAxMTIxNjEzMjha +MIJAhzCCP2+gAwIBAgIDDuxtMA0GCSqGSIb3DQEBCwUAMB0xGzAZBgNVBAMMEndl +Yi1wbGF0Zm9ybS10ZXN0czAeFw0yMTAzMTIwMDI3MzNaFw0yMjAzMTIwMDI3MzNa MB0xGzAZBgNVBAMMEndlYi1wbGF0Zm9ybS10ZXN0czCCASIwDQYJKoZIhvcNAQEB -BQADggEPADCCAQoCggEBAKlAc+52QkFGs3xjT0OiT3t7HajqFqelNp5toVZfL/SF -cXqvhldvWzlKs3XW4+OKnGQP1nB7qmZZ8GjSY02Nho36Vq+YdzmHIHYPZcAlfmNO -6iY/nca7C9MEIVJvxQsG/C5ZUTkKJ93iDehGay5YF8wiIb+k6cmaV5cDs+oBwmwu -X3hxsDjOklUYCVY4Wvd4fU/zR/LdI3QZTAlNa4eLu7v/8z0vo8vG7T8VS09mc6eh -BjB0x1L7XE6n+4v3gGE8RbxeaIpZbv8vVWK1LLLQ01gCOiNFjuuD3VcBqnZTbV9/ -v4MqHrPFfZm1MxesB/kybMTve4Y6PjT1U3zgJsrV0UcCAwEAAaOCPc4wgj3KMAwG -A1UdEwQFMAMBAf8wHQYDVR0OBBYEFNxtjWLdVJjIYBfC01Gzv3NbXJC5MEcGA1Ud -IwRAMD6AFNxtjWLdVJjIYBfC01Gzv3NbXJC5oSGkHzAdMRswGQYDVQQDDBJ3ZWIt -cGxhdGZvcm0tdGVzdHOCAwZVRTALBgNVHQ8EBAMCAgQwgh+bBgNVHR4Egh+SMIIf -jqCCH4owE4IRd2ViLXBsYXRmb3JtLnRlc3QwF4IVb3A4LndlYi1wbGF0Zm9ybS50 -ZXN0MBeCFW9wNy53ZWItcGxhdGZvcm0udGVzdDAXghVvcDkud2ViLXBsYXRmb3Jt -LnRlc3QwF4IVb3A0LndlYi1wbGF0Zm9ybS50ZXN0MBeCFW5vdC13ZWItcGxhdGZv -cm0udGVzdDAXghVvcDYud2ViLXBsYXRmb3JtLnRlc3QwF4IVb3AzLndlYi1wbGF0 -Zm9ybS50ZXN0MBeCFW9wMi53ZWItcGxhdGZvcm0udGVzdDAXghVvcDEud2ViLXBs -YXRmb3JtLnRlc3QwF4IVd3d3LndlYi1wbGF0Zm9ybS50ZXN0MBeCFW9wNS53ZWIt -cGxhdGZvcm0udGVzdDAYghZvcDg4LndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wOTgu -d2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A4NS53ZWItcGxhdGZvcm0udGVzdDAYghZv -cDg5LndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wNjYud2ViLXBsYXRmb3JtLnRlc3Qw -GIIWb3A3Mi53ZWItcGxhdGZvcm0udGVzdDAYghZvcDI0LndlYi1wbGF0Zm9ybS50 -ZXN0MBiCFm9wNDEud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A3OS53ZWItcGxhdGZv -cm0udGVzdDAYghZvcDkxLndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wNTkud2ViLXBs -YXRmb3JtLnRlc3QwGIIWb3AzOS53ZWItcGxhdGZvcm0udGVzdDAYghZvcDYwLndl -Yi1wbGF0Zm9ybS50ZXN0MBiCFm9wNTgud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3Ay -OC53ZWItcGxhdGZvcm0udGVzdDAYghZ3d3cxLndlYi1wbGF0Zm9ybS50ZXN0MBiC -Fm9wMTQud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A2OS53ZWItcGxhdGZvcm0udGVz -dDAYghZvcDQwLndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wNzQud2ViLXBsYXRmb3Jt -LnRlc3QwGIIWb3AzMS53ZWItcGxhdGZvcm0udGVzdDAYghZvcDE4LndlYi1wbGF0 -Zm9ybS50ZXN0MBiCFm9wNzMud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A3Ny53ZWIt -cGxhdGZvcm0udGVzdDAYghZvcDEyLndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wNTQu -d2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A2My53ZWItcGxhdGZvcm0udGVzdDAYghZv -cDcxLndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wOTUud2ViLXBsYXRmb3JtLnRlc3Qw -GIIWb3AxNi53ZWItcGxhdGZvcm0udGVzdDAYghZvcDM2LndlYi1wbGF0Zm9ybS50 -ZXN0MBiCFm9wMjcud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3AyOS53ZWItcGxhdGZv -cm0udGVzdDAYghZvcDk0LndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wNDQud2ViLXBs -YXRmb3JtLnRlc3QwGIIWb3AzMy53ZWItcGxhdGZvcm0udGVzdDAYghZvcDg0Lndl -Yi1wbGF0Zm9ybS50ZXN0MBiCFm9wMzIud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A2 -MS53ZWItcGxhdGZvcm0udGVzdDAYghZvcDcwLndlYi1wbGF0Zm9ybS50ZXN0MBiC -Fnd3dzIud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A0My53ZWItcGxhdGZvcm0udGVz -dDAYghZvcDc4LndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wMjYud2ViLXBsYXRmb3Jt -LnRlc3QwGIIWb3A3Ni53ZWItcGxhdGZvcm0udGVzdDAYghZvcDUyLndlYi1wbGF0 -Zm9ybS50ZXN0MBiCFm9wOTkud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A4Ni53ZWIt -cGxhdGZvcm0udGVzdDAYghZvcDQ2LndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wMTcu -d2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A5MC53ZWItcGxhdGZvcm0udGVzdDAYghZv -cDkzLndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wMTAud2ViLXBsYXRmb3JtLnRlc3Qw -GIIWb3A1NS53ZWItcGxhdGZvcm0udGVzdDAYghZvcDQ3LndlYi1wbGF0Zm9ybS50 -ZXN0MBiCFm9wNTEud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A0NS53ZWItcGxhdGZv -cm0udGVzdDAYghZvcDgwLndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wNjgud2ViLXBs -YXRmb3JtLnRlc3QwGIIWb3A0OS53ZWItcGxhdGZvcm0udGVzdDAYghZvcDU3Lndl -Yi1wbGF0Zm9ybS50ZXN0MBiCFm9wMzUud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A2 -Ny53ZWItcGxhdGZvcm0udGVzdDAYghZvcDkyLndlYi1wbGF0Zm9ybS50ZXN0MBiC -Fm9wMTUud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3AxMy53ZWItcGxhdGZvcm0udGVz -dDAYghZvcDc1LndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wNjQud2ViLXBsYXRmb3Jt -LnRlc3QwGIIWb3A5Ny53ZWItcGxhdGZvcm0udGVzdDAYghZvcDM3LndlYi1wbGF0 -Zm9ybS50ZXN0MBiCFm9wNTYud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A2Mi53ZWIt -cGxhdGZvcm0udGVzdDAYghZvcDgyLndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wMjUu -d2ViLXBsYXRmb3JtLnRlc3QwGIIWb3AxMS53ZWItcGxhdGZvcm0udGVzdDAYghZv -cDUwLndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wMzgud2ViLXBsYXRmb3JtLnRlc3Qw -GIIWb3A4My53ZWItcGxhdGZvcm0udGVzdDAYghZvcDgxLndlYi1wbGF0Zm9ybS50 -ZXN0MBiCFm9wMjAud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3AyMS53ZWItcGxhdGZv -cm0udGVzdDAYghZvcDIzLndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wNDIud2ViLXBs -YXRmb3JtLnRlc3QwGIIWb3AyMi53ZWItcGxhdGZvcm0udGVzdDAYghZvcDY1Lndl -Yi1wbGF0Zm9ybS50ZXN0MBiCFm9wOTYud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A4 -Ny53ZWItcGxhdGZvcm0udGVzdDAYghZvcDE5LndlYi1wbGF0Zm9ybS50ZXN0MBiC -Fm9wNTMud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3AzMC53ZWItcGxhdGZvcm0udGVz -dDAYghZvcDQ4LndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wMzQud2ViLXBsYXRmb3Jt -LnRlc3QwG4IZb3A2Lm5vdC13ZWItcGxhdGZvcm0udGVzdDAbghlvcDMubm90LXdl -Yi1wbGF0Zm9ybS50ZXN0MBuCGW9wMi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwG4IZ -b3A1Lm5vdC13ZWItcGxhdGZvcm0udGVzdDAbghl3d3cubm90LXdlYi1wbGF0Zm9y -bS50ZXN0MBuCGXd3dy53d3cud2ViLXBsYXRmb3JtLnRlc3QwG4IZb3A3Lm5vdC13 -ZWItcGxhdGZvcm0udGVzdDAbghlvcDQubm90LXdlYi1wbGF0Zm9ybS50ZXN0MBuC -GW9wOC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwG4IZb3A5Lm5vdC13ZWItcGxhdGZv -cm0udGVzdDAbghlvcDEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMzYubm90 +BQADggEPADCCAQoCggEBAL28unmE4CuE50yyQ87wsXB1py9fN6vq9Re7kZrZVUbl +p90KMqfb9mN9LTrJBZWygzz1lXEXTkYcsbmDhbxT5xpptpuK41EKl5GudhRd5k0V +9urrVVANlWnFiaeSazFvqw0UPktrL2+C2VLXKy+b6cN7fUImS12+NGUkujmU11hY +Yg3eP/habOoeKZG9gAnlIWLmFZ2GQ5qLru2IAH0OOL7C0w7JihKfYHI+Lq2a96KG +FdPlOzDnUFidEqN3ssQIIX8C4jNhbQr2r7Magg8Lj4WeyrPlZGw2E/rGzmD1E1C3 +3KjOfBv0/AOprZGo1JsvsuYoq07Et/yx1WJwwm4fnO8CAwEAAaOCPc4wgj3KMAwG +A1UdEwQFMAMBAf8wHQYDVR0OBBYEFL14OMI385wGqOs+r1qhiCQUhVu+MEcGA1Ud +IwRAMD6AFL14OMI385wGqOs+r1qhiCQUhVu+oSGkHzAdMRswGQYDVQQDDBJ3ZWIt +cGxhdGZvcm0tdGVzdHOCAw7sbTALBgNVHQ8EBAMCAgQwgh+bBgNVHR4Egh+SMIIf +jqCCH4owE4IRd2ViLXBsYXRmb3JtLnRlc3QwF4IVbm90LXdlYi1wbGF0Zm9ybS50 +ZXN0MBeCFW9wNi53ZWItcGxhdGZvcm0udGVzdDAXghV3d3cud2ViLXBsYXRmb3Jt +LnRlc3QwF4IVb3AxLndlYi1wbGF0Zm9ybS50ZXN0MBeCFW9wNy53ZWItcGxhdGZv +cm0udGVzdDAXghVvcDgud2ViLXBsYXRmb3JtLnRlc3QwF4IVb3AyLndlYi1wbGF0 +Zm9ybS50ZXN0MBeCFW9wOS53ZWItcGxhdGZvcm0udGVzdDAXghVvcDUud2ViLXBs +YXRmb3JtLnRlc3QwF4IVb3A0LndlYi1wbGF0Zm9ybS50ZXN0MBeCFW9wMy53ZWIt +cGxhdGZvcm0udGVzdDAYghZvcDQwLndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wNjEu +d2ViLXBsYXRmb3JtLnRlc3QwGIIWb3AzMy53ZWItcGxhdGZvcm0udGVzdDAYghZv +cDc5LndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wMzgud2ViLXBsYXRmb3JtLnRlc3Qw +GIIWb3A3Ny53ZWItcGxhdGZvcm0udGVzdDAYghZvcDQzLndlYi1wbGF0Zm9ybS50 +ZXN0MBiCFm9wNDQud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3AxNC53ZWItcGxhdGZv +cm0udGVzdDAYghZvcDQ5LndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wMzYud2ViLXBs +YXRmb3JtLnRlc3QwGIIWb3AyMS53ZWItcGxhdGZvcm0udGVzdDAYghZvcDYwLndl +Yi1wbGF0Zm9ybS50ZXN0MBiCFm9wNzEud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A1 +Ni53ZWItcGxhdGZvcm0udGVzdDAYghZvcDk0LndlYi1wbGF0Zm9ybS50ZXN0MBiC +Fm9wMTgud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A1Ny53ZWItcGxhdGZvcm0udGVz +dDAYghZ3d3cyLndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wOTEud2ViLXBsYXRmb3Jt +LnRlc3QwGIIWb3A0MS53ZWItcGxhdGZvcm0udGVzdDAYghZvcDQ3LndlYi1wbGF0 +Zm9ybS50ZXN0MBiCFm9wNTIud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3AyNS53ZWIt +cGxhdGZvcm0udGVzdDAYghZvcDE2LndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wMjYu +d2ViLXBsYXRmb3JtLnRlc3QwGIIWb3AxMC53ZWItcGxhdGZvcm0udGVzdDAYghZv +cDY5LndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wMTIud2ViLXBsYXRmb3JtLnRlc3Qw +GIIWb3A5Ni53ZWItcGxhdGZvcm0udGVzdDAYghZvcDc0LndlYi1wbGF0Zm9ybS50 +ZXN0MBiCFm9wODkud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A4NC53ZWItcGxhdGZv +cm0udGVzdDAYghZvcDM3LndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wNDUud2ViLXBs +YXRmb3JtLnRlc3QwGIIWb3A2Mi53ZWItcGxhdGZvcm0udGVzdDAYghZvcDg2Lndl +Yi1wbGF0Zm9ybS50ZXN0MBiCFm9wNDIud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3Az +NC53ZWItcGxhdGZvcm0udGVzdDAYghZvcDQ4LndlYi1wbGF0Zm9ybS50ZXN0MBiC +Fm9wNzUud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A1MC53ZWItcGxhdGZvcm0udGVz +dDAYghZvcDIyLndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wMjMud2ViLXBsYXRmb3Jt +LnRlc3QwGIIWb3A3My53ZWItcGxhdGZvcm0udGVzdDAYghZvcDIwLndlYi1wbGF0 +Zm9ybS50ZXN0MBiCFm9wOTIud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3AzMi53ZWIt +cGxhdGZvcm0udGVzdDAYghZvcDgyLndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wOTgu +d2ViLXBsYXRmb3JtLnRlc3QwGIIWb3AzMS53ZWItcGxhdGZvcm0udGVzdDAYghZv +cDMwLndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wODcud2ViLXBsYXRmb3JtLnRlc3Qw +GIIWb3A3MC53ZWItcGxhdGZvcm0udGVzdDAYghZvcDY0LndlYi1wbGF0Zm9ybS50 +ZXN0MBiCFm9wMTEud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3AxNS53ZWItcGxhdGZv +cm0udGVzdDAYghZvcDg1LndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wNTgud2ViLXBs +YXRmb3JtLnRlc3QwGIIWd3d3MS53ZWItcGxhdGZvcm0udGVzdDAYghZvcDgzLndl +Yi1wbGF0Zm9ybS50ZXN0MBiCFm9wMTMud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A2 +OC53ZWItcGxhdGZvcm0udGVzdDAYghZvcDk5LndlYi1wbGF0Zm9ybS50ZXN0MBiC +Fm9wMzkud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A1OS53ZWItcGxhdGZvcm0udGVz +dDAYghZvcDk1LndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wNTMud2ViLXBsYXRmb3Jt +LnRlc3QwGIIWb3A2My53ZWItcGxhdGZvcm0udGVzdDAYghZvcDU0LndlYi1wbGF0 +Zm9ybS50ZXN0MBiCFm9wODgud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A5My53ZWIt +cGxhdGZvcm0udGVzdDAYghZvcDI4LndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wNTEu +d2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A2Ni53ZWItcGxhdGZvcm0udGVzdDAYghZv +cDE5LndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wOTAud2ViLXBsYXRmb3JtLnRlc3Qw +GIIWb3A4MC53ZWItcGxhdGZvcm0udGVzdDAYghZvcDY3LndlYi1wbGF0Zm9ybS50 +ZXN0MBiCFm9wNjUud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3AyNy53ZWItcGxhdGZv +cm0udGVzdDAYghZvcDc2LndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wNzIud2ViLXBs +YXRmb3JtLnRlc3QwGIIWb3AyOS53ZWItcGxhdGZvcm0udGVzdDAYghZvcDk3Lndl +Yi1wbGF0Zm9ybS50ZXN0MBiCFm9wMzUud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A1 +NS53ZWItcGxhdGZvcm0udGVzdDAYghZvcDQ2LndlYi1wbGF0Zm9ybS50ZXN0MBiC +Fm9wNzgud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3AxNy53ZWItcGxhdGZvcm0udGVz +dDAYghZvcDI0LndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wODEud2ViLXBsYXRmb3Jt +LnRlc3QwG4IZb3A3Lm5vdC13ZWItcGxhdGZvcm0udGVzdDAbghlvcDQubm90LXdl +Yi1wbGF0Zm9ybS50ZXN0MBuCGW9wOC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwG4IZ +d3d3Lnd3dy53ZWItcGxhdGZvcm0udGVzdDAbghlvcDkubm90LXdlYi1wbGF0Zm9y +bS50ZXN0MBuCGXd3dy5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwG4IZb3AxLm5vdC13 +ZWItcGxhdGZvcm0udGVzdDAbghlvcDMubm90LXdlYi1wbGF0Zm9ybS50ZXN0MBuC +GW9wNS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwG4IZb3AyLm5vdC13ZWItcGxhdGZv +cm0udGVzdDAbghlvcDYubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMjYubm90 +LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wOTQubm90LXdlYi1wbGF0Zm9ybS50ZXN0 +MByCGm9wNzUubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNTQubm90LXdlYi1w +bGF0Zm9ybS50ZXN0MByCGm9wMjUubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w +Mjgubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wOTIubm90LXdlYi1wbGF0Zm9y +bS50ZXN0MByCGm9wMTcubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wOTUubm90 LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNTMubm90LXdlYi1wbGF0Zm9ybS50ZXN0 -MByCGm9wNTAubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMjQubm90LXdlYi1w -bGF0Zm9ybS50ZXN0MByCGm9wMzEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w -OTUubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wODMubm90LXdlYi1wbGF0Zm9y -bS50ZXN0MByCGnd3dzIubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNzMubm90 -LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMTkubm90LXdlYi1wbGF0Zm9ybS50ZXN0 -MByCGm9wMjEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wODEubm90LXdlYi1w -bGF0Zm9ybS50ZXN0MByCGm9wNzAubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w -Nzgubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNDAubm90LXdlYi1wbGF0Zm9y -bS50ZXN0MByCGm9wMjUubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNjUubm90 -LXdlYi1wbGF0Zm9ybS50ZXN0MByCGnd3dy53d3cyLndlYi1wbGF0Zm9ybS50ZXN0 -MByCGm9wODAubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNTIubm90LXdlYi1w +MByCGm9wMzcubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNDEubm90LXdlYi1w bGF0Zm9ybS50ZXN0MByCGm9wNjgubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w -NDUubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNzEubm90LXdlYi1wbGF0Zm9y -bS50ZXN0MByCGm9wNzIubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wOTAubm90 -LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wODkubm90LXdlYi1wbGF0Zm9ybS50ZXN0 -MByCGm9wNDkubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNzcubm90LXdlYi1w -bGF0Zm9ybS50ZXN0MByCGm9wNzkubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w -ODIubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGnd3dy53d3cxLndlYi1wbGF0Zm9y -bS50ZXN0MByCGm9wMTIubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMzkubm90 -LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNDQubm90LXdlYi1wbGF0Zm9ybS50ZXN0 -MByCGnd3dzEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNTgubm90LXdlYi1w -bGF0Zm9ybS50ZXN0MByCGm9wMTQubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w -MzAubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNjIubm90LXdlYi1wbGF0Zm9y -bS50ZXN0MByCGm9wNjEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wOTIubm90 -LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMjkubm90LXdlYi1wbGF0Zm9ybS50ZXN0 -MByCGm9wOTgubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNjQubm90LXdlYi1w -bGF0Zm9ybS50ZXN0MByCGm9wMjYubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w -MjIubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wOTQubm90LXdlYi1wbGF0Zm9y -bS50ZXN0MByCGm9wMzgubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMzMubm90 -LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMjMubm90LXdlYi1wbGF0Zm9ybS50ZXN0 -MByCGm9wNTcubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNTQubm90LXdlYi1w -bGF0Zm9ybS50ZXN0MByCGm9wODUubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w -NDYubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wOTcubm90LXdlYi1wbGF0Zm9y -bS50ZXN0MByCGm9wMzIubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNjAubm90 -LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wOTYubm90LXdlYi1wbGF0Zm9ybS50ZXN0 -MByCGm9wNTEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNDEubm90LXdlYi1w -bGF0Zm9ybS50ZXN0MByCGm9wMzUubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w -OTkubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNDIubm90LXdlYi1wbGF0Zm9y -bS50ZXN0MByCGm9wNjcubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMzcubm90 -LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNDgubm90LXdlYi1wbGF0Zm9ybS50ZXN0 -MByCGm9wNTUubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNTYubm90LXdlYi1w -bGF0Zm9ybS50ZXN0MByCGm9wODQubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w -MzQubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNjkubm90LXdlYi1wbGF0Zm9y -bS50ZXN0MByCGm9wMTEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wOTMubm90 -LXdlYi1wbGF0Zm9ybS50ZXN0MByCGnd3dzEud3d3LndlYi1wbGF0Zm9ybS50ZXN0 -MByCGm9wODYubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMTMubm90LXdlYi1w -bGF0Zm9ybS50ZXN0MByCGm9wMjAubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w -NzYubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMjcubm90LXdlYi1wbGF0Zm9y -bS50ZXN0MByCGm9wMTcubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNzUubm90 -LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMTUubm90LXdlYi1wbGF0Zm9ybS50ZXN0 -MByCGm9wNDcubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMTgubm90LXdlYi1w +ODcubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGnd3dzEud3d3LndlYi1wbGF0Zm9y +bS50ZXN0MByCGm9wNzAubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wODMubm90 +LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wOTEubm90LXdlYi1wbGF0Zm9ybS50ZXN0 +MByCGm9wODEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wOTkubm90LXdlYi1w +bGF0Zm9ybS50ZXN0MByCGm9wNDgubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w +NjQubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNzYubm90LXdlYi1wbGF0Zm9y +bS50ZXN0MByCGnd3dy53d3cyLndlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMjQubm90 +LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNzgubm90LXdlYi1wbGF0Zm9ybS50ZXN0 +MByCGnd3dy53d3cxLndlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNzEubm90LXdlYi1w +bGF0Zm9ybS50ZXN0MByCGm9wMTUubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w +NzIubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNjUubm90LXdlYi1wbGF0Zm9y +bS50ZXN0MByCGm9wOTgubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNDkubm90 +LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNTAubm90LXdlYi1wbGF0Zm9ybS50ZXN0 +MByCGnd3dzEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNDcubm90LXdlYi1w +bGF0Zm9ybS50ZXN0MByCGm9wODIubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w +MTIubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMjcubm90LXdlYi1wbGF0Zm9y +bS50ZXN0MByCGm9wODkubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wODYubm90 +LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNTIubm90LXdlYi1wbGF0Zm9ybS50ZXN0 +MByCGm9wMjAubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMjMubm90LXdlYi1w bGF0Zm9ybS50ZXN0MByCGm9wNjMubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w -Mjgubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNDMubm90LXdlYi1wbGF0Zm9y -bS50ZXN0MByCGm9wNjYubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGnd3dzIud3d3 -LndlYi1wbGF0Zm9ybS50ZXN0MByCGm9wOTEubm90LXdlYi1wbGF0Zm9ybS50ZXN0 -MByCGm9wNzQubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNTkubm90LXdlYi1w -bGF0Zm9ybS50ZXN0MByCGm9wODgubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w -ODcubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMTAubm90LXdlYi1wbGF0Zm9y -bS50ZXN0MByCGm9wMTYubm90LXdlYi1wbGF0Zm9ybS50ZXN0MB2CG3d3dzEud3d3 -Mi53ZWItcGxhdGZvcm0udGVzdDAdght3d3cyLnd3dzIud2ViLXBsYXRmb3JtLnRl -c3QwHYIbd3d3Mi53d3cxLndlYi1wbGF0Zm9ybS50ZXN0MB2CG3d3dzEud3d3MS53 +NDIubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNzQubm90LXdlYi1wbGF0Zm9y +bS50ZXN0MByCGm9wNjIubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMTMubm90 +LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNTgubm90LXdlYi1wbGF0Zm9ybS50ZXN0 +MByCGm9wNjYubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGnd3dzIubm90LXdlYi1w +bGF0Zm9ybS50ZXN0MByCGm9wMzEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w +Mzkubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNzMubm90LXdlYi1wbGF0Zm9y +bS50ZXN0MByCGm9wNzcubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNTUubm90 +LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNjkubm90LXdlYi1wbGF0Zm9ybS50ZXN0 +MByCGm9wNTEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wOTYubm90LXdlYi1w +bGF0Zm9ybS50ZXN0MByCGm9wMTYubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w +MTAubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGnd3dzIud3d3LndlYi1wbGF0Zm9y +bS50ZXN0MByCGm9wNjEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMjEubm90 +LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wODAubm90LXdlYi1wbGF0Zm9ybS50ZXN0 +MByCGm9wOTAubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNjcubm90LXdlYi1w +bGF0Zm9ybS50ZXN0MByCGm9wNDMubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w +NTkubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNDQubm90LXdlYi1wbGF0Zm9y +bS50ZXN0MByCGm9wMTQubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMTkubm90 +LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMzMubm90LXdlYi1wbGF0Zm9ybS50ZXN0 +MByCGm9wMjIubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wODgubm90LXdlYi1w +bGF0Zm9ybS50ZXN0MByCGm9wNjAubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w +NDAubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNDYubm90LXdlYi1wbGF0Zm9y +bS50ZXN0MByCGm9wMzIubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNTYubm90 +LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMjkubm90LXdlYi1wbGF0Zm9ybS50ZXN0 +MByCGm9wMzQubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wOTcubm90LXdlYi1w +bGF0Zm9ybS50ZXN0MByCGm9wODQubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w +MzUubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wOTMubm90LXdlYi1wbGF0Zm9y +bS50ZXN0MByCGm9wNzkubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMTgubm90 +LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNTcubm90LXdlYi1wbGF0Zm9ybS50ZXN0 +MByCGm9wMzYubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMTEubm90LXdlYi1w +bGF0Zm9ybS50ZXN0MByCGm9wMzgubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w +ODUubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMzAubm90LXdlYi1wbGF0Zm9y +bS50ZXN0MByCGm9wNDUubm90LXdlYi1wbGF0Zm9ybS50ZXN0MB2CG3d3dzIud3d3 +Mi53ZWItcGxhdGZvcm0udGVzdDAdght3d3cxLnd3dzEud2ViLXBsYXRmb3JtLnRl +c3QwHYIbd3d3MS53d3cyLndlYi1wbGF0Zm9ybS50ZXN0MB2CG3d3dzIud3d3MS53 ZWItcGxhdGZvcm0udGVzdDAfgh13d3cud3d3Lm5vdC13ZWItcGxhdGZvcm0udGVz -dDAggh54bi0tbHZlLTZsYWQud2ViLXBsYXRmb3JtLnRlc3QwIIIed3d3MS53d3cu +dDAggh53d3cxLnd3dy5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwIIIed3d3Lnd3dzEu bm90LXdlYi1wbGF0Zm9ybS50ZXN0MCCCHnd3dy53d3cyLm5vdC13ZWItcGxhdGZv -cm0udGVzdDAggh53d3cyLnd3dy5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwIIIed3d3 -Lnd3dzEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MCGCH3d3dzIud3d3Mi5ub3Qtd2Vi -LXBsYXRmb3JtLnRlc3QwIYIfd3d3Mi53d3cxLm5vdC13ZWItcGxhdGZvcm0udGVz -dDAhgh93d3cxLnd3dzEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MCGCH3d3dzEud3d3 +cm0udGVzdDAggh53d3cyLnd3dy5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwIIIeeG4t +LWx2ZS02bGFkLndlYi1wbGF0Zm9ybS50ZXN0MCGCH3d3dzIud3d3MS5ub3Qtd2Vi +LXBsYXRmb3JtLnRlc3QwIYIfd3d3MS53d3cxLm5vdC13ZWItcGxhdGZvcm0udGVz +dDAhgh93d3cyLnd3dzIubm90LXdlYi1wbGF0Zm9ybS50ZXN0MCGCH3d3dzEud3d3 Mi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwJIIieG4tLWx2ZS02bGFkLnd3dy53ZWIt -cGxhdGZvcm0udGVzdDAkgiJ4bi0tbHZlLTZsYWQubm90LXdlYi1wbGF0Zm9ybS50 -ZXN0MCSCInd3dy54bi0tbHZlLTZsYWQud2ViLXBsYXRmb3JtLnRlc3QwJYIjd3d3 -Mi54bi0tbHZlLTZsYWQud2ViLXBsYXRmb3JtLnRlc3QwJYIjeG4tLWx2ZS02bGFk -Lnd3dzIud2ViLXBsYXRmb3JtLnRlc3QwJYIjeG4tLWx2ZS02bGFkLnd3dzEud2Vi +cGxhdGZvcm0udGVzdDAkgiJ3d3cueG4tLWx2ZS02bGFkLndlYi1wbGF0Zm9ybS50 +ZXN0MCSCInhuLS1sdmUtNmxhZC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwJYIjeG4t +LWx2ZS02bGFkLnd3dzEud2ViLXBsYXRmb3JtLnRlc3QwJYIjeG4tLWx2ZS02bGFk +Lnd3dzIud2ViLXBsYXRmb3JtLnRlc3QwJYIjd3d3Mi54bi0tbHZlLTZsYWQud2Vi LXBsYXRmb3JtLnRlc3QwJYIjd3d3MS54bi0tbHZlLTZsYWQud2ViLXBsYXRmb3Jt LnRlc3QwKIImeG4tLWx2ZS02bGFkLnd3dy5ub3Qtd2ViLXBsYXRmb3JtLnRlc3Qw -KIImd3d3LnhuLS1sdmUtNmxhZC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwKYIneG4t -LWx2ZS02bGFkLnd3dzEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MCmCJ3d3dzIueG4t -LWx2ZS02bGFkLm5vdC13ZWItcGxhdGZvcm0udGVzdDApgid3d3cxLnhuLS1sdmUt -NmxhZC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwKYIneG4tLWx2ZS02bGFkLnd3dzIu +KIImd3d3LnhuLS1sdmUtNmxhZC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwKYInd3d3 +MS54bi0tbHZlLTZsYWQubm90LXdlYi1wbGF0Zm9ybS50ZXN0MCmCJ3huLS1sdmUt +NmxhZC53d3cxLm5vdC13ZWItcGxhdGZvcm0udGVzdDApgid4bi0tbHZlLTZsYWQu +d3d3Mi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwKYInd3d3Mi54bi0tbHZlLTZsYWQu bm90LXdlYi1wbGF0Zm9ybS50ZXN0MCuCKXhuLS1uOGo2ZHM1M2x3d2tycWh2Mjhh LndlYi1wbGF0Zm9ybS50ZXN0MC2CK3huLS1sdmUtNmxhZC54bi0tbHZlLTZsYWQu -d2ViLXBsYXRmb3JtLnRlc3QwL4Itd3d3LnhuLS1uOGo2ZHM1M2x3d2tycWh2Mjhh +d2ViLXBsYXRmb3JtLnRlc3QwL4IteG4tLW44ajZkczUzbHd3a3JxaHYyOGEud3d3 LndlYi1wbGF0Zm9ybS50ZXN0MC+CLXhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLm5v -dC13ZWItcGxhdGZvcm0udGVzdDAvgi14bi0tbjhqNmRzNTNsd3drcnFodjI4YS53 -d3cud2ViLXBsYXRmb3JtLnRlc3QwMIIud3d3MS54bi0tbjhqNmRzNTNsd3drcnFo -djI4YS53ZWItcGxhdGZvcm0udGVzdDAwgi54bi0tbjhqNmRzNTNsd3drcnFodjI4 -YS53d3cyLndlYi1wbGF0Zm9ybS50ZXN0MDCCLnhuLS1uOGo2ZHM1M2x3d2tycWh2 -MjhhLnd3dzEud2ViLXBsYXRmb3JtLnRlc3QwMIIud3d3Mi54bi0tbjhqNmRzNTNs -d3drcnFodjI4YS53ZWItcGxhdGZvcm0udGVzdDAxgi94bi0tbHZlLTZsYWQueG4t +dC13ZWItcGxhdGZvcm0udGVzdDAvgi13d3cueG4tLW44ajZkczUzbHd3a3JxaHYy +OGEud2ViLXBsYXRmb3JtLnRlc3QwMIIud3d3Mi54bi0tbjhqNmRzNTNsd3drcnFo +djI4YS53ZWItcGxhdGZvcm0udGVzdDAwgi53d3cxLnhuLS1uOGo2ZHM1M2x3d2ty +cWh2MjhhLndlYi1wbGF0Zm9ybS50ZXN0MDCCLnhuLS1uOGo2ZHM1M2x3d2tycWh2 +MjhhLnd3dzEud2ViLXBsYXRmb3JtLnRlc3QwMIIueG4tLW44ajZkczUzbHd3a3Jx +aHYyOGEud3d3Mi53ZWItcGxhdGZvcm0udGVzdDAxgi94bi0tbHZlLTZsYWQueG4t LWx2ZS02bGFkLm5vdC13ZWItcGxhdGZvcm0udGVzdDAzgjF3d3cueG4tLW44ajZk czUzbHd3a3JxaHYyOGEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MDOCMXhuLS1uOGo2 ZHM1M2x3d2tycWh2MjhhLnd3dy5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwNIIyeG4t -LW44ajZkczUzbHd3a3JxaHYyOGEud3d3Mi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3Qw -NIIyd3d3MS54bi0tbjhqNmRzNTNsd3drcnFodjI4YS5ub3Qtd2ViLXBsYXRmb3Jt -LnRlc3QwNIIyd3d3Mi54bi0tbjhqNmRzNTNsd3drcnFodjI4YS5ub3Qtd2ViLXBs -YXRmb3JtLnRlc3QwNIIyeG4tLW44ajZkczUzbHd3a3JxaHYyOGEud3d3MS5ub3Qt +LW44ajZkczUzbHd3a3JxaHYyOGEud3d3MS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3Qw +NIIyd3d3Mi54bi0tbjhqNmRzNTNsd3drcnFodjI4YS5ub3Qtd2ViLXBsYXRmb3Jt +LnRlc3QwNIIyd3d3MS54bi0tbjhqNmRzNTNsd3drcnFodjI4YS5ub3Qtd2ViLXBs +YXRmb3JtLnRlc3QwNIIyeG4tLW44ajZkczUzbHd3a3JxaHYyOGEud3d3Mi5ub3Qt d2ViLXBsYXRmb3JtLnRlc3QwOII2eG4tLW44ajZkczUzbHd3a3JxaHYyOGEueG4t LWx2ZS02bGFkLndlYi1wbGF0Zm9ybS50ZXN0MDiCNnhuLS1sdmUtNmxhZC54bi0t bjhqNmRzNTNsd3drcnFodjI4YS53ZWItcGxhdGZvcm0udGVzdDA8gjp4bi0tbjhq @@ -180,156 +180,156 @@ LW44ajZkczUzbHd3a3JxaHYyOGEud2ViLXBsYXRmb3JtLnRlc3QwR4JFeG4tLW44 ajZkczUzbHd3a3JxaHYyOGEueG4tLW44ajZkczUzbHd3a3JxaHYyOGEubm90LXdl Yi1wbGF0Zm9ybS50ZXN0MBMGA1UdJQQMMAoGCCsGAQUFBwMBMIIdjwYDVR0RBIId -hjCCHYKCEXdlYi1wbGF0Zm9ybS50ZXN0ghVvcDgud2ViLXBsYXRmb3JtLnRlc3SC -FW9wNy53ZWItcGxhdGZvcm0udGVzdIIVb3A5LndlYi1wbGF0Zm9ybS50ZXN0ghVv -cDQud2ViLXBsYXRmb3JtLnRlc3SCFW5vdC13ZWItcGxhdGZvcm0udGVzdIIVb3A2 -LndlYi1wbGF0Zm9ybS50ZXN0ghVvcDMud2ViLXBsYXRmb3JtLnRlc3SCFW9wMi53 -ZWItcGxhdGZvcm0udGVzdIIVb3AxLndlYi1wbGF0Zm9ybS50ZXN0ghV3d3cud2Vi -LXBsYXRmb3JtLnRlc3SCFW9wNS53ZWItcGxhdGZvcm0udGVzdIIWb3A4OC53ZWIt -cGxhdGZvcm0udGVzdIIWb3A5OC53ZWItcGxhdGZvcm0udGVzdIIWb3A4NS53ZWIt -cGxhdGZvcm0udGVzdIIWb3A4OS53ZWItcGxhdGZvcm0udGVzdIIWb3A2Ni53ZWIt -cGxhdGZvcm0udGVzdIIWb3A3Mi53ZWItcGxhdGZvcm0udGVzdIIWb3AyNC53ZWIt -cGxhdGZvcm0udGVzdIIWb3A0MS53ZWItcGxhdGZvcm0udGVzdIIWb3A3OS53ZWIt -cGxhdGZvcm0udGVzdIIWb3A5MS53ZWItcGxhdGZvcm0udGVzdIIWb3A1OS53ZWIt -cGxhdGZvcm0udGVzdIIWb3AzOS53ZWItcGxhdGZvcm0udGVzdIIWb3A2MC53ZWIt -cGxhdGZvcm0udGVzdIIWb3A1OC53ZWItcGxhdGZvcm0udGVzdIIWb3AyOC53ZWIt -cGxhdGZvcm0udGVzdIIWd3d3MS53ZWItcGxhdGZvcm0udGVzdIIWb3AxNC53ZWIt -cGxhdGZvcm0udGVzdIIWb3A2OS53ZWItcGxhdGZvcm0udGVzdIIWb3A0MC53ZWIt -cGxhdGZvcm0udGVzdIIWb3A3NC53ZWItcGxhdGZvcm0udGVzdIIWb3AzMS53ZWIt -cGxhdGZvcm0udGVzdIIWb3AxOC53ZWItcGxhdGZvcm0udGVzdIIWb3A3My53ZWIt -cGxhdGZvcm0udGVzdIIWb3A3Ny53ZWItcGxhdGZvcm0udGVzdIIWb3AxMi53ZWIt -cGxhdGZvcm0udGVzdIIWb3A1NC53ZWItcGxhdGZvcm0udGVzdIIWb3A2My53ZWIt -cGxhdGZvcm0udGVzdIIWb3A3MS53ZWItcGxhdGZvcm0udGVzdIIWb3A5NS53ZWIt -cGxhdGZvcm0udGVzdIIWb3AxNi53ZWItcGxhdGZvcm0udGVzdIIWb3AzNi53ZWIt -cGxhdGZvcm0udGVzdIIWb3AyNy53ZWItcGxhdGZvcm0udGVzdIIWb3AyOS53ZWIt -cGxhdGZvcm0udGVzdIIWb3A5NC53ZWItcGxhdGZvcm0udGVzdIIWb3A0NC53ZWIt -cGxhdGZvcm0udGVzdIIWb3AzMy53ZWItcGxhdGZvcm0udGVzdIIWb3A4NC53ZWIt -cGxhdGZvcm0udGVzdIIWb3AzMi53ZWItcGxhdGZvcm0udGVzdIIWb3A2MS53ZWIt -cGxhdGZvcm0udGVzdIIWb3A3MC53ZWItcGxhdGZvcm0udGVzdIIWd3d3Mi53ZWIt -cGxhdGZvcm0udGVzdIIWb3A0My53ZWItcGxhdGZvcm0udGVzdIIWb3A3OC53ZWIt -cGxhdGZvcm0udGVzdIIWb3AyNi53ZWItcGxhdGZvcm0udGVzdIIWb3A3Ni53ZWIt -cGxhdGZvcm0udGVzdIIWb3A1Mi53ZWItcGxhdGZvcm0udGVzdIIWb3A5OS53ZWIt -cGxhdGZvcm0udGVzdIIWb3A4Ni53ZWItcGxhdGZvcm0udGVzdIIWb3A0Ni53ZWIt -cGxhdGZvcm0udGVzdIIWb3AxNy53ZWItcGxhdGZvcm0udGVzdIIWb3A5MC53ZWIt -cGxhdGZvcm0udGVzdIIWb3A5My53ZWItcGxhdGZvcm0udGVzdIIWb3AxMC53ZWIt -cGxhdGZvcm0udGVzdIIWb3A1NS53ZWItcGxhdGZvcm0udGVzdIIWb3A0Ny53ZWIt -cGxhdGZvcm0udGVzdIIWb3A1MS53ZWItcGxhdGZvcm0udGVzdIIWb3A0NS53ZWIt -cGxhdGZvcm0udGVzdIIWb3A4MC53ZWItcGxhdGZvcm0udGVzdIIWb3A2OC53ZWIt -cGxhdGZvcm0udGVzdIIWb3A0OS53ZWItcGxhdGZvcm0udGVzdIIWb3A1Ny53ZWIt -cGxhdGZvcm0udGVzdIIWb3AzNS53ZWItcGxhdGZvcm0udGVzdIIWb3A2Ny53ZWIt -cGxhdGZvcm0udGVzdIIWb3A5Mi53ZWItcGxhdGZvcm0udGVzdIIWb3AxNS53ZWIt -cGxhdGZvcm0udGVzdIIWb3AxMy53ZWItcGxhdGZvcm0udGVzdIIWb3A3NS53ZWIt -cGxhdGZvcm0udGVzdIIWb3A2NC53ZWItcGxhdGZvcm0udGVzdIIWb3A5Ny53ZWIt -cGxhdGZvcm0udGVzdIIWb3AzNy53ZWItcGxhdGZvcm0udGVzdIIWb3A1Ni53ZWIt -cGxhdGZvcm0udGVzdIIWb3A2Mi53ZWItcGxhdGZvcm0udGVzdIIWb3A4Mi53ZWIt -cGxhdGZvcm0udGVzdIIWb3AyNS53ZWItcGxhdGZvcm0udGVzdIIWb3AxMS53ZWIt -cGxhdGZvcm0udGVzdIIWb3A1MC53ZWItcGxhdGZvcm0udGVzdIIWb3AzOC53ZWIt -cGxhdGZvcm0udGVzdIIWb3A4My53ZWItcGxhdGZvcm0udGVzdIIWb3A4MS53ZWIt -cGxhdGZvcm0udGVzdIIWb3AyMC53ZWItcGxhdGZvcm0udGVzdIIWb3AyMS53ZWIt -cGxhdGZvcm0udGVzdIIWb3AyMy53ZWItcGxhdGZvcm0udGVzdIIWb3A0Mi53ZWIt -cGxhdGZvcm0udGVzdIIWb3AyMi53ZWItcGxhdGZvcm0udGVzdIIWb3A2NS53ZWIt -cGxhdGZvcm0udGVzdIIWb3A5Ni53ZWItcGxhdGZvcm0udGVzdIIWb3A4Ny53ZWIt -cGxhdGZvcm0udGVzdIIWb3AxOS53ZWItcGxhdGZvcm0udGVzdIIWb3A1My53ZWIt -cGxhdGZvcm0udGVzdIIWb3AzMC53ZWItcGxhdGZvcm0udGVzdIIWb3A0OC53ZWIt -cGxhdGZvcm0udGVzdIIWb3AzNC53ZWItcGxhdGZvcm0udGVzdIIZb3A2Lm5vdC13 -ZWItcGxhdGZvcm0udGVzdIIZb3AzLm5vdC13ZWItcGxhdGZvcm0udGVzdIIZb3Ay -Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIZb3A1Lm5vdC13ZWItcGxhdGZvcm0udGVz -dIIZd3d3Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIZd3d3Lnd3dy53ZWItcGxhdGZv -cm0udGVzdIIZb3A3Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIZb3A0Lm5vdC13ZWIt -cGxhdGZvcm0udGVzdIIZb3A4Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIZb3A5Lm5v -dC13ZWItcGxhdGZvcm0udGVzdIIZb3AxLm5vdC13ZWItcGxhdGZvcm0udGVzdIIa -b3AzNi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNTMubm90LXdlYi1wbGF0Zm9y -bS50ZXN0ghpvcDUwLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3AyNC5ub3Qtd2Vi -LXBsYXRmb3JtLnRlc3SCGm9wMzEubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDk1 -Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A4My5ub3Qtd2ViLXBsYXRmb3JtLnRl -c3SCGnd3dzIubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDczLm5vdC13ZWItcGxh -dGZvcm0udGVzdIIab3AxOS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMjEubm90 -LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDgxLm5vdC13ZWItcGxhdGZvcm0udGVzdIIa -b3A3MC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNzgubm90LXdlYi1wbGF0Zm9y -bS50ZXN0ghpvcDQwLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3AyNS5ub3Qtd2Vi -LXBsYXRmb3JtLnRlc3SCGm9wNjUubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghp3d3cu -d3d3Mi53ZWItcGxhdGZvcm0udGVzdIIab3A4MC5ub3Qtd2ViLXBsYXRmb3JtLnRl -c3SCGm9wNTIubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDY4Lm5vdC13ZWItcGxh -dGZvcm0udGVzdIIab3A0NS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNzEubm90 -LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDcyLm5vdC13ZWItcGxhdGZvcm0udGVzdIIa -b3A5MC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wODkubm90LXdlYi1wbGF0Zm9y -bS50ZXN0ghpvcDQ5Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A3Ny5ub3Qtd2Vi -LXBsYXRmb3JtLnRlc3SCGm9wNzkubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDgy -Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIad3d3Lnd3dzEud2ViLXBsYXRmb3JtLnRl -c3SCGm9wMTIubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDM5Lm5vdC13ZWItcGxh -dGZvcm0udGVzdIIab3A0NC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGnd3dzEubm90 -LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDU4Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIa -b3AxNC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMzAubm90LXdlYi1wbGF0Zm9y -bS50ZXN0ghpvcDYyLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A2MS5ub3Qtd2Vi -LXBsYXRmb3JtLnRlc3SCGm9wOTIubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDI5 -Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A5OC5ub3Qtd2ViLXBsYXRmb3JtLnRl -c3SCGm9wNjQubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDI2Lm5vdC13ZWItcGxh -dGZvcm0udGVzdIIab3AyMi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wOTQubm90 -LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDM4Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIa -b3AzMy5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMjMubm90LXdlYi1wbGF0Zm9y -bS50ZXN0ghpvcDU3Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A1NC5ub3Qtd2Vi -LXBsYXRmb3JtLnRlc3SCGm9wODUubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDQ2 -Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A5Ny5ub3Qtd2ViLXBsYXRmb3JtLnRl -c3SCGm9wMzIubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDYwLm5vdC13ZWItcGxh -dGZvcm0udGVzdIIab3A5Ni5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNTEubm90 +hjCCHYKCEXdlYi1wbGF0Zm9ybS50ZXN0ghVub3Qtd2ViLXBsYXRmb3JtLnRlc3SC +FW9wNi53ZWItcGxhdGZvcm0udGVzdIIVd3d3LndlYi1wbGF0Zm9ybS50ZXN0ghVv +cDEud2ViLXBsYXRmb3JtLnRlc3SCFW9wNy53ZWItcGxhdGZvcm0udGVzdIIVb3A4 +LndlYi1wbGF0Zm9ybS50ZXN0ghVvcDIud2ViLXBsYXRmb3JtLnRlc3SCFW9wOS53 +ZWItcGxhdGZvcm0udGVzdIIVb3A1LndlYi1wbGF0Zm9ybS50ZXN0ghVvcDQud2Vi +LXBsYXRmb3JtLnRlc3SCFW9wMy53ZWItcGxhdGZvcm0udGVzdIIWb3A0MC53ZWIt +cGxhdGZvcm0udGVzdIIWb3A2MS53ZWItcGxhdGZvcm0udGVzdIIWb3AzMy53ZWIt +cGxhdGZvcm0udGVzdIIWb3A3OS53ZWItcGxhdGZvcm0udGVzdIIWb3AzOC53ZWIt +cGxhdGZvcm0udGVzdIIWb3A3Ny53ZWItcGxhdGZvcm0udGVzdIIWb3A0My53ZWIt +cGxhdGZvcm0udGVzdIIWb3A0NC53ZWItcGxhdGZvcm0udGVzdIIWb3AxNC53ZWIt +cGxhdGZvcm0udGVzdIIWb3A0OS53ZWItcGxhdGZvcm0udGVzdIIWb3AzNi53ZWIt +cGxhdGZvcm0udGVzdIIWb3AyMS53ZWItcGxhdGZvcm0udGVzdIIWb3A2MC53ZWIt +cGxhdGZvcm0udGVzdIIWb3A3MS53ZWItcGxhdGZvcm0udGVzdIIWb3A1Ni53ZWIt +cGxhdGZvcm0udGVzdIIWb3A5NC53ZWItcGxhdGZvcm0udGVzdIIWb3AxOC53ZWIt +cGxhdGZvcm0udGVzdIIWb3A1Ny53ZWItcGxhdGZvcm0udGVzdIIWd3d3Mi53ZWIt +cGxhdGZvcm0udGVzdIIWb3A5MS53ZWItcGxhdGZvcm0udGVzdIIWb3A0MS53ZWIt +cGxhdGZvcm0udGVzdIIWb3A0Ny53ZWItcGxhdGZvcm0udGVzdIIWb3A1Mi53ZWIt +cGxhdGZvcm0udGVzdIIWb3AyNS53ZWItcGxhdGZvcm0udGVzdIIWb3AxNi53ZWIt +cGxhdGZvcm0udGVzdIIWb3AyNi53ZWItcGxhdGZvcm0udGVzdIIWb3AxMC53ZWIt +cGxhdGZvcm0udGVzdIIWb3A2OS53ZWItcGxhdGZvcm0udGVzdIIWb3AxMi53ZWIt +cGxhdGZvcm0udGVzdIIWb3A5Ni53ZWItcGxhdGZvcm0udGVzdIIWb3A3NC53ZWIt +cGxhdGZvcm0udGVzdIIWb3A4OS53ZWItcGxhdGZvcm0udGVzdIIWb3A4NC53ZWIt +cGxhdGZvcm0udGVzdIIWb3AzNy53ZWItcGxhdGZvcm0udGVzdIIWb3A0NS53ZWIt +cGxhdGZvcm0udGVzdIIWb3A2Mi53ZWItcGxhdGZvcm0udGVzdIIWb3A4Ni53ZWIt +cGxhdGZvcm0udGVzdIIWb3A0Mi53ZWItcGxhdGZvcm0udGVzdIIWb3AzNC53ZWIt +cGxhdGZvcm0udGVzdIIWb3A0OC53ZWItcGxhdGZvcm0udGVzdIIWb3A3NS53ZWIt +cGxhdGZvcm0udGVzdIIWb3A1MC53ZWItcGxhdGZvcm0udGVzdIIWb3AyMi53ZWIt +cGxhdGZvcm0udGVzdIIWb3AyMy53ZWItcGxhdGZvcm0udGVzdIIWb3A3My53ZWIt +cGxhdGZvcm0udGVzdIIWb3AyMC53ZWItcGxhdGZvcm0udGVzdIIWb3A5Mi53ZWIt +cGxhdGZvcm0udGVzdIIWb3AzMi53ZWItcGxhdGZvcm0udGVzdIIWb3A4Mi53ZWIt +cGxhdGZvcm0udGVzdIIWb3A5OC53ZWItcGxhdGZvcm0udGVzdIIWb3AzMS53ZWIt +cGxhdGZvcm0udGVzdIIWb3AzMC53ZWItcGxhdGZvcm0udGVzdIIWb3A4Ny53ZWIt +cGxhdGZvcm0udGVzdIIWb3A3MC53ZWItcGxhdGZvcm0udGVzdIIWb3A2NC53ZWIt +cGxhdGZvcm0udGVzdIIWb3AxMS53ZWItcGxhdGZvcm0udGVzdIIWb3AxNS53ZWIt +cGxhdGZvcm0udGVzdIIWb3A4NS53ZWItcGxhdGZvcm0udGVzdIIWb3A1OC53ZWIt +cGxhdGZvcm0udGVzdIIWd3d3MS53ZWItcGxhdGZvcm0udGVzdIIWb3A4My53ZWIt +cGxhdGZvcm0udGVzdIIWb3AxMy53ZWItcGxhdGZvcm0udGVzdIIWb3A2OC53ZWIt +cGxhdGZvcm0udGVzdIIWb3A5OS53ZWItcGxhdGZvcm0udGVzdIIWb3AzOS53ZWIt +cGxhdGZvcm0udGVzdIIWb3A1OS53ZWItcGxhdGZvcm0udGVzdIIWb3A5NS53ZWIt +cGxhdGZvcm0udGVzdIIWb3A1My53ZWItcGxhdGZvcm0udGVzdIIWb3A2My53ZWIt +cGxhdGZvcm0udGVzdIIWb3A1NC53ZWItcGxhdGZvcm0udGVzdIIWb3A4OC53ZWIt +cGxhdGZvcm0udGVzdIIWb3A5My53ZWItcGxhdGZvcm0udGVzdIIWb3AyOC53ZWIt +cGxhdGZvcm0udGVzdIIWb3A1MS53ZWItcGxhdGZvcm0udGVzdIIWb3A2Ni53ZWIt +cGxhdGZvcm0udGVzdIIWb3AxOS53ZWItcGxhdGZvcm0udGVzdIIWb3A5MC53ZWIt +cGxhdGZvcm0udGVzdIIWb3A4MC53ZWItcGxhdGZvcm0udGVzdIIWb3A2Ny53ZWIt +cGxhdGZvcm0udGVzdIIWb3A2NS53ZWItcGxhdGZvcm0udGVzdIIWb3AyNy53ZWIt +cGxhdGZvcm0udGVzdIIWb3A3Ni53ZWItcGxhdGZvcm0udGVzdIIWb3A3Mi53ZWIt +cGxhdGZvcm0udGVzdIIWb3AyOS53ZWItcGxhdGZvcm0udGVzdIIWb3A5Ny53ZWIt +cGxhdGZvcm0udGVzdIIWb3AzNS53ZWItcGxhdGZvcm0udGVzdIIWb3A1NS53ZWIt +cGxhdGZvcm0udGVzdIIWb3A0Ni53ZWItcGxhdGZvcm0udGVzdIIWb3A3OC53ZWIt +cGxhdGZvcm0udGVzdIIWb3AxNy53ZWItcGxhdGZvcm0udGVzdIIWb3AyNC53ZWIt +cGxhdGZvcm0udGVzdIIWb3A4MS53ZWItcGxhdGZvcm0udGVzdIIZb3A3Lm5vdC13 +ZWItcGxhdGZvcm0udGVzdIIZb3A0Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIZb3A4 +Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIZd3d3Lnd3dy53ZWItcGxhdGZvcm0udGVz +dIIZb3A5Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIZd3d3Lm5vdC13ZWItcGxhdGZv +cm0udGVzdIIZb3AxLm5vdC13ZWItcGxhdGZvcm0udGVzdIIZb3AzLm5vdC13ZWIt +cGxhdGZvcm0udGVzdIIZb3A1Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIZb3AyLm5v +dC13ZWItcGxhdGZvcm0udGVzdIIZb3A2Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIa +b3AyNi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wOTQubm90LXdlYi1wbGF0Zm9y +bS50ZXN0ghpvcDc1Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A1NC5ub3Qtd2Vi +LXBsYXRmb3JtLnRlc3SCGm9wMjUubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDI4 +Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A5Mi5ub3Qtd2ViLXBsYXRmb3JtLnRl +c3SCGm9wMTcubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDk1Lm5vdC13ZWItcGxh +dGZvcm0udGVzdIIab3A1My5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMzcubm90 LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDQxLm5vdC13ZWItcGxhdGZvcm0udGVzdIIa -b3AzNS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wOTkubm90LXdlYi1wbGF0Zm9y -bS50ZXN0ghpvcDQyLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A2Ny5ub3Qtd2Vi -LXBsYXRmb3JtLnRlc3SCGm9wMzcubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDQ4 -Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A1NS5ub3Qtd2ViLXBsYXRmb3JtLnRl -c3SCGm9wNTYubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDg0Lm5vdC13ZWItcGxh -dGZvcm0udGVzdIIab3AzNC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNjkubm90 -LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDExLm5vdC13ZWItcGxhdGZvcm0udGVzdIIa -b3A5My5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGnd3dzEud3d3LndlYi1wbGF0Zm9y -bS50ZXN0ghpvcDg2Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3AxMy5ub3Qtd2Vi -LXBsYXRmb3JtLnRlc3SCGm9wMjAubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDc2 -Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3AyNy5ub3Qtd2ViLXBsYXRmb3JtLnRl -c3SCGm9wMTcubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDc1Lm5vdC13ZWItcGxh -dGZvcm0udGVzdIIab3AxNS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNDcubm90 -LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDE4Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIa -b3A2My5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMjgubm90LXdlYi1wbGF0Zm9y -bS50ZXN0ghpvcDQzLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A2Ni5ub3Qtd2Vi -LXBsYXRmb3JtLnRlc3SCGnd3dzIud3d3LndlYi1wbGF0Zm9ybS50ZXN0ghpvcDkx -Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A3NC5ub3Qtd2ViLXBsYXRmb3JtLnRl -c3SCGm9wNTkubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDg4Lm5vdC13ZWItcGxh -dGZvcm0udGVzdIIab3A4Ny5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMTAubm90 -LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDE2Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIb -d3d3MS53d3cyLndlYi1wbGF0Zm9ybS50ZXN0ght3d3cyLnd3dzIud2ViLXBsYXRm -b3JtLnRlc3SCG3d3dzIud3d3MS53ZWItcGxhdGZvcm0udGVzdIIbd3d3MS53d3cx +b3A2OC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wODcubm90LXdlYi1wbGF0Zm9y +bS50ZXN0ghp3d3cxLnd3dy53ZWItcGxhdGZvcm0udGVzdIIab3A3MC5ub3Qtd2Vi +LXBsYXRmb3JtLnRlc3SCGm9wODMubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDkx +Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A4MS5ub3Qtd2ViLXBsYXRmb3JtLnRl +c3SCGm9wOTkubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDQ4Lm5vdC13ZWItcGxh +dGZvcm0udGVzdIIab3A2NC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNzYubm90 +LXdlYi1wbGF0Zm9ybS50ZXN0ghp3d3cud3d3Mi53ZWItcGxhdGZvcm0udGVzdIIa +b3AyNC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNzgubm90LXdlYi1wbGF0Zm9y +bS50ZXN0ghp3d3cud3d3MS53ZWItcGxhdGZvcm0udGVzdIIab3A3MS5ub3Qtd2Vi +LXBsYXRmb3JtLnRlc3SCGm9wMTUubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDcy +Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A2NS5ub3Qtd2ViLXBsYXRmb3JtLnRl +c3SCGm9wOTgubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDQ5Lm5vdC13ZWItcGxh +dGZvcm0udGVzdIIab3A1MC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGnd3dzEubm90 +LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDQ3Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIa +b3A4Mi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMTIubm90LXdlYi1wbGF0Zm9y +bS50ZXN0ghpvcDI3Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A4OS5ub3Qtd2Vi +LXBsYXRmb3JtLnRlc3SCGm9wODYubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDUy +Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3AyMC5ub3Qtd2ViLXBsYXRmb3JtLnRl +c3SCGm9wMjMubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDYzLm5vdC13ZWItcGxh +dGZvcm0udGVzdIIab3A0Mi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNzQubm90 +LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDYyLm5vdC13ZWItcGxhdGZvcm0udGVzdIIa +b3AxMy5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNTgubm90LXdlYi1wbGF0Zm9y +bS50ZXN0ghpvcDY2Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIad3d3Mi5ub3Qtd2Vi +LXBsYXRmb3JtLnRlc3SCGm9wMzEubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDM5 +Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A3My5ub3Qtd2ViLXBsYXRmb3JtLnRl +c3SCGm9wNzcubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDU1Lm5vdC13ZWItcGxh +dGZvcm0udGVzdIIab3A2OS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNTEubm90 +LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDk2Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIa +b3AxNi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMTAubm90LXdlYi1wbGF0Zm9y +bS50ZXN0ghp3d3cyLnd3dy53ZWItcGxhdGZvcm0udGVzdIIab3A2MS5ub3Qtd2Vi +LXBsYXRmb3JtLnRlc3SCGm9wMjEubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDgw +Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A5MC5ub3Qtd2ViLXBsYXRmb3JtLnRl +c3SCGm9wNjcubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDQzLm5vdC13ZWItcGxh +dGZvcm0udGVzdIIab3A1OS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNDQubm90 +LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDE0Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIa +b3AxOS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMzMubm90LXdlYi1wbGF0Zm9y +bS50ZXN0ghpvcDIyLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A4OC5ub3Qtd2Vi +LXBsYXRmb3JtLnRlc3SCGm9wNjAubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDQw +Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A0Ni5ub3Qtd2ViLXBsYXRmb3JtLnRl +c3SCGm9wMzIubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDU2Lm5vdC13ZWItcGxh +dGZvcm0udGVzdIIab3AyOS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMzQubm90 +LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDk3Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIa +b3A4NC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMzUubm90LXdlYi1wbGF0Zm9y +bS50ZXN0ghpvcDkzLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A3OS5ub3Qtd2Vi +LXBsYXRmb3JtLnRlc3SCGm9wMTgubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDU3 +Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3AzNi5ub3Qtd2ViLXBsYXRmb3JtLnRl +c3SCGm9wMTEubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDM4Lm5vdC13ZWItcGxh +dGZvcm0udGVzdIIab3A4NS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMzAubm90 +LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDQ1Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIb +d3d3Mi53d3cyLndlYi1wbGF0Zm9ybS50ZXN0ght3d3cxLnd3dzEud2ViLXBsYXRm +b3JtLnRlc3SCG3d3dzEud3d3Mi53ZWItcGxhdGZvcm0udGVzdIIbd3d3Mi53d3cx LndlYi1wbGF0Zm9ybS50ZXN0gh13d3cud3d3Lm5vdC13ZWItcGxhdGZvcm0udGVz -dIIeeG4tLWx2ZS02bGFkLndlYi1wbGF0Zm9ybS50ZXN0gh53d3cxLnd3dy5ub3Qt +dIIed3d3MS53d3cubm90LXdlYi1wbGF0Zm9ybS50ZXN0gh53d3cud3d3MS5ub3Qt d2ViLXBsYXRmb3JtLnRlc3SCHnd3dy53d3cyLm5vdC13ZWItcGxhdGZvcm0udGVz -dIIed3d3Mi53d3cubm90LXdlYi1wbGF0Zm9ybS50ZXN0gh53d3cud3d3MS5ub3Qt -d2ViLXBsYXRmb3JtLnRlc3SCH3d3dzIud3d3Mi5ub3Qtd2ViLXBsYXRmb3JtLnRl -c3SCH3d3dzIud3d3MS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCH3d3dzEud3d3MS5u +dIIed3d3Mi53d3cubm90LXdlYi1wbGF0Zm9ybS50ZXN0gh54bi0tbHZlLTZsYWQu +d2ViLXBsYXRmb3JtLnRlc3SCH3d3dzIud3d3MS5ub3Qtd2ViLXBsYXRmb3JtLnRl +c3SCH3d3dzEud3d3MS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCH3d3dzIud3d3Mi5u b3Qtd2ViLXBsYXRmb3JtLnRlc3SCH3d3dzEud3d3Mi5ub3Qtd2ViLXBsYXRmb3Jt -LnRlc3SCInhuLS1sdmUtNmxhZC53d3cud2ViLXBsYXRmb3JtLnRlc3SCInhuLS1s -dmUtNmxhZC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCInd3dy54bi0tbHZlLTZsYWQu -d2ViLXBsYXRmb3JtLnRlc3SCI3d3dzIueG4tLWx2ZS02bGFkLndlYi1wbGF0Zm9y -bS50ZXN0giN4bi0tbHZlLTZsYWQud3d3Mi53ZWItcGxhdGZvcm0udGVzdIIjeG4t -LWx2ZS02bGFkLnd3dzEud2ViLXBsYXRmb3JtLnRlc3SCI3d3dzEueG4tLWx2ZS02 +LnRlc3SCInhuLS1sdmUtNmxhZC53d3cud2ViLXBsYXRmb3JtLnRlc3SCInd3dy54 +bi0tbHZlLTZsYWQud2ViLXBsYXRmb3JtLnRlc3SCInhuLS1sdmUtNmxhZC5ub3Qt +d2ViLXBsYXRmb3JtLnRlc3SCI3huLS1sdmUtNmxhZC53d3cxLndlYi1wbGF0Zm9y +bS50ZXN0giN4bi0tbHZlLTZsYWQud3d3Mi53ZWItcGxhdGZvcm0udGVzdIIjd3d3 +Mi54bi0tbHZlLTZsYWQud2ViLXBsYXRmb3JtLnRlc3SCI3d3dzEueG4tLWx2ZS02 bGFkLndlYi1wbGF0Zm9ybS50ZXN0giZ4bi0tbHZlLTZsYWQud3d3Lm5vdC13ZWIt cGxhdGZvcm0udGVzdIImd3d3LnhuLS1sdmUtNmxhZC5ub3Qtd2ViLXBsYXRmb3Jt -LnRlc3SCJ3huLS1sdmUtNmxhZC53d3cxLm5vdC13ZWItcGxhdGZvcm0udGVzdIIn -d3d3Mi54bi0tbHZlLTZsYWQubm90LXdlYi1wbGF0Zm9ybS50ZXN0gid3d3cxLnhu -LS1sdmUtNmxhZC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCJ3huLS1sdmUtNmxhZC53 -d3cyLm5vdC13ZWItcGxhdGZvcm0udGVzdIIpeG4tLW44ajZkczUzbHd3a3JxaHYy +LnRlc3SCJ3d3dzEueG4tLWx2ZS02bGFkLm5vdC13ZWItcGxhdGZvcm0udGVzdIIn +eG4tLWx2ZS02bGFkLnd3dzEubm90LXdlYi1wbGF0Zm9ybS50ZXN0gid4bi0tbHZl +LTZsYWQud3d3Mi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCJ3d3dzIueG4tLWx2ZS02 +bGFkLm5vdC13ZWItcGxhdGZvcm0udGVzdIIpeG4tLW44ajZkczUzbHd3a3JxaHYy OGEud2ViLXBsYXRmb3JtLnRlc3SCK3huLS1sdmUtNmxhZC54bi0tbHZlLTZsYWQu -d2ViLXBsYXRmb3JtLnRlc3SCLXd3dy54bi0tbjhqNmRzNTNsd3drcnFodjI4YS53 +d2ViLXBsYXRmb3JtLnRlc3SCLXhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLnd3dy53 ZWItcGxhdGZvcm0udGVzdIIteG4tLW44ajZkczUzbHd3a3JxaHYyOGEubm90LXdl -Yi1wbGF0Zm9ybS50ZXN0gi14bi0tbjhqNmRzNTNsd3drcnFodjI4YS53d3cud2Vi -LXBsYXRmb3JtLnRlc3SCLnd3dzEueG4tLW44ajZkczUzbHd3a3JxaHYyOGEud2Vi -LXBsYXRmb3JtLnRlc3SCLnhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLnd3dzIud2Vi -LXBsYXRmb3JtLnRlc3SCLnhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLnd3dzEud2Vi +Yi1wbGF0Zm9ybS50ZXN0gi13d3cueG4tLW44ajZkczUzbHd3a3JxaHYyOGEud2Vi LXBsYXRmb3JtLnRlc3SCLnd3dzIueG4tLW44ajZkczUzbHd3a3JxaHYyOGEud2Vi +LXBsYXRmb3JtLnRlc3SCLnd3dzEueG4tLW44ajZkczUzbHd3a3JxaHYyOGEud2Vi +LXBsYXRmb3JtLnRlc3SCLnhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLnd3dzEud2Vi +LXBsYXRmb3JtLnRlc3SCLnhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLnd3dzIud2Vi LXBsYXRmb3JtLnRlc3SCL3huLS1sdmUtNmxhZC54bi0tbHZlLTZsYWQubm90LXdl Yi1wbGF0Zm9ybS50ZXN0gjF3d3cueG4tLW44ajZkczUzbHd3a3JxaHYyOGEubm90 LXdlYi1wbGF0Zm9ybS50ZXN0gjF4bi0tbjhqNmRzNTNsd3drcnFodjI4YS53d3cu bm90LXdlYi1wbGF0Zm9ybS50ZXN0gjJ4bi0tbjhqNmRzNTNsd3drcnFodjI4YS53 -d3cyLm5vdC13ZWItcGxhdGZvcm0udGVzdIIyd3d3MS54bi0tbjhqNmRzNTNsd3dr -cnFodjI4YS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCMnd3dzIueG4tLW44ajZkczUz +d3cxLm5vdC13ZWItcGxhdGZvcm0udGVzdIIyd3d3Mi54bi0tbjhqNmRzNTNsd3dr +cnFodjI4YS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCMnd3dzEueG4tLW44ajZkczUz bHd3a3JxaHYyOGEubm90LXdlYi1wbGF0Zm9ybS50ZXN0gjJ4bi0tbjhqNmRzNTNs -d3drcnFodjI4YS53d3cxLm5vdC13ZWItcGxhdGZvcm0udGVzdII2eG4tLW44ajZk +d3drcnFodjI4YS53d3cyLm5vdC13ZWItcGxhdGZvcm0udGVzdII2eG4tLW44ajZk czUzbHd3a3JxaHYyOGEueG4tLWx2ZS02bGFkLndlYi1wbGF0Zm9ybS50ZXN0gjZ4 bi0tbHZlLTZsYWQueG4tLW44ajZkczUzbHd3a3JxaHYyOGEud2ViLXBsYXRmb3Jt LnRlc3SCOnhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLnhuLS1sdmUtNmxhZC5ub3Qt @@ -337,11 +337,11 @@ cnFodjI4YS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCQXhuLS1uOGo2ZHM1M2x3d2ty cWh2MjhhLnhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLndlYi1wbGF0Zm9ybS50ZXN0 gkV4bi0tbjhqNmRzNTNsd3drcnFodjI4YS54bi0tbjhqNmRzNTNsd3drcnFodjI4 -YS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwDQYJKoZIhvcNAQELBQADggEBAHOGp2Ji -xKvvqNucL2gpFBIpsT8abmKBLBm4LsSBGEFPy12fDztkWBVTEN/WiyHRL93PPnn2 -YFn3/jSuAgq0LkSx8VB/Xn2CZgY9+WzL4++GN6I6kYAuuvG4/P6iwwDCwX7y2coD -D75E4WVVTjEsKG2vRiVWzccmg/BTmvXQJU8DSPhzPQtU/D8qHUIe/McHmEW9sxpG -ktJSXqAe0VnvwPXhJ/scOiyJaXvC8mRjM50nUGny0n9Nywltm3oxOAVAZIahZa7g -KMnRywojNqlkccXeHCjH1wXOhzuyQX+MvvBqq968ttIV/hbUXh+D/Su9M0qQclbA -09vdXeld+rSxP8s= +YS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwDQYJKoZIhvcNAQELBQADggEBADVc8bl1 +d4P2NmDg9XR7Lf97e9v4JIQMfvBpKk9kiyRrMGKHpWlGetSipBL4MAR0yvrHUs7+ +61Bbzu0L5Tzd/gyD7ZG8nYHZCThjrWFMdxdltwO2FNmb3xs8lAS8pCOXEcXwY8bv +y/ODP24UZvkBsizQ/cm4uOD70cdPZq+gKf103nUtPNIkq+NhbpzoNfzV/XYIG4Mb +TxAngSBX9/swqkYkgojpSJX+BPr0lZ9iNh/JNCUnwX/HRDYdt0br+ytEf2U0RQ97 +ZUlyC264H2+g8Gnv4BRbfvktaS4PpVSE29tAHBL0cowmx7jXuie3n2O35SDxQkgz +P57oA3Ezv83wshY= -----END CERTIFICATE-----
diff --git a/third_party/wpt_tools/wpt/tools/certs/web-platform.test.key b/third_party/wpt_tools/wpt/tools/certs/web-platform.test.key index b69ed2a..7b5d9ff1 100644 --- a/third_party/wpt_tools/wpt/tools/certs/web-platform.test.key +++ b/third_party/wpt_tools/wpt/tools/certs/web-platform.test.key
@@ -1,28 +1,28 @@ -----BEGIN PRIVATE KEY----- -MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDcwhdziEv2WAkv -K/wpecn5LRAprbWRjaotacXvktoxS0aK2ff34wiV7GrBucxxU81i3LCucnd82dGT -4vHfzTKKab5/+vut1FNoG5BKmGYZCpOo6MZOWAJJ4zXYQBAEeKurSjglzOXWmjSp -AEzM9TqUG66lpoSK58zv7gneDbjDnJhbKYZQurNOm3PLMd0ep3/yxqwqVia1nOn+ -xa4ZoFrWwguWDKx09yhBKEVDHXtAGfZp9EWATquEsqFSoeLqyQDvfe5Hefi4dPmY -32OiJG4ArSKegxyRekQZ8E4x3mnlt3prC6nZFexLG60UOix/AN3RifpHDey8Zq/L -pGsy+NT7AgMBAAECggEBAJrkOA4hAKNs66zEYN49DKCfpKqJrk7dJh1NDMtmr19M -4McF3r1394sx4Unh8ndFhGMsU29i80GPl0P7RRhxYlfJkBc94574zjjKtjgQq/o/ -+JDYGmPXzmtHV31Ona51eIXrwm+LT2x+sBowErLwEVTgA29I4dCQibOCwjuiRxQ/ -mn2A4Q60OllIRCwSE3/uA9+mUpeMp5jgJd+oN3uT58Tme/SRNXxOKgCie8WRUnue -X/cghKYSNmAyDSkbJ0KY4oavb5YRKXNpAt2hNW9JsN0qd3+j6JZ21odhydDbtqSq -mxjPTUFQNFeLVvDTaRYw+zK+I/noZIrlQsS6JPNfXkECgYEA+m3L9jLe2lz0SJmG -NnFuY8rwwYVJm4TLhjYDmdmYbGcYCPo9CHHKhR6ZXrmNzxcXvwaZk8ZTspAZ2Bzw -1AM52mhGZejR7yV5FECh+UKrx/Aud+jm0WhPtwYjixz8IhmGG81orYueux50HUcO -Q/K5Nqo1esBBC+X5Ya2rb3jShGECgYEA4atRn6P5DCj4ug3SSlUNIS3dJxbe3QhB -lTkCtXUQC+p+VIUI0mVk6NgN4drgViKOlhzMKYDMtiVY2XLXQNVPEJ4ngMSC1uzr -tGefMuL/WRpsysxwjN0b+0fDVeXtM16CtXOpqnoYi3XX/R6aIqZ3zVi/ttwEOy6G -TdgnZNcJVtsCgYAW70tIpuwF75FnvLev8L99YC6gaoaNOaIyDmxSAL2W3/IxkEla -pqE3g8/j/vZfyuuf0QjrobQ0nEHhqvTbVdhMilQ4LRRc5H+sPScYXuTAkNyQmsHY -18bFKkjDCsqEjPXdQfiePDUzSdy0ebdyvZ38xaXUMhtC7bLjITacJOKSwQKBgGlJ -1kZmab8rqoicBD5cGkkdre4b9JUp0fd+Zu4klP0KRjDG9Qu89OzSSP/UcBCgBOiy -vOqsRlbBbAfgVd/Q5he5wnKIvQbr+Tjtk9BZKov3EUU5R1Xhn7mIjPGZ2ia6dL+W -HFYGq0b+D2zwhzeddY3gV2pIkszN8ymErTSWQ6w7AoGBAIECBMwE3YL0TGWPdU9A -RV3a5G9slunqhVGQCwvBfWwj6tIplhtOLAp4y400DHbw4Jwi5Z+hDQu9PzMGhhwu -qZLMJZJ4BAUaVHoEcuo1sab25UH6a0pdGf7BgCmjKjPAHtvzMyfwfKpju7ZObpqx -Yet1DMpvmPlX1kZsEh072zBs +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC0NvriO1g8i0L7 +kEIwIDMFeyOvfiHxY8SnFioFfxtIiaVde1lC4DZm8+nC5z4uJa/IFghDpsPh0Mx3 +X8fZ/MK/W8i28hVf8tecB1NGevxZGBeVxDDZt7rMAsPCkRxw03BH2udMIY+8v68K +ErT0G7ryzO8R3UN57RZsA3vtDfkvjaLgAbedjb4A/ETqBk/e+s36587iBPvqxaAm +wFWyqzacRI/agK6EoOkEps8AeJlhHiVzLevF/MQxAxmS9ZQ4aGBrMmhSZEfGSfsk +4bTwFucFrlFmwaNayWBlhrC677pqFZpWJYw5JBY+J+eYE8RiOCQfacD/XkQIktUy +Djrq7GQrAgMBAAECggEBAIwW5SXx3eCKnRIzDNCeZysOkyn7keU0mg0M1LObIBle +LrchiLzM0F1tpDzHR3XWA/Q09E2qmEC08Ayn3xJcQwNAFSHpw6Xnf6WhqCF0vy9+ +4+6fKR5FjabDS2u3I/Ws1250AzMSL8sY8reQ3SuZVtUha4Jmjup7298xQid/okJM +uOemXHg/jBhwoYW8pWG331ezGTOxQExIVE3FTtlwSk5wkDbf7+klT4adwpEDRwpW +JbI/xdq+r7SxGRKA5DNWETePQNQSKEzRXeZ+eh/ipWoNG6mXrppLs0EeaF55XB1b +e1UvNFOCozsiTY2s8DBEg9hlqL+k7nLeaUGUtui5/EECgYEA2ST2jpNJfXcI9oPl +yjg88cbBpaMGp3w1ygQzfnVQ2h05drM6frLqg/1MlpHW5XWxadeNn3PzlnBb6JVo +v522Y/IRcSNLC8enfUTy/Oltem7RTggL4hMMi2yZordJ5AMvWqYCw22SNSMt3m9Z +K4UnbkFpIDYJtetfPeNSkKm1e6ECgYEA1HZUfWwdJUc1mgOBSIzZ9v/SPRdIjz9E +p3JqNIaJaXO/bE91Y1C0L26hX7gNmEtBjsHvQskOUSrDNkyCMGANRepyH3FfrF6V +kuKUK3bSUkUNowL0ztzsk7QE/dRIg8gpLHQzHj9JTdz5qRSoDjJm2ph2rigRmJ9V +2d59O04RrEsCgYEAxTA13n+OSytfrk1UzXCIl57Al6QWFN5NEmkCQiJTC99iIZLc +2dWr9bR+anWByto4BD/E0jo/yCu8qteTSf70dIqMoEtGiSoDxVRpvJZV3srns47H +C8P0rmAunH8J0M+7nvwGomXMUgjiTI6dUVIX3p3z01Z/Nv7JfLAEeG5E6kECgYBm +iXk7Uss6K4TOALULW5byIwLHIw6Mu78ZhRmGogt9TjRrRGnl9ZQQdDcDqCM/hcps +6GHdfIUhXR77fK80Q5cEUCKl1CSVXsyXKCzUUTMuK09qhcm6cFro6e+ixSn+F8Lv +RmFJTsfFAUmodWSp/V8wTnawlHvxiax4Sm1sCsBywwKBgCL3fpUb8bMddwm7dgIT +DWBVdjTbEvvZhJ4Ec0sSTxv3AwUoD70evuphotIucruLPhG0NWrPIQgZfjTKaZ24 +MBjMSWSfu+FH3J+UYaaFQKWp7fu65ioaNIrb/AhlCP68yl30m0vLGrDiZk66XAUx +JPGxuQ/gxnR2RogWiLK9tQ+k -----END PRIVATE KEY-----
diff --git a/third_party/wpt_tools/wpt/tools/certs/web-platform.test.pem b/third_party/wpt_tools/wpt/tools/certs/web-platform.test.pem index e79323d..9f0929a 100644 --- a/third_party/wpt_tools/wpt/tools/certs/web-platform.test.pem +++ b/third_party/wpt_tools/wpt/tools/certs/web-platform.test.pem
@@ -1,228 +1,228 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: 415046 (0x65546) + Serial Number: 978030 (0xeec6e) Signature Algorithm: sha256WithRSAEncryption Issuer: CN=web-platform-tests Validity - Not Before: Jan 12 16:13:28 2021 GMT - Not After : Jan 12 16:13:28 2022 GMT + Not Before: Mar 12 00:27:34 2021 GMT + Not After : Mar 12 00:27:34 2022 GMT Subject: CN=web-platform.test Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public-Key: (2048 bit) Modulus: - 00:dc:c2:17:73:88:4b:f6:58:09:2f:2b:fc:29:79: - c9:f9:2d:10:29:ad:b5:91:8d:aa:2d:69:c5:ef:92: - da:31:4b:46:8a:d9:f7:f7:e3:08:95:ec:6a:c1:b9: - cc:71:53:cd:62:dc:b0:ae:72:77:7c:d9:d1:93:e2: - f1:df:cd:32:8a:69:be:7f:fa:fb:ad:d4:53:68:1b: - 90:4a:98:66:19:0a:93:a8:e8:c6:4e:58:02:49:e3: - 35:d8:40:10:04:78:ab:ab:4a:38:25:cc:e5:d6:9a: - 34:a9:00:4c:cc:f5:3a:94:1b:ae:a5:a6:84:8a:e7: - cc:ef:ee:09:de:0d:b8:c3:9c:98:5b:29:86:50:ba: - b3:4e:9b:73:cb:31:dd:1e:a7:7f:f2:c6:ac:2a:56: - 26:b5:9c:e9:fe:c5:ae:19:a0:5a:d6:c2:0b:96:0c: - ac:74:f7:28:41:28:45:43:1d:7b:40:19:f6:69:f4: - 45:80:4e:ab:84:b2:a1:52:a1:e2:ea:c9:00:ef:7d: - ee:47:79:f8:b8:74:f9:98:df:63:a2:24:6e:00:ad: - 22:9e:83:1c:91:7a:44:19:f0:4e:31:de:69:e5:b7: - 7a:6b:0b:a9:d9:15:ec:4b:1b:ad:14:3a:2c:7f:00: - dd:d1:89:fa:47:0d:ec:bc:66:af:cb:a4:6b:32:f8: - d4:fb + 00:b4:36:fa:e2:3b:58:3c:8b:42:fb:90:42:30:20: + 33:05:7b:23:af:7e:21:f1:63:c4:a7:16:2a:05:7f: + 1b:48:89:a5:5d:7b:59:42:e0:36:66:f3:e9:c2:e7: + 3e:2e:25:af:c8:16:08:43:a6:c3:e1:d0:cc:77:5f: + c7:d9:fc:c2:bf:5b:c8:b6:f2:15:5f:f2:d7:9c:07: + 53:46:7a:fc:59:18:17:95:c4:30:d9:b7:ba:cc:02: + c3:c2:91:1c:70:d3:70:47:da:e7:4c:21:8f:bc:bf: + af:0a:12:b4:f4:1b:ba:f2:cc:ef:11:dd:43:79:ed: + 16:6c:03:7b:ed:0d:f9:2f:8d:a2:e0:01:b7:9d:8d: + be:00:fc:44:ea:06:4f:de:fa:cd:fa:e7:ce:e2:04: + fb:ea:c5:a0:26:c0:55:b2:ab:36:9c:44:8f:da:80: + ae:84:a0:e9:04:a6:cf:00:78:99:61:1e:25:73:2d: + eb:c5:fc:c4:31:03:19:92:f5:94:38:68:60:6b:32: + 68:52:64:47:c6:49:fb:24:e1:b4:f0:16:e7:05:ae: + 51:66:c1:a3:5a:c9:60:65:86:b0:ba:ef:ba:6a:15: + 9a:56:25:8c:39:24:16:3e:27:e7:98:13:c4:62:38: + 24:1f:69:c0:ff:5e:44:08:92:d5:32:0e:3a:ea:ec: + 64:2b Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: CA:FALSE X509v3 Subject Key Identifier: - CD:F1:C8:62:D1:EC:A5:3D:E4:1A:91:70:F1:02:E6:6E:BC:2F:E2:05 + C9:06:D2:C5:1F:09:F4:48:6A:0F:40:E8:29:4B:33:22:A0:8A:FB:33 X509v3 Authority Key Identifier: - keyid:DC:6D:8D:62:DD:54:98:C8:60:17:C2:D3:51:B3:BF:73:5B:5C:90:B9 + keyid:BD:78:38:C2:37:F3:9C:06:A8:EB:3E:AF:5A:A1:88:24:14:85:5B:BE X509v3 Key Usage: Digital Signature, Non Repudiation, Key Encipherment X509v3 Extended Key Usage: TLS Web Server Authentication X509v3 Subject Alternative Name: - DNS:web-platform.test, DNS:op8.web-platform.test, DNS:op7.web-platform.test, DNS:op9.web-platform.test, DNS:op4.web-platform.test, DNS:not-web-platform.test, DNS:op6.web-platform.test, DNS:op3.web-platform.test, DNS:op2.web-platform.test, DNS:op1.web-platform.test, DNS:www.web-platform.test, DNS:op5.web-platform.test, DNS:op88.web-platform.test, DNS:op98.web-platform.test, DNS:op85.web-platform.test, DNS:op89.web-platform.test, DNS:op66.web-platform.test, DNS:op72.web-platform.test, DNS:op24.web-platform.test, DNS:op41.web-platform.test, DNS:op79.web-platform.test, DNS:op91.web-platform.test, DNS:op59.web-platform.test, DNS:op39.web-platform.test, DNS:op60.web-platform.test, DNS:op58.web-platform.test, DNS:op28.web-platform.test, DNS:www1.web-platform.test, DNS:op14.web-platform.test, DNS:op69.web-platform.test, DNS:op40.web-platform.test, DNS:op74.web-platform.test, DNS:op31.web-platform.test, DNS:op18.web-platform.test, DNS:op73.web-platform.test, DNS:op77.web-platform.test, DNS:op12.web-platform.test, DNS:op54.web-platform.test, DNS:op63.web-platform.test, DNS:op71.web-platform.test, DNS:op95.web-platform.test, DNS:op16.web-platform.test, DNS:op36.web-platform.test, DNS:op27.web-platform.test, DNS:op29.web-platform.test, DNS:op94.web-platform.test, DNS:op44.web-platform.test, DNS:op33.web-platform.test, DNS:op84.web-platform.test, DNS:op32.web-platform.test, DNS:op61.web-platform.test, DNS:op70.web-platform.test, DNS:www2.web-platform.test, DNS:op43.web-platform.test, DNS:op78.web-platform.test, DNS:op26.web-platform.test, DNS:op76.web-platform.test, DNS:op52.web-platform.test, DNS:op99.web-platform.test, DNS:op86.web-platform.test, DNS:op46.web-platform.test, DNS:op17.web-platform.test, DNS:op90.web-platform.test, DNS:op93.web-platform.test, DNS:op10.web-platform.test, DNS:op55.web-platform.test, DNS:op47.web-platform.test, DNS:op51.web-platform.test, DNS:op45.web-platform.test, DNS:op80.web-platform.test, DNS:op68.web-platform.test, DNS:op49.web-platform.test, DNS:op57.web-platform.test, DNS:op35.web-platform.test, DNS:op67.web-platform.test, DNS:op92.web-platform.test, DNS:op15.web-platform.test, DNS:op13.web-platform.test, DNS:op75.web-platform.test, DNS:op64.web-platform.test, DNS:op97.web-platform.test, DNS:op37.web-platform.test, DNS:op56.web-platform.test, DNS:op62.web-platform.test, DNS:op82.web-platform.test, DNS:op25.web-platform.test, DNS:op11.web-platform.test, DNS:op50.web-platform.test, DNS:op38.web-platform.test, DNS:op83.web-platform.test, DNS:op81.web-platform.test, DNS:op20.web-platform.test, DNS:op21.web-platform.test, DNS:op23.web-platform.test, DNS:op42.web-platform.test, DNS:op22.web-platform.test, DNS:op65.web-platform.test, DNS:op96.web-platform.test, DNS:op87.web-platform.test, DNS:op19.web-platform.test, DNS:op53.web-platform.test, DNS:op30.web-platform.test, DNS:op48.web-platform.test, DNS:op34.web-platform.test, DNS:op6.not-web-platform.test, DNS:op3.not-web-platform.test, DNS:op2.not-web-platform.test, DNS:op5.not-web-platform.test, DNS:www.not-web-platform.test, DNS:www.www.web-platform.test, DNS:op7.not-web-platform.test, DNS:op4.not-web-platform.test, DNS:op8.not-web-platform.test, DNS:op9.not-web-platform.test, DNS:op1.not-web-platform.test, DNS:op36.not-web-platform.test, DNS:op53.not-web-platform.test, DNS:op50.not-web-platform.test, DNS:op24.not-web-platform.test, DNS:op31.not-web-platform.test, DNS:op95.not-web-platform.test, DNS:op83.not-web-platform.test, DNS:www2.not-web-platform.test, DNS:op73.not-web-platform.test, DNS:op19.not-web-platform.test, DNS:op21.not-web-platform.test, DNS:op81.not-web-platform.test, DNS:op70.not-web-platform.test, DNS:op78.not-web-platform.test, DNS:op40.not-web-platform.test, DNS:op25.not-web-platform.test, DNS:op65.not-web-platform.test, DNS:www.www2.web-platform.test, DNS:op80.not-web-platform.test, DNS:op52.not-web-platform.test, DNS:op68.not-web-platform.test, DNS:op45.not-web-platform.test, DNS:op71.not-web-platform.test, DNS:op72.not-web-platform.test, DNS:op90.not-web-platform.test, DNS:op89.not-web-platform.test, DNS:op49.not-web-platform.test, DNS:op77.not-web-platform.test, DNS:op79.not-web-platform.test, DNS:op82.not-web-platform.test, DNS:www.www1.web-platform.test, DNS:op12.not-web-platform.test, DNS:op39.not-web-platform.test, DNS:op44.not-web-platform.test, DNS:www1.not-web-platform.test, DNS:op58.not-web-platform.test, DNS:op14.not-web-platform.test, DNS:op30.not-web-platform.test, DNS:op62.not-web-platform.test, DNS:op61.not-web-platform.test, DNS:op92.not-web-platform.test, DNS:op29.not-web-platform.test, DNS:op98.not-web-platform.test, DNS:op64.not-web-platform.test, DNS:op26.not-web-platform.test, DNS:op22.not-web-platform.test, DNS:op94.not-web-platform.test, DNS:op38.not-web-platform.test, DNS:op33.not-web-platform.test, DNS:op23.not-web-platform.test, DNS:op57.not-web-platform.test, DNS:op54.not-web-platform.test, DNS:op85.not-web-platform.test, DNS:op46.not-web-platform.test, DNS:op97.not-web-platform.test, DNS:op32.not-web-platform.test, DNS:op60.not-web-platform.test, DNS:op96.not-web-platform.test, DNS:op51.not-web-platform.test, DNS:op41.not-web-platform.test, DNS:op35.not-web-platform.test, DNS:op99.not-web-platform.test, DNS:op42.not-web-platform.test, DNS:op67.not-web-platform.test, DNS:op37.not-web-platform.test, DNS:op48.not-web-platform.test, DNS:op55.not-web-platform.test, DNS:op56.not-web-platform.test, DNS:op84.not-web-platform.test, DNS:op34.not-web-platform.test, DNS:op69.not-web-platform.test, DNS:op11.not-web-platform.test, DNS:op93.not-web-platform.test, DNS:www1.www.web-platform.test, DNS:op86.not-web-platform.test, DNS:op13.not-web-platform.test, DNS:op20.not-web-platform.test, DNS:op76.not-web-platform.test, DNS:op27.not-web-platform.test, DNS:op17.not-web-platform.test, DNS:op75.not-web-platform.test, DNS:op15.not-web-platform.test, DNS:op47.not-web-platform.test, DNS:op18.not-web-platform.test, DNS:op63.not-web-platform.test, DNS:op28.not-web-platform.test, DNS:op43.not-web-platform.test, DNS:op66.not-web-platform.test, DNS:www2.www.web-platform.test, DNS:op91.not-web-platform.test, DNS:op74.not-web-platform.test, DNS:op59.not-web-platform.test, DNS:op88.not-web-platform.test, DNS:op87.not-web-platform.test, DNS:op10.not-web-platform.test, DNS:op16.not-web-platform.test, DNS:www1.www2.web-platform.test, DNS:www2.www2.web-platform.test, DNS:www2.www1.web-platform.test, DNS:www1.www1.web-platform.test, DNS:www.www.not-web-platform.test, DNS:xn--lve-6lad.web-platform.test, DNS:www1.www.not-web-platform.test, DNS:www.www2.not-web-platform.test, DNS:www2.www.not-web-platform.test, DNS:www.www1.not-web-platform.test, DNS:www2.www2.not-web-platform.test, DNS:www2.www1.not-web-platform.test, DNS:www1.www1.not-web-platform.test, DNS:www1.www2.not-web-platform.test, DNS:xn--lve-6lad.www.web-platform.test, DNS:xn--lve-6lad.not-web-platform.test, DNS:www.xn--lve-6lad.web-platform.test, DNS:www2.xn--lve-6lad.web-platform.test, DNS:xn--lve-6lad.www2.web-platform.test, DNS:xn--lve-6lad.www1.web-platform.test, DNS:www1.xn--lve-6lad.web-platform.test, DNS:xn--lve-6lad.www.not-web-platform.test, DNS:www.xn--lve-6lad.not-web-platform.test, DNS:xn--lve-6lad.www1.not-web-platform.test, DNS:www2.xn--lve-6lad.not-web-platform.test, DNS:www1.xn--lve-6lad.not-web-platform.test, DNS:xn--lve-6lad.www2.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:xn--lve-6lad.xn--lve-6lad.web-platform.test, DNS:www.xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.www.web-platform.test, DNS:www1.xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.www2.web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.www1.web-platform.test, DNS:www2.xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:xn--lve-6lad.xn--lve-6lad.not-web-platform.test, DNS:www.xn--n8j6ds53lwwkrqhv28a.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.www.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.www2.not-web-platform.test, DNS:www1.xn--n8j6ds53lwwkrqhv28a.not-web-platform.test, DNS:www2.xn--n8j6ds53lwwkrqhv28a.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.www1.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.xn--lve-6lad.web-platform.test, DNS:xn--lve-6lad.xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.xn--lve-6lad.not-web-platform.test, DNS:xn--lve-6lad.xn--n8j6ds53lwwkrqhv28a.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.xn--n8j6ds53lwwkrqhv28a.not-web-platform.test + DNS:web-platform.test, DNS:not-web-platform.test, DNS:op6.web-platform.test, DNS:www.web-platform.test, DNS:op1.web-platform.test, DNS:op7.web-platform.test, DNS:op8.web-platform.test, DNS:op2.web-platform.test, DNS:op9.web-platform.test, DNS:op5.web-platform.test, DNS:op4.web-platform.test, DNS:op3.web-platform.test, DNS:op40.web-platform.test, DNS:op61.web-platform.test, DNS:op33.web-platform.test, DNS:op79.web-platform.test, DNS:op38.web-platform.test, DNS:op77.web-platform.test, DNS:op43.web-platform.test, DNS:op44.web-platform.test, DNS:op14.web-platform.test, DNS:op49.web-platform.test, DNS:op36.web-platform.test, DNS:op21.web-platform.test, DNS:op60.web-platform.test, DNS:op71.web-platform.test, DNS:op56.web-platform.test, DNS:op94.web-platform.test, DNS:op18.web-platform.test, DNS:op57.web-platform.test, DNS:www2.web-platform.test, DNS:op91.web-platform.test, DNS:op41.web-platform.test, DNS:op47.web-platform.test, DNS:op52.web-platform.test, DNS:op25.web-platform.test, DNS:op16.web-platform.test, DNS:op26.web-platform.test, DNS:op10.web-platform.test, DNS:op69.web-platform.test, DNS:op12.web-platform.test, DNS:op96.web-platform.test, DNS:op74.web-platform.test, DNS:op89.web-platform.test, DNS:op84.web-platform.test, DNS:op37.web-platform.test, DNS:op45.web-platform.test, DNS:op62.web-platform.test, DNS:op86.web-platform.test, DNS:op42.web-platform.test, DNS:op34.web-platform.test, DNS:op48.web-platform.test, DNS:op75.web-platform.test, DNS:op50.web-platform.test, DNS:op22.web-platform.test, DNS:op23.web-platform.test, DNS:op73.web-platform.test, DNS:op20.web-platform.test, DNS:op92.web-platform.test, DNS:op32.web-platform.test, DNS:op82.web-platform.test, DNS:op98.web-platform.test, DNS:op31.web-platform.test, DNS:op30.web-platform.test, DNS:op87.web-platform.test, DNS:op70.web-platform.test, DNS:op64.web-platform.test, DNS:op11.web-platform.test, DNS:op15.web-platform.test, DNS:op85.web-platform.test, DNS:op58.web-platform.test, DNS:www1.web-platform.test, DNS:op83.web-platform.test, DNS:op13.web-platform.test, DNS:op68.web-platform.test, DNS:op99.web-platform.test, DNS:op39.web-platform.test, DNS:op59.web-platform.test, DNS:op95.web-platform.test, DNS:op53.web-platform.test, DNS:op63.web-platform.test, DNS:op54.web-platform.test, DNS:op88.web-platform.test, DNS:op93.web-platform.test, DNS:op28.web-platform.test, DNS:op51.web-platform.test, DNS:op66.web-platform.test, DNS:op19.web-platform.test, DNS:op90.web-platform.test, DNS:op80.web-platform.test, DNS:op67.web-platform.test, DNS:op65.web-platform.test, DNS:op27.web-platform.test, DNS:op76.web-platform.test, DNS:op72.web-platform.test, DNS:op29.web-platform.test, DNS:op97.web-platform.test, DNS:op35.web-platform.test, DNS:op55.web-platform.test, DNS:op46.web-platform.test, DNS:op78.web-platform.test, DNS:op17.web-platform.test, DNS:op24.web-platform.test, DNS:op81.web-platform.test, DNS:op7.not-web-platform.test, DNS:op4.not-web-platform.test, DNS:op8.not-web-platform.test, DNS:www.www.web-platform.test, DNS:op9.not-web-platform.test, DNS:www.not-web-platform.test, DNS:op1.not-web-platform.test, DNS:op3.not-web-platform.test, DNS:op5.not-web-platform.test, DNS:op2.not-web-platform.test, DNS:op6.not-web-platform.test, DNS:op26.not-web-platform.test, DNS:op94.not-web-platform.test, DNS:op75.not-web-platform.test, DNS:op54.not-web-platform.test, DNS:op25.not-web-platform.test, DNS:op28.not-web-platform.test, DNS:op92.not-web-platform.test, DNS:op17.not-web-platform.test, DNS:op95.not-web-platform.test, DNS:op53.not-web-platform.test, DNS:op37.not-web-platform.test, DNS:op41.not-web-platform.test, DNS:op68.not-web-platform.test, DNS:op87.not-web-platform.test, DNS:www1.www.web-platform.test, DNS:op70.not-web-platform.test, DNS:op83.not-web-platform.test, DNS:op91.not-web-platform.test, DNS:op81.not-web-platform.test, DNS:op99.not-web-platform.test, DNS:op48.not-web-platform.test, DNS:op64.not-web-platform.test, DNS:op76.not-web-platform.test, DNS:www.www2.web-platform.test, DNS:op24.not-web-platform.test, DNS:op78.not-web-platform.test, DNS:www.www1.web-platform.test, DNS:op71.not-web-platform.test, DNS:op15.not-web-platform.test, DNS:op72.not-web-platform.test, DNS:op65.not-web-platform.test, DNS:op98.not-web-platform.test, DNS:op49.not-web-platform.test, DNS:op50.not-web-platform.test, DNS:www1.not-web-platform.test, DNS:op47.not-web-platform.test, DNS:op82.not-web-platform.test, DNS:op12.not-web-platform.test, DNS:op27.not-web-platform.test, DNS:op89.not-web-platform.test, DNS:op86.not-web-platform.test, DNS:op52.not-web-platform.test, DNS:op20.not-web-platform.test, DNS:op23.not-web-platform.test, DNS:op63.not-web-platform.test, DNS:op42.not-web-platform.test, DNS:op74.not-web-platform.test, DNS:op62.not-web-platform.test, DNS:op13.not-web-platform.test, DNS:op58.not-web-platform.test, DNS:op66.not-web-platform.test, DNS:www2.not-web-platform.test, DNS:op31.not-web-platform.test, DNS:op39.not-web-platform.test, DNS:op73.not-web-platform.test, DNS:op77.not-web-platform.test, DNS:op55.not-web-platform.test, DNS:op69.not-web-platform.test, DNS:op51.not-web-platform.test, DNS:op96.not-web-platform.test, DNS:op16.not-web-platform.test, DNS:op10.not-web-platform.test, DNS:www2.www.web-platform.test, DNS:op61.not-web-platform.test, DNS:op21.not-web-platform.test, DNS:op80.not-web-platform.test, DNS:op90.not-web-platform.test, DNS:op67.not-web-platform.test, DNS:op43.not-web-platform.test, DNS:op59.not-web-platform.test, DNS:op44.not-web-platform.test, DNS:op14.not-web-platform.test, DNS:op19.not-web-platform.test, DNS:op33.not-web-platform.test, DNS:op22.not-web-platform.test, DNS:op88.not-web-platform.test, DNS:op60.not-web-platform.test, DNS:op40.not-web-platform.test, DNS:op46.not-web-platform.test, DNS:op32.not-web-platform.test, DNS:op56.not-web-platform.test, DNS:op29.not-web-platform.test, DNS:op34.not-web-platform.test, DNS:op97.not-web-platform.test, DNS:op84.not-web-platform.test, DNS:op35.not-web-platform.test, DNS:op93.not-web-platform.test, DNS:op79.not-web-platform.test, DNS:op18.not-web-platform.test, DNS:op57.not-web-platform.test, DNS:op36.not-web-platform.test, DNS:op11.not-web-platform.test, DNS:op38.not-web-platform.test, DNS:op85.not-web-platform.test, DNS:op30.not-web-platform.test, DNS:op45.not-web-platform.test, DNS:www2.www2.web-platform.test, DNS:www1.www1.web-platform.test, DNS:www1.www2.web-platform.test, DNS:www2.www1.web-platform.test, DNS:www.www.not-web-platform.test, DNS:www1.www.not-web-platform.test, DNS:www.www1.not-web-platform.test, DNS:www.www2.not-web-platform.test, DNS:www2.www.not-web-platform.test, DNS:xn--lve-6lad.web-platform.test, DNS:www2.www1.not-web-platform.test, DNS:www1.www1.not-web-platform.test, DNS:www2.www2.not-web-platform.test, DNS:www1.www2.not-web-platform.test, DNS:xn--lve-6lad.www.web-platform.test, DNS:www.xn--lve-6lad.web-platform.test, DNS:xn--lve-6lad.not-web-platform.test, DNS:xn--lve-6lad.www1.web-platform.test, DNS:xn--lve-6lad.www2.web-platform.test, DNS:www2.xn--lve-6lad.web-platform.test, DNS:www1.xn--lve-6lad.web-platform.test, DNS:xn--lve-6lad.www.not-web-platform.test, DNS:www.xn--lve-6lad.not-web-platform.test, DNS:www1.xn--lve-6lad.not-web-platform.test, DNS:xn--lve-6lad.www1.not-web-platform.test, DNS:xn--lve-6lad.www2.not-web-platform.test, DNS:www2.xn--lve-6lad.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:xn--lve-6lad.xn--lve-6lad.web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.www.web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.not-web-platform.test, DNS:www.xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:www2.xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:www1.xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.www1.web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.www2.web-platform.test, DNS:xn--lve-6lad.xn--lve-6lad.not-web-platform.test, DNS:www.xn--n8j6ds53lwwkrqhv28a.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.www.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.www1.not-web-platform.test, DNS:www2.xn--n8j6ds53lwwkrqhv28a.not-web-platform.test, DNS:www1.xn--n8j6ds53lwwkrqhv28a.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.www2.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.xn--lve-6lad.web-platform.test, DNS:xn--lve-6lad.xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.xn--lve-6lad.not-web-platform.test, DNS:xn--lve-6lad.xn--n8j6ds53lwwkrqhv28a.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.xn--n8j6ds53lwwkrqhv28a.not-web-platform.test Signature Algorithm: sha256WithRSAEncryption - 38:a7:ef:eb:55:30:e8:6f:bf:51:a9:eb:52:9a:66:ec:3d:19: - 5d:f4:1d:84:17:c0:f2:26:3e:2b:66:5d:7a:a9:44:86:c3:ba: - d7:f0:9e:e7:b2:b3:05:0c:25:ef:e1:b7:94:8c:44:1c:d2:57: - 4c:30:51:96:29:96:2e:b3:e3:1c:f8:9c:e6:7d:96:14:3f:3f: - 3e:a6:96:4b:01:dc:f2:ed:bf:fc:e3:64:93:49:81:be:c9:dd: - dd:1b:ce:da:72:45:d1:2d:ca:99:cd:d1:7d:f9:17:e1:ee:12: - f4:ed:76:41:ca:6f:a5:5c:72:00:4a:8d:76:c5:2b:b7:18:7b: - ce:e8:ab:76:9a:75:e9:1d:53:9b:75:93:6d:0b:2e:49:3f:bf: - 84:1f:71:be:49:23:ab:2c:f8:a6:a2:28:93:82:04:6c:8e:85: - 22:0e:b6:6d:c5:1e:82:d1:0d:c6:08:9a:86:a1:29:5c:79:53: - d3:ae:d6:c4:33:4b:d2:04:5a:d9:a0:c3:6d:26:ec:e8:35:06: - e7:88:12:03:7c:c5:83:26:b2:b5:32:a3:41:51:b4:94:b0:84: - 0d:4a:05:52:02:29:41:5b:03:04:f0:c3:e5:24:e6:5a:ef:70: - 45:45:58:25:2b:5e:be:7d:ca:73:02:2b:1d:4f:3c:4b:00:f4: - 69:5f:1a:6e + 20:ff:20:71:e5:2d:9f:16:4a:f0:b8:ef:cb:23:63:56:70:bc: + 8c:c6:6b:0e:fa:f5:80:55:5a:f5:75:58:cd:c6:7e:66:6d:11: + 33:ef:fc:a6:6b:5b:98:04:d5:6b:5b:ee:8d:3c:0b:13:d4:f9: + 6b:6e:9b:b5:ad:a6:6e:05:d4:d3:f5:ff:b1:a7:17:46:8e:98: + 7b:89:87:14:a4:c1:fa:26:02:6d:44:c5:c8:c6:5a:d2:9c:e8: + 32:83:ab:77:07:80:c8:80:ab:1f:c6:56:7a:ee:7f:aa:1d:6b: + 37:e1:d5:c1:04:54:e5:30:41:e9:a5:9e:f0:7d:8f:f5:24:60: + f0:24:79:cb:d2:e8:2d:95:33:9d:ca:98:02:11:37:47:97:43: + 13:c2:8a:73:a3:e1:14:cb:86:de:70:c2:b1:d5:5b:d9:6d:f6: + ad:6f:cc:a5:2b:9b:21:8b:d7:78:03:5c:2b:e4:f8:42:c5:7d: + 0d:07:b0:e1:41:ed:ac:26:95:93:db:12:9b:a3:6e:ff:90:62: + 0d:10:ae:d5:f4:87:3d:3a:50:55:c7:c4:e0:48:53:91:e9:22: + eb:97:a6:31:42:2b:3f:24:06:12:5c:92:ff:69:5e:af:00:fd: + e6:ec:2d:66:30:7f:59:db:d1:6f:bc:2d:f4:8b:d3:74:25:e1: + a5:46:79:2d -----BEGIN CERTIFICATE----- -MIIgvDCCH6SgAwIBAgIDBlVGMA0GCSqGSIb3DQEBCwUAMB0xGzAZBgNVBAMMEndl -Yi1wbGF0Zm9ybS10ZXN0czAeFw0yMTAxMTIxNjEzMjhaFw0yMjAxMTIxNjEzMjha +MIIgvDCCH6SgAwIBAgIDDuxuMA0GCSqGSIb3DQEBCwUAMB0xGzAZBgNVBAMMEndl +Yi1wbGF0Zm9ybS10ZXN0czAeFw0yMTAzMTIwMDI3MzRaFw0yMjAzMTIwMDI3MzRa MBwxGjAYBgNVBAMMEXdlYi1wbGF0Zm9ybS50ZXN0MIIBIjANBgkqhkiG9w0BAQEF -AAOCAQ8AMIIBCgKCAQEA3MIXc4hL9lgJLyv8KXnJ+S0QKa21kY2qLWnF75LaMUtG -itn39+MIlexqwbnMcVPNYtywrnJ3fNnRk+Lx380yimm+f/r7rdRTaBuQSphmGQqT -qOjGTlgCSeM12EAQBHirq0o4Jczl1po0qQBMzPU6lBuupaaEiufM7+4J3g24w5yY -WymGULqzTptzyzHdHqd/8sasKlYmtZzp/sWuGaBa1sILlgysdPcoQShFQx17QBn2 -afRFgE6rhLKhUqHi6skA733uR3n4uHT5mN9joiRuAK0inoMckXpEGfBOMd5p5bd6 -awup2RXsSxutFDosfwDd0Yn6Rw3svGavy6RrMvjU+wIDAQABo4IeBDCCHgAwCQYD -VR0TBAIwADAdBgNVHQ4EFgQUzfHIYtHspT3kGpFw8QLmbrwv4gUwHwYDVR0jBBgw -FoAU3G2NYt1UmMhgF8LTUbO/c1tckLkwCwYDVR0PBAQDAgXgMBMGA1UdJQQMMAoG -CCsGAQUFBwMBMIIdjwYDVR0RBIIdhjCCHYKCEXdlYi1wbGF0Zm9ybS50ZXN0ghVv -cDgud2ViLXBsYXRmb3JtLnRlc3SCFW9wNy53ZWItcGxhdGZvcm0udGVzdIIVb3A5 -LndlYi1wbGF0Zm9ybS50ZXN0ghVvcDQud2ViLXBsYXRmb3JtLnRlc3SCFW5vdC13 -ZWItcGxhdGZvcm0udGVzdIIVb3A2LndlYi1wbGF0Zm9ybS50ZXN0ghVvcDMud2Vi -LXBsYXRmb3JtLnRlc3SCFW9wMi53ZWItcGxhdGZvcm0udGVzdIIVb3AxLndlYi1w -bGF0Zm9ybS50ZXN0ghV3d3cud2ViLXBsYXRmb3JtLnRlc3SCFW9wNS53ZWItcGxh -dGZvcm0udGVzdIIWb3A4OC53ZWItcGxhdGZvcm0udGVzdIIWb3A5OC53ZWItcGxh -dGZvcm0udGVzdIIWb3A4NS53ZWItcGxhdGZvcm0udGVzdIIWb3A4OS53ZWItcGxh -dGZvcm0udGVzdIIWb3A2Ni53ZWItcGxhdGZvcm0udGVzdIIWb3A3Mi53ZWItcGxh -dGZvcm0udGVzdIIWb3AyNC53ZWItcGxhdGZvcm0udGVzdIIWb3A0MS53ZWItcGxh -dGZvcm0udGVzdIIWb3A3OS53ZWItcGxhdGZvcm0udGVzdIIWb3A5MS53ZWItcGxh -dGZvcm0udGVzdIIWb3A1OS53ZWItcGxhdGZvcm0udGVzdIIWb3AzOS53ZWItcGxh -dGZvcm0udGVzdIIWb3A2MC53ZWItcGxhdGZvcm0udGVzdIIWb3A1OC53ZWItcGxh -dGZvcm0udGVzdIIWb3AyOC53ZWItcGxhdGZvcm0udGVzdIIWd3d3MS53ZWItcGxh -dGZvcm0udGVzdIIWb3AxNC53ZWItcGxhdGZvcm0udGVzdIIWb3A2OS53ZWItcGxh -dGZvcm0udGVzdIIWb3A0MC53ZWItcGxhdGZvcm0udGVzdIIWb3A3NC53ZWItcGxh -dGZvcm0udGVzdIIWb3AzMS53ZWItcGxhdGZvcm0udGVzdIIWb3AxOC53ZWItcGxh -dGZvcm0udGVzdIIWb3A3My53ZWItcGxhdGZvcm0udGVzdIIWb3A3Ny53ZWItcGxh -dGZvcm0udGVzdIIWb3AxMi53ZWItcGxhdGZvcm0udGVzdIIWb3A1NC53ZWItcGxh -dGZvcm0udGVzdIIWb3A2My53ZWItcGxhdGZvcm0udGVzdIIWb3A3MS53ZWItcGxh -dGZvcm0udGVzdIIWb3A5NS53ZWItcGxhdGZvcm0udGVzdIIWb3AxNi53ZWItcGxh -dGZvcm0udGVzdIIWb3AzNi53ZWItcGxhdGZvcm0udGVzdIIWb3AyNy53ZWItcGxh -dGZvcm0udGVzdIIWb3AyOS53ZWItcGxhdGZvcm0udGVzdIIWb3A5NC53ZWItcGxh -dGZvcm0udGVzdIIWb3A0NC53ZWItcGxhdGZvcm0udGVzdIIWb3AzMy53ZWItcGxh -dGZvcm0udGVzdIIWb3A4NC53ZWItcGxhdGZvcm0udGVzdIIWb3AzMi53ZWItcGxh -dGZvcm0udGVzdIIWb3A2MS53ZWItcGxhdGZvcm0udGVzdIIWb3A3MC53ZWItcGxh -dGZvcm0udGVzdIIWd3d3Mi53ZWItcGxhdGZvcm0udGVzdIIWb3A0My53ZWItcGxh -dGZvcm0udGVzdIIWb3A3OC53ZWItcGxhdGZvcm0udGVzdIIWb3AyNi53ZWItcGxh -dGZvcm0udGVzdIIWb3A3Ni53ZWItcGxhdGZvcm0udGVzdIIWb3A1Mi53ZWItcGxh -dGZvcm0udGVzdIIWb3A5OS53ZWItcGxhdGZvcm0udGVzdIIWb3A4Ni53ZWItcGxh -dGZvcm0udGVzdIIWb3A0Ni53ZWItcGxhdGZvcm0udGVzdIIWb3AxNy53ZWItcGxh -dGZvcm0udGVzdIIWb3A5MC53ZWItcGxhdGZvcm0udGVzdIIWb3A5My53ZWItcGxh -dGZvcm0udGVzdIIWb3AxMC53ZWItcGxhdGZvcm0udGVzdIIWb3A1NS53ZWItcGxh -dGZvcm0udGVzdIIWb3A0Ny53ZWItcGxhdGZvcm0udGVzdIIWb3A1MS53ZWItcGxh -dGZvcm0udGVzdIIWb3A0NS53ZWItcGxhdGZvcm0udGVzdIIWb3A4MC53ZWItcGxh -dGZvcm0udGVzdIIWb3A2OC53ZWItcGxhdGZvcm0udGVzdIIWb3A0OS53ZWItcGxh -dGZvcm0udGVzdIIWb3A1Ny53ZWItcGxhdGZvcm0udGVzdIIWb3AzNS53ZWItcGxh -dGZvcm0udGVzdIIWb3A2Ny53ZWItcGxhdGZvcm0udGVzdIIWb3A5Mi53ZWItcGxh -dGZvcm0udGVzdIIWb3AxNS53ZWItcGxhdGZvcm0udGVzdIIWb3AxMy53ZWItcGxh -dGZvcm0udGVzdIIWb3A3NS53ZWItcGxhdGZvcm0udGVzdIIWb3A2NC53ZWItcGxh -dGZvcm0udGVzdIIWb3A5Ny53ZWItcGxhdGZvcm0udGVzdIIWb3AzNy53ZWItcGxh -dGZvcm0udGVzdIIWb3A1Ni53ZWItcGxhdGZvcm0udGVzdIIWb3A2Mi53ZWItcGxh -dGZvcm0udGVzdIIWb3A4Mi53ZWItcGxhdGZvcm0udGVzdIIWb3AyNS53ZWItcGxh -dGZvcm0udGVzdIIWb3AxMS53ZWItcGxhdGZvcm0udGVzdIIWb3A1MC53ZWItcGxh -dGZvcm0udGVzdIIWb3AzOC53ZWItcGxhdGZvcm0udGVzdIIWb3A4My53ZWItcGxh -dGZvcm0udGVzdIIWb3A4MS53ZWItcGxhdGZvcm0udGVzdIIWb3AyMC53ZWItcGxh -dGZvcm0udGVzdIIWb3AyMS53ZWItcGxhdGZvcm0udGVzdIIWb3AyMy53ZWItcGxh -dGZvcm0udGVzdIIWb3A0Mi53ZWItcGxhdGZvcm0udGVzdIIWb3AyMi53ZWItcGxh -dGZvcm0udGVzdIIWb3A2NS53ZWItcGxhdGZvcm0udGVzdIIWb3A5Ni53ZWItcGxh -dGZvcm0udGVzdIIWb3A4Ny53ZWItcGxhdGZvcm0udGVzdIIWb3AxOS53ZWItcGxh -dGZvcm0udGVzdIIWb3A1My53ZWItcGxhdGZvcm0udGVzdIIWb3AzMC53ZWItcGxh -dGZvcm0udGVzdIIWb3A0OC53ZWItcGxhdGZvcm0udGVzdIIWb3AzNC53ZWItcGxh -dGZvcm0udGVzdIIZb3A2Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIZb3AzLm5vdC13 -ZWItcGxhdGZvcm0udGVzdIIZb3AyLm5vdC13ZWItcGxhdGZvcm0udGVzdIIZb3A1 -Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIZd3d3Lm5vdC13ZWItcGxhdGZvcm0udGVz -dIIZd3d3Lnd3dy53ZWItcGxhdGZvcm0udGVzdIIZb3A3Lm5vdC13ZWItcGxhdGZv -cm0udGVzdIIZb3A0Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIZb3A4Lm5vdC13ZWIt -cGxhdGZvcm0udGVzdIIZb3A5Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIZb3AxLm5v -dC13ZWItcGxhdGZvcm0udGVzdIIab3AzNi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SC -Gm9wNTMubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDUwLm5vdC13ZWItcGxhdGZv -cm0udGVzdIIab3AyNC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMzEubm90LXdl -Yi1wbGF0Zm9ybS50ZXN0ghpvcDk1Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A4 -My5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGnd3dzIubm90LXdlYi1wbGF0Zm9ybS50 -ZXN0ghpvcDczLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3AxOS5ub3Qtd2ViLXBs -YXRmb3JtLnRlc3SCGm9wMjEubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDgxLm5v -dC13ZWItcGxhdGZvcm0udGVzdIIab3A3MC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SC -Gm9wNzgubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDQwLm5vdC13ZWItcGxhdGZv -cm0udGVzdIIab3AyNS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNjUubm90LXdl -Yi1wbGF0Zm9ybS50ZXN0ghp3d3cud3d3Mi53ZWItcGxhdGZvcm0udGVzdIIab3A4 -MC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNTIubm90LXdlYi1wbGF0Zm9ybS50 -ZXN0ghpvcDY4Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A0NS5ub3Qtd2ViLXBs -YXRmb3JtLnRlc3SCGm9wNzEubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDcyLm5v -dC13ZWItcGxhdGZvcm0udGVzdIIab3A5MC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SC -Gm9wODkubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDQ5Lm5vdC13ZWItcGxhdGZv -cm0udGVzdIIab3A3Ny5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNzkubm90LXdl -Yi1wbGF0Zm9ybS50ZXN0ghpvcDgyLm5vdC13ZWItcGxhdGZvcm0udGVzdIIad3d3 -Lnd3dzEud2ViLXBsYXRmb3JtLnRlc3SCGm9wMTIubm90LXdlYi1wbGF0Zm9ybS50 -ZXN0ghpvcDM5Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A0NC5ub3Qtd2ViLXBs -YXRmb3JtLnRlc3SCGnd3dzEubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDU4Lm5v -dC13ZWItcGxhdGZvcm0udGVzdIIab3AxNC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SC -Gm9wMzAubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDYyLm5vdC13ZWItcGxhdGZv -cm0udGVzdIIab3A2MS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wOTIubm90LXdl -Yi1wbGF0Zm9ybS50ZXN0ghpvcDI5Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A5 -OC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNjQubm90LXdlYi1wbGF0Zm9ybS50 -ZXN0ghpvcDI2Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3AyMi5ub3Qtd2ViLXBs -YXRmb3JtLnRlc3SCGm9wOTQubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDM4Lm5v -dC13ZWItcGxhdGZvcm0udGVzdIIab3AzMy5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SC -Gm9wMjMubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDU3Lm5vdC13ZWItcGxhdGZv -cm0udGVzdIIab3A1NC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wODUubm90LXdl -Yi1wbGF0Zm9ybS50ZXN0ghpvcDQ2Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A5 -Ny5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMzIubm90LXdlYi1wbGF0Zm9ybS50 -ZXN0ghpvcDYwLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A5Ni5ub3Qtd2ViLXBs -YXRmb3JtLnRlc3SCGm9wNTEubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDQxLm5v -dC13ZWItcGxhdGZvcm0udGVzdIIab3AzNS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SC -Gm9wOTkubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDQyLm5vdC13ZWItcGxhdGZv -cm0udGVzdIIab3A2Ny5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMzcubm90LXdl -Yi1wbGF0Zm9ybS50ZXN0ghpvcDQ4Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A1 -NS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNTYubm90LXdlYi1wbGF0Zm9ybS50 -ZXN0ghpvcDg0Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3AzNC5ub3Qtd2ViLXBs -YXRmb3JtLnRlc3SCGm9wNjkubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDExLm5v -dC13ZWItcGxhdGZvcm0udGVzdIIab3A5My5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SC -Gnd3dzEud3d3LndlYi1wbGF0Zm9ybS50ZXN0ghpvcDg2Lm5vdC13ZWItcGxhdGZv -cm0udGVzdIIab3AxMy5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMjAubm90LXdl -Yi1wbGF0Zm9ybS50ZXN0ghpvcDc2Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3Ay -Ny5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMTcubm90LXdlYi1wbGF0Zm9ybS50 -ZXN0ghpvcDc1Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3AxNS5ub3Qtd2ViLXBs -YXRmb3JtLnRlc3SCGm9wNDcubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDE4Lm5v -dC13ZWItcGxhdGZvcm0udGVzdIIab3A2My5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SC -Gm9wMjgubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDQzLm5vdC13ZWItcGxhdGZv -cm0udGVzdIIab3A2Ni5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGnd3dzIud3d3Lndl -Yi1wbGF0Zm9ybS50ZXN0ghpvcDkxLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A3 -NC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNTkubm90LXdlYi1wbGF0Zm9ybS50 -ZXN0ghpvcDg4Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A4Ny5ub3Qtd2ViLXBs -YXRmb3JtLnRlc3SCGm9wMTAubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDE2Lm5v -dC13ZWItcGxhdGZvcm0udGVzdIIbd3d3MS53d3cyLndlYi1wbGF0Zm9ybS50ZXN0 -ght3d3cyLnd3dzIud2ViLXBsYXRmb3JtLnRlc3SCG3d3dzIud3d3MS53ZWItcGxh -dGZvcm0udGVzdIIbd3d3MS53d3cxLndlYi1wbGF0Zm9ybS50ZXN0gh13d3cud3d3 -Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIeeG4tLWx2ZS02bGFkLndlYi1wbGF0Zm9y -bS50ZXN0gh53d3cxLnd3dy5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCHnd3dy53d3cy +AAOCAQ8AMIIBCgKCAQEAtDb64jtYPItC+5BCMCAzBXsjr34h8WPEpxYqBX8bSIml +XXtZQuA2ZvPpwuc+LiWvyBYIQ6bD4dDMd1/H2fzCv1vItvIVX/LXnAdTRnr8WRgX +lcQw2be6zALDwpEccNNwR9rnTCGPvL+vChK09Bu68szvEd1Dee0WbAN77Q35L42i +4AG3nY2+APxE6gZP3vrN+ufO4gT76sWgJsBVsqs2nESP2oCuhKDpBKbPAHiZYR4l +cy3rxfzEMQMZkvWUOGhgazJoUmRHxkn7JOG08BbnBa5RZsGjWslgZYawuu+6ahWa +ViWMOSQWPifnmBPEYjgkH2nA/15ECJLVMg466uxkKwIDAQABo4IeBDCCHgAwCQYD +VR0TBAIwADAdBgNVHQ4EFgQUyQbSxR8J9EhqD0DoKUszIqCK+zMwHwYDVR0jBBgw +FoAUvXg4wjfznAao6z6vWqGIJBSFW74wCwYDVR0PBAQDAgXgMBMGA1UdJQQMMAoG +CCsGAQUFBwMBMIIdjwYDVR0RBIIdhjCCHYKCEXdlYi1wbGF0Zm9ybS50ZXN0ghVu +b3Qtd2ViLXBsYXRmb3JtLnRlc3SCFW9wNi53ZWItcGxhdGZvcm0udGVzdIIVd3d3 +LndlYi1wbGF0Zm9ybS50ZXN0ghVvcDEud2ViLXBsYXRmb3JtLnRlc3SCFW9wNy53 +ZWItcGxhdGZvcm0udGVzdIIVb3A4LndlYi1wbGF0Zm9ybS50ZXN0ghVvcDIud2Vi +LXBsYXRmb3JtLnRlc3SCFW9wOS53ZWItcGxhdGZvcm0udGVzdIIVb3A1LndlYi1w +bGF0Zm9ybS50ZXN0ghVvcDQud2ViLXBsYXRmb3JtLnRlc3SCFW9wMy53ZWItcGxh +dGZvcm0udGVzdIIWb3A0MC53ZWItcGxhdGZvcm0udGVzdIIWb3A2MS53ZWItcGxh +dGZvcm0udGVzdIIWb3AzMy53ZWItcGxhdGZvcm0udGVzdIIWb3A3OS53ZWItcGxh +dGZvcm0udGVzdIIWb3AzOC53ZWItcGxhdGZvcm0udGVzdIIWb3A3Ny53ZWItcGxh +dGZvcm0udGVzdIIWb3A0My53ZWItcGxhdGZvcm0udGVzdIIWb3A0NC53ZWItcGxh +dGZvcm0udGVzdIIWb3AxNC53ZWItcGxhdGZvcm0udGVzdIIWb3A0OS53ZWItcGxh +dGZvcm0udGVzdIIWb3AzNi53ZWItcGxhdGZvcm0udGVzdIIWb3AyMS53ZWItcGxh +dGZvcm0udGVzdIIWb3A2MC53ZWItcGxhdGZvcm0udGVzdIIWb3A3MS53ZWItcGxh +dGZvcm0udGVzdIIWb3A1Ni53ZWItcGxhdGZvcm0udGVzdIIWb3A5NC53ZWItcGxh +dGZvcm0udGVzdIIWb3AxOC53ZWItcGxhdGZvcm0udGVzdIIWb3A1Ny53ZWItcGxh +dGZvcm0udGVzdIIWd3d3Mi53ZWItcGxhdGZvcm0udGVzdIIWb3A5MS53ZWItcGxh +dGZvcm0udGVzdIIWb3A0MS53ZWItcGxhdGZvcm0udGVzdIIWb3A0Ny53ZWItcGxh +dGZvcm0udGVzdIIWb3A1Mi53ZWItcGxhdGZvcm0udGVzdIIWb3AyNS53ZWItcGxh +dGZvcm0udGVzdIIWb3AxNi53ZWItcGxhdGZvcm0udGVzdIIWb3AyNi53ZWItcGxh +dGZvcm0udGVzdIIWb3AxMC53ZWItcGxhdGZvcm0udGVzdIIWb3A2OS53ZWItcGxh +dGZvcm0udGVzdIIWb3AxMi53ZWItcGxhdGZvcm0udGVzdIIWb3A5Ni53ZWItcGxh +dGZvcm0udGVzdIIWb3A3NC53ZWItcGxhdGZvcm0udGVzdIIWb3A4OS53ZWItcGxh +dGZvcm0udGVzdIIWb3A4NC53ZWItcGxhdGZvcm0udGVzdIIWb3AzNy53ZWItcGxh +dGZvcm0udGVzdIIWb3A0NS53ZWItcGxhdGZvcm0udGVzdIIWb3A2Mi53ZWItcGxh +dGZvcm0udGVzdIIWb3A4Ni53ZWItcGxhdGZvcm0udGVzdIIWb3A0Mi53ZWItcGxh +dGZvcm0udGVzdIIWb3AzNC53ZWItcGxhdGZvcm0udGVzdIIWb3A0OC53ZWItcGxh +dGZvcm0udGVzdIIWb3A3NS53ZWItcGxhdGZvcm0udGVzdIIWb3A1MC53ZWItcGxh +dGZvcm0udGVzdIIWb3AyMi53ZWItcGxhdGZvcm0udGVzdIIWb3AyMy53ZWItcGxh +dGZvcm0udGVzdIIWb3A3My53ZWItcGxhdGZvcm0udGVzdIIWb3AyMC53ZWItcGxh +dGZvcm0udGVzdIIWb3A5Mi53ZWItcGxhdGZvcm0udGVzdIIWb3AzMi53ZWItcGxh +dGZvcm0udGVzdIIWb3A4Mi53ZWItcGxhdGZvcm0udGVzdIIWb3A5OC53ZWItcGxh +dGZvcm0udGVzdIIWb3AzMS53ZWItcGxhdGZvcm0udGVzdIIWb3AzMC53ZWItcGxh +dGZvcm0udGVzdIIWb3A4Ny53ZWItcGxhdGZvcm0udGVzdIIWb3A3MC53ZWItcGxh +dGZvcm0udGVzdIIWb3A2NC53ZWItcGxhdGZvcm0udGVzdIIWb3AxMS53ZWItcGxh +dGZvcm0udGVzdIIWb3AxNS53ZWItcGxhdGZvcm0udGVzdIIWb3A4NS53ZWItcGxh +dGZvcm0udGVzdIIWb3A1OC53ZWItcGxhdGZvcm0udGVzdIIWd3d3MS53ZWItcGxh +dGZvcm0udGVzdIIWb3A4My53ZWItcGxhdGZvcm0udGVzdIIWb3AxMy53ZWItcGxh +dGZvcm0udGVzdIIWb3A2OC53ZWItcGxhdGZvcm0udGVzdIIWb3A5OS53ZWItcGxh +dGZvcm0udGVzdIIWb3AzOS53ZWItcGxhdGZvcm0udGVzdIIWb3A1OS53ZWItcGxh +dGZvcm0udGVzdIIWb3A5NS53ZWItcGxhdGZvcm0udGVzdIIWb3A1My53ZWItcGxh +dGZvcm0udGVzdIIWb3A2My53ZWItcGxhdGZvcm0udGVzdIIWb3A1NC53ZWItcGxh +dGZvcm0udGVzdIIWb3A4OC53ZWItcGxhdGZvcm0udGVzdIIWb3A5My53ZWItcGxh +dGZvcm0udGVzdIIWb3AyOC53ZWItcGxhdGZvcm0udGVzdIIWb3A1MS53ZWItcGxh +dGZvcm0udGVzdIIWb3A2Ni53ZWItcGxhdGZvcm0udGVzdIIWb3AxOS53ZWItcGxh +dGZvcm0udGVzdIIWb3A5MC53ZWItcGxhdGZvcm0udGVzdIIWb3A4MC53ZWItcGxh +dGZvcm0udGVzdIIWb3A2Ny53ZWItcGxhdGZvcm0udGVzdIIWb3A2NS53ZWItcGxh +dGZvcm0udGVzdIIWb3AyNy53ZWItcGxhdGZvcm0udGVzdIIWb3A3Ni53ZWItcGxh +dGZvcm0udGVzdIIWb3A3Mi53ZWItcGxhdGZvcm0udGVzdIIWb3AyOS53ZWItcGxh +dGZvcm0udGVzdIIWb3A5Ny53ZWItcGxhdGZvcm0udGVzdIIWb3AzNS53ZWItcGxh +dGZvcm0udGVzdIIWb3A1NS53ZWItcGxhdGZvcm0udGVzdIIWb3A0Ni53ZWItcGxh +dGZvcm0udGVzdIIWb3A3OC53ZWItcGxhdGZvcm0udGVzdIIWb3AxNy53ZWItcGxh +dGZvcm0udGVzdIIWb3AyNC53ZWItcGxhdGZvcm0udGVzdIIWb3A4MS53ZWItcGxh +dGZvcm0udGVzdIIZb3A3Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIZb3A0Lm5vdC13 +ZWItcGxhdGZvcm0udGVzdIIZb3A4Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIZd3d3 +Lnd3dy53ZWItcGxhdGZvcm0udGVzdIIZb3A5Lm5vdC13ZWItcGxhdGZvcm0udGVz +dIIZd3d3Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIZb3AxLm5vdC13ZWItcGxhdGZv +cm0udGVzdIIZb3AzLm5vdC13ZWItcGxhdGZvcm0udGVzdIIZb3A1Lm5vdC13ZWIt +cGxhdGZvcm0udGVzdIIZb3AyLm5vdC13ZWItcGxhdGZvcm0udGVzdIIZb3A2Lm5v +dC13ZWItcGxhdGZvcm0udGVzdIIab3AyNi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SC +Gm9wOTQubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDc1Lm5vdC13ZWItcGxhdGZv +cm0udGVzdIIab3A1NC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMjUubm90LXdl +Yi1wbGF0Zm9ybS50ZXN0ghpvcDI4Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A5 +Mi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMTcubm90LXdlYi1wbGF0Zm9ybS50 +ZXN0ghpvcDk1Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A1My5ub3Qtd2ViLXBs +YXRmb3JtLnRlc3SCGm9wMzcubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDQxLm5v +dC13ZWItcGxhdGZvcm0udGVzdIIab3A2OC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SC +Gm9wODcubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghp3d3cxLnd3dy53ZWItcGxhdGZv +cm0udGVzdIIab3A3MC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wODMubm90LXdl +Yi1wbGF0Zm9ybS50ZXN0ghpvcDkxLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A4 +MS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wOTkubm90LXdlYi1wbGF0Zm9ybS50 +ZXN0ghpvcDQ4Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A2NC5ub3Qtd2ViLXBs +YXRmb3JtLnRlc3SCGm9wNzYubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghp3d3cud3d3 +Mi53ZWItcGxhdGZvcm0udGVzdIIab3AyNC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SC +Gm9wNzgubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghp3d3cud3d3MS53ZWItcGxhdGZv +cm0udGVzdIIab3A3MS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMTUubm90LXdl +Yi1wbGF0Zm9ybS50ZXN0ghpvcDcyLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A2 +NS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wOTgubm90LXdlYi1wbGF0Zm9ybS50 +ZXN0ghpvcDQ5Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A1MC5ub3Qtd2ViLXBs +YXRmb3JtLnRlc3SCGnd3dzEubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDQ3Lm5v +dC13ZWItcGxhdGZvcm0udGVzdIIab3A4Mi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SC +Gm9wMTIubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDI3Lm5vdC13ZWItcGxhdGZv +cm0udGVzdIIab3A4OS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wODYubm90LXdl +Yi1wbGF0Zm9ybS50ZXN0ghpvcDUyLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3Ay +MC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMjMubm90LXdlYi1wbGF0Zm9ybS50 +ZXN0ghpvcDYzLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A0Mi5ub3Qtd2ViLXBs +YXRmb3JtLnRlc3SCGm9wNzQubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDYyLm5v +dC13ZWItcGxhdGZvcm0udGVzdIIab3AxMy5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SC +Gm9wNTgubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDY2Lm5vdC13ZWItcGxhdGZv +cm0udGVzdIIad3d3Mi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMzEubm90LXdl +Yi1wbGF0Zm9ybS50ZXN0ghpvcDM5Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A3 +My5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNzcubm90LXdlYi1wbGF0Zm9ybS50 +ZXN0ghpvcDU1Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A2OS5ub3Qtd2ViLXBs +YXRmb3JtLnRlc3SCGm9wNTEubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDk2Lm5v +dC13ZWItcGxhdGZvcm0udGVzdIIab3AxNi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SC +Gm9wMTAubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghp3d3cyLnd3dy53ZWItcGxhdGZv +cm0udGVzdIIab3A2MS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMjEubm90LXdl +Yi1wbGF0Zm9ybS50ZXN0ghpvcDgwLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A5 +MC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNjcubm90LXdlYi1wbGF0Zm9ybS50 +ZXN0ghpvcDQzLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A1OS5ub3Qtd2ViLXBs +YXRmb3JtLnRlc3SCGm9wNDQubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDE0Lm5v +dC13ZWItcGxhdGZvcm0udGVzdIIab3AxOS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SC +Gm9wMzMubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDIyLm5vdC13ZWItcGxhdGZv +cm0udGVzdIIab3A4OC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNjAubm90LXdl +Yi1wbGF0Zm9ybS50ZXN0ghpvcDQwLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A0 +Ni5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMzIubm90LXdlYi1wbGF0Zm9ybS50 +ZXN0ghpvcDU2Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3AyOS5ub3Qtd2ViLXBs +YXRmb3JtLnRlc3SCGm9wMzQubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDk3Lm5v +dC13ZWItcGxhdGZvcm0udGVzdIIab3A4NC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SC +Gm9wMzUubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDkzLm5vdC13ZWItcGxhdGZv +cm0udGVzdIIab3A3OS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMTgubm90LXdl +Yi1wbGF0Zm9ybS50ZXN0ghpvcDU3Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3Az +Ni5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMTEubm90LXdlYi1wbGF0Zm9ybS50 +ZXN0ghpvcDM4Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A4NS5ub3Qtd2ViLXBs +YXRmb3JtLnRlc3SCGm9wMzAubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDQ1Lm5v +dC13ZWItcGxhdGZvcm0udGVzdIIbd3d3Mi53d3cyLndlYi1wbGF0Zm9ybS50ZXN0 +ght3d3cxLnd3dzEud2ViLXBsYXRmb3JtLnRlc3SCG3d3dzEud3d3Mi53ZWItcGxh +dGZvcm0udGVzdIIbd3d3Mi53d3cxLndlYi1wbGF0Zm9ybS50ZXN0gh13d3cud3d3 +Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIed3d3MS53d3cubm90LXdlYi1wbGF0Zm9y +bS50ZXN0gh53d3cud3d3MS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCHnd3dy53d3cy Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIed3d3Mi53d3cubm90LXdlYi1wbGF0Zm9y -bS50ZXN0gh53d3cud3d3MS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCH3d3dzIud3d3 -Mi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCH3d3dzIud3d3MS5ub3Qtd2ViLXBsYXRm -b3JtLnRlc3SCH3d3dzEud3d3MS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCH3d3dzEu +bS50ZXN0gh54bi0tbHZlLTZsYWQud2ViLXBsYXRmb3JtLnRlc3SCH3d3dzIud3d3 +MS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCH3d3dzEud3d3MS5ub3Qtd2ViLXBsYXRm +b3JtLnRlc3SCH3d3dzIud3d3Mi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCH3d3dzEu d3d3Mi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCInhuLS1sdmUtNmxhZC53d3cud2Vi -LXBsYXRmb3JtLnRlc3SCInhuLS1sdmUtNmxhZC5ub3Qtd2ViLXBsYXRmb3JtLnRl -c3SCInd3dy54bi0tbHZlLTZsYWQud2ViLXBsYXRmb3JtLnRlc3SCI3d3dzIueG4t -LWx2ZS02bGFkLndlYi1wbGF0Zm9ybS50ZXN0giN4bi0tbHZlLTZsYWQud3d3Mi53 -ZWItcGxhdGZvcm0udGVzdIIjeG4tLWx2ZS02bGFkLnd3dzEud2ViLXBsYXRmb3Jt +LXBsYXRmb3JtLnRlc3SCInd3dy54bi0tbHZlLTZsYWQud2ViLXBsYXRmb3JtLnRl +c3SCInhuLS1sdmUtNmxhZC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCI3huLS1sdmUt +NmxhZC53d3cxLndlYi1wbGF0Zm9ybS50ZXN0giN4bi0tbHZlLTZsYWQud3d3Mi53 +ZWItcGxhdGZvcm0udGVzdIIjd3d3Mi54bi0tbHZlLTZsYWQud2ViLXBsYXRmb3Jt LnRlc3SCI3d3dzEueG4tLWx2ZS02bGFkLndlYi1wbGF0Zm9ybS50ZXN0giZ4bi0t bHZlLTZsYWQud3d3Lm5vdC13ZWItcGxhdGZvcm0udGVzdIImd3d3LnhuLS1sdmUt -NmxhZC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCJ3huLS1sdmUtNmxhZC53d3cxLm5v -dC13ZWItcGxhdGZvcm0udGVzdIInd3d3Mi54bi0tbHZlLTZsYWQubm90LXdlYi1w -bGF0Zm9ybS50ZXN0gid3d3cxLnhuLS1sdmUtNmxhZC5ub3Qtd2ViLXBsYXRmb3Jt -LnRlc3SCJ3huLS1sdmUtNmxhZC53d3cyLm5vdC13ZWItcGxhdGZvcm0udGVzdIIp +NmxhZC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCJ3d3dzEueG4tLWx2ZS02bGFkLm5v +dC13ZWItcGxhdGZvcm0udGVzdIIneG4tLWx2ZS02bGFkLnd3dzEubm90LXdlYi1w +bGF0Zm9ybS50ZXN0gid4bi0tbHZlLTZsYWQud3d3Mi5ub3Qtd2ViLXBsYXRmb3Jt +LnRlc3SCJ3d3dzIueG4tLWx2ZS02bGFkLm5vdC13ZWItcGxhdGZvcm0udGVzdIIp eG4tLW44ajZkczUzbHd3a3JxaHYyOGEud2ViLXBsYXRmb3JtLnRlc3SCK3huLS1s -dmUtNmxhZC54bi0tbHZlLTZsYWQud2ViLXBsYXRmb3JtLnRlc3SCLXd3dy54bi0t -bjhqNmRzNTNsd3drcnFodjI4YS53ZWItcGxhdGZvcm0udGVzdIIteG4tLW44ajZk -czUzbHd3a3JxaHYyOGEubm90LXdlYi1wbGF0Zm9ybS50ZXN0gi14bi0tbjhqNmRz -NTNsd3drcnFodjI4YS53d3cud2ViLXBsYXRmb3JtLnRlc3SCLnd3dzEueG4tLW44 +dmUtNmxhZC54bi0tbHZlLTZsYWQud2ViLXBsYXRmb3JtLnRlc3SCLXhuLS1uOGo2 +ZHM1M2x3d2tycWh2MjhhLnd3dy53ZWItcGxhdGZvcm0udGVzdIIteG4tLW44ajZk +czUzbHd3a3JxaHYyOGEubm90LXdlYi1wbGF0Zm9ybS50ZXN0gi13d3cueG4tLW44 +ajZkczUzbHd3a3JxaHYyOGEud2ViLXBsYXRmb3JtLnRlc3SCLnd3dzIueG4tLW44 +ajZkczUzbHd3a3JxaHYyOGEud2ViLXBsYXRmb3JtLnRlc3SCLnd3dzEueG4tLW44 ajZkczUzbHd3a3JxaHYyOGEud2ViLXBsYXRmb3JtLnRlc3SCLnhuLS1uOGo2ZHM1 -M2x3d2tycWh2MjhhLnd3dzIud2ViLXBsYXRmb3JtLnRlc3SCLnhuLS1uOGo2ZHM1 -M2x3d2tycWh2MjhhLnd3dzEud2ViLXBsYXRmb3JtLnRlc3SCLnd3dzIueG4tLW44 -ajZkczUzbHd3a3JxaHYyOGEud2ViLXBsYXRmb3JtLnRlc3SCL3huLS1sdmUtNmxh +M2x3d2tycWh2MjhhLnd3dzEud2ViLXBsYXRmb3JtLnRlc3SCLnhuLS1uOGo2ZHM1 +M2x3d2tycWh2MjhhLnd3dzIud2ViLXBsYXRmb3JtLnRlc3SCL3huLS1sdmUtNmxh ZC54bi0tbHZlLTZsYWQubm90LXdlYi1wbGF0Zm9ybS50ZXN0gjF3d3cueG4tLW44 ajZkczUzbHd3a3JxaHYyOGEubm90LXdlYi1wbGF0Zm9ybS50ZXN0gjF4bi0tbjhq NmRzNTNsd3drcnFodjI4YS53d3cubm90LXdlYi1wbGF0Zm9ybS50ZXN0gjJ4bi0t -bjhqNmRzNTNsd3drcnFodjI4YS53d3cyLm5vdC13ZWItcGxhdGZvcm0udGVzdIIy -d3d3MS54bi0tbjhqNmRzNTNsd3drcnFodjI4YS5ub3Qtd2ViLXBsYXRmb3JtLnRl -c3SCMnd3dzIueG4tLW44ajZkczUzbHd3a3JxaHYyOGEubm90LXdlYi1wbGF0Zm9y -bS50ZXN0gjJ4bi0tbjhqNmRzNTNsd3drcnFodjI4YS53d3cxLm5vdC13ZWItcGxh +bjhqNmRzNTNsd3drcnFodjI4YS53d3cxLm5vdC13ZWItcGxhdGZvcm0udGVzdIIy +d3d3Mi54bi0tbjhqNmRzNTNsd3drcnFodjI4YS5ub3Qtd2ViLXBsYXRmb3JtLnRl +c3SCMnd3dzEueG4tLW44ajZkczUzbHd3a3JxaHYyOGEubm90LXdlYi1wbGF0Zm9y +bS50ZXN0gjJ4bi0tbjhqNmRzNTNsd3drcnFodjI4YS53d3cyLm5vdC13ZWItcGxh dGZvcm0udGVzdII2eG4tLW44ajZkczUzbHd3a3JxaHYyOGEueG4tLWx2ZS02bGFk LndlYi1wbGF0Zm9ybS50ZXN0gjZ4bi0tbHZlLTZsYWQueG4tLW44ajZkczUzbHd3 a3JxaHYyOGEud2ViLXBsYXRmb3JtLnRlc3SCOnhuLS1uOGo2ZHM1M2x3d2tycWh2 @@ -231,10 +231,10 @@ c3SCQXhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLnhuLS1uOGo2ZHM1M2x3d2tycWh2 MjhhLndlYi1wbGF0Zm9ybS50ZXN0gkV4bi0tbjhqNmRzNTNsd3drcnFodjI4YS54 bi0tbjhqNmRzNTNsd3drcnFodjI4YS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwDQYJ -KoZIhvcNAQELBQADggEBADin7+tVMOhvv1Gp61KaZuw9GV30HYQXwPImPitmXXqp -RIbDutfwnueyswUMJe/ht5SMRBzSV0wwUZYpli6z4xz4nOZ9lhQ/Pz6mlksB3PLt -v/zjZJNJgb7J3d0bztpyRdEtypnN0X35F+HuEvTtdkHKb6VccgBKjXbFK7cYe87o -q3aadekdU5t1k20LLkk/v4Qfcb5JI6ss+KaiKJOCBGyOhSIOtm3FHoLRDcYImoah -KVx5U9Ou1sQzS9IEWtmgw20m7Og1BueIEgN8xYMmsrUyo0FRtJSwhA1KBVICKUFb -AwTww+Uk5lrvcEVFWCUrXr59ynMCKx1PPEsA9GlfGm4= +KoZIhvcNAQELBQADggEBACD/IHHlLZ8WSvC478sjY1ZwvIzGaw769YBVWvV1WM3G +fmZtETPv/KZrW5gE1Wtb7o08CxPU+Wtum7Wtpm4F1NP1/7GnF0aOmHuJhxSkwfom +Am1ExcjGWtKc6DKDq3cHgMiAqx/GVnruf6odazfh1cEEVOUwQemlnvB9j/UkYPAk +ecvS6C2VM53KmAIRN0eXQxPCinOj4RTLht5wwrHVW9lt9q1vzKUrmyGL13gDXCvk ++ELFfQ0HsOFB7awmlZPbEpujbv+QYg0QrtX0hz06UFXHxOBIU5HpIuuXpjFCKz8k +BhJckv9pXq8A/ebsLWYwf1nb0W+8LfSL03Ql4aVGeS0= -----END CERTIFICATE-----
diff --git a/third_party/wpt_tools/wpt/tools/gitignore/gitignore.py b/third_party/wpt_tools/wpt/tools/gitignore/gitignore.py index dbe83c2..500fe783 100644 --- a/third_party/wpt_tools/wpt/tools/gitignore/gitignore.py +++ b/third_party/wpt_tools/wpt/tools/gitignore/gitignore.py
@@ -1,7 +1,7 @@ import re import os import itertools -from six import ensure_binary, itervalues, iteritems +from six import ensure_binary from collections import defaultdict MYPY = False @@ -194,13 +194,13 @@ rule = cast(Tuple[bool, Pattern[bytes]], rule) if not dir_only: rules_iter = itertools.chain( - itertools.chain(*(iteritems(item) for item in itervalues(self.literals_dir))), - itertools.chain(*(iteritems(item) for item in itervalues(self.literals_file))), + itertools.chain(*(item.items() for item in self.literals_dir.values())), + itertools.chain(*(item.items() for item in self.literals_file.values())), self.patterns_dir, self.patterns_file) # type: Iterable[Tuple[Any, List[Tuple[bool, Pattern[bytes]]]]] else: rules_iter = itertools.chain( - itertools.chain(*(iteritems(item) for item in itervalues(self.literals_dir))), + itertools.chain(*(item.items() for item in self.literals_dir.values())), self.patterns_dir) for rules in rules_iter:
diff --git a/third_party/wpt_tools/wpt/tools/lint/lint.py b/third_party/wpt_tools/wpt/tools/lint/lint.py index f936055..d8fb9fc 100644 --- a/third_party/wpt_tools/wpt/tools/lint/lint.py +++ b/third_party/wpt_tools/wpt/tools/lint/lint.py
@@ -14,6 +14,7 @@ import tempfile from collections import defaultdict +from urllib.parse import urlsplit, urljoin from . import fnmatch from . import rules @@ -24,9 +25,7 @@ from ..manifest.vcs import walk from ..manifest.sourcefile import SourceFile, js_meta_re, python_meta_re, space_chars, get_any_variants -from six import binary_type, ensure_binary, ensure_text, iteritems, itervalues, with_metaclass -from six.moves import range -from six.moves.urllib.parse import urlsplit, urljoin +from six import ensure_binary, ensure_text MYPY = False if MYPY: @@ -325,7 +324,7 @@ errors = [] - for name, colliding in iteritems(test_files): + for name, colliding in test_files.items(): if len(colliding) > 1: if not _all_files_equal([os.path.join(repo_root, x) for x in colliding]): # Only compute by_spec if there are prima-facie collisions because of cost @@ -342,7 +341,7 @@ continue by_spec[spec].add(path) - for spec, spec_paths in iteritems(by_spec): + for spec, spec_paths in by_spec.items(): if not _all_files_equal([os.path.join(repo_root, x) for x in spec_paths]): for x in spec_paths: context1 = (name, spec, ", ".join(sorted(spec_paths))) @@ -351,7 +350,7 @@ for rule_class, d in [(rules.CSSCollidingRefName, ref_files), (rules.CSSCollidingSupportName, support_files)]: - for name, colliding in iteritems(d): + for name, colliding in d.items(): if len(colliding) > 1: if not _all_files_equal([os.path.join(repo_root, x) for x in colliding]): context2 = (name, ", ".join(sorted(colliding))) @@ -451,7 +450,7 @@ # which explains how to fix it correctly and shouldn't be skipped. if error_type in data and error_type != "IGNORED PATH": wl_files = data[error_type] - for file_match, allowed_lines in iteritems(wl_files): + for file_match, allowed_lines in wl_files.items(): if None in allowed_lines or line in allowed_lines: if fnmatch.fnmatchcase(normpath, file_match): skipped[i] = True @@ -668,7 +667,7 @@ return errors -class ASTCheck(with_metaclass(abc.ABCMeta)): +class ASTCheck(metaclass=abc.ABCMeta): @abc.abstractproperty def rule(self): # type: () -> Type[rules.Rule] @@ -741,7 +740,7 @@ done = False errors = [] for idx, line in enumerate(f): - assert isinstance(line, binary_type), line + assert isinstance(line, bytes), line m = meta_re.match(line) if m: @@ -975,7 +974,7 @@ def main(**kwargs_str): # type: (**Any) -> int - kwargs = {ensure_text(key): value for key, value in iteritems(kwargs_str)} + kwargs = {ensure_text(key): value for key, value in kwargs_str.items()} assert logger is not None if kwargs.get("json") and kwargs.get("markdown"): @@ -1103,7 +1102,7 @@ if error_count and github_checks_outputter: github_checks_outputter.output("```") - return sum(itervalues(error_count)) + return sum(error_count.values()) path_lints = [check_file_type, check_path_length, check_worker_collision, check_ahem_copy,
diff --git a/third_party/wpt_tools/wpt/tools/lint/rules.py b/third_party/wpt_tools/wpt/tools/lint/rules.py index b389e3d..e9bb30b5 100644 --- a/third_party/wpt_tools/wpt/tools/lint/rules.py +++ b/third_party/wpt_tools/wpt/tools/lint/rules.py
@@ -5,8 +5,6 @@ import os import re -import six - MYPY = False if MYPY: # MYPY is set to True when run under Mypy. @@ -19,7 +17,7 @@ return inspect.cleandoc(str(text)).replace("\n", " ") -class Rule(six.with_metaclass(abc.ABCMeta)): +class Rule(metaclass=abc.ABCMeta): @abc.abstractproperty def name(self): # type: () -> Text @@ -367,7 +365,7 @@ to_fix = "rename directory to be called 'tentative'" -class Regexp(six.with_metaclass(abc.ABCMeta)): +class Regexp(metaclass=abc.ABCMeta): @abc.abstractproperty def pattern(self): # type: () -> bytes
diff --git a/third_party/wpt_tools/wpt/tools/localpaths.py b/third_party/wpt_tools/wpt/tools/localpaths.py index a79acb82..1cb6f5b3 100644 --- a/third_party/wpt_tools/wpt/tools/localpaths.py +++ b/third_party/wpt_tools/wpt/tools/localpaths.py
@@ -18,6 +18,7 @@ sys.path.insert(0, os.path.join(here, "third_party", "py")) sys.path.insert(0, os.path.join(here, "third_party", "pytest")) sys.path.insert(0, os.path.join(here, "third_party", "pytest", "src")) +sys.path.insert(0, os.path.join(here, "third_party", "pytest-asyncio")) sys.path.insert(0, os.path.join(here, "third_party", "six")) sys.path.insert(0, os.path.join(here, "third_party", "webencodings")) sys.path.insert(0, os.path.join(here, "third_party", "h2")) @@ -25,6 +26,8 @@ sys.path.insert(0, os.path.join(here, "third_party", "hyperframe")) sys.path.insert(0, os.path.join(here, "third_party", "certifi")) sys.path.insert(0, os.path.join(here, "third_party", "hyper")) +sys.path.insert(0, os.path.join(here, "third_party", "websockets", "src")) +sys.path.insert(0, os.path.join(here, "third_party", "iniconfig", "src")) if sys.version_info < (3, 8): sys.path.insert(0, os.path.join(here, "third_party", "importlib_metadata")) sys.path.insert(0, os.path.join(here, "webdriver"))
diff --git a/third_party/wpt_tools/wpt/tools/manifest/XMLParser.py b/third_party/wpt_tools/wpt/tools/manifest/XMLParser.py index 80aa3b5..45a8a54 100644 --- a/third_party/wpt_tools/wpt/tools/manifest/XMLParser.py +++ b/third_party/wpt_tools/wpt/tools/manifest/XMLParser.py
@@ -6,8 +6,6 @@ from xml.parsers import expat import xml.etree.ElementTree as etree # noqa: N813 -from six import text_type - MYPY = False if MYPY: # MYPY is set to True when run under Mypy. @@ -83,7 +81,7 @@ def _start(self, tag, attrib_in): # type: (Text, List[str]) -> etree.Element - assert isinstance(tag, text_type) + assert isinstance(tag, str) self._fed_data = None tag = _fixname(tag) attrib = OrderedDict() # type: Dict[Union[bytes, Text], Union[bytes, Text]]
diff --git a/third_party/wpt_tools/wpt/tools/manifest/download.py b/third_party/wpt_tools/wpt/tools/manifest/download.py index 9d76318..88d478f 100644 --- a/third_party/wpt_tools/wpt/tools/manifest/download.py +++ b/third_party/wpt_tools/wpt/tools/manifest/download.py
@@ -7,8 +7,7 @@ import io import os from datetime import datetime, timedelta - -from six.moves.urllib.request import urlopen +from urllib.request import urlopen try: import zstandard
diff --git a/third_party/wpt_tools/wpt/tools/manifest/item.py b/third_party/wpt_tools/wpt/tools/manifest/item.py index 857c8485..4b973d5 100644 --- a/third_party/wpt_tools/wpt/tools/manifest/item.py +++ b/third_party/wpt_tools/wpt/tools/manifest/item.py
@@ -1,7 +1,6 @@ import os.path from inspect import isabstract -from six import iteritems, with_metaclass -from six.moves.urllib.parse import urljoin, urlparse, parse_qs +from urllib.parse import urljoin, urlparse, parse_qs from abc import ABCMeta, abstractproperty from .utils import to_os_path @@ -42,7 +41,7 @@ return rv # type: ignore -class ManifestItem(with_metaclass(ManifestItemMeta)): +class ManifestItem(metaclass=ManifestItemMeta): __slots__ = ("_tests_root", "path") def __init__(self, tests_root, path): @@ -289,7 +288,7 @@ if self.dpi is not None: extras["dpi"] = self.dpi if self.fuzzy: - extras["fuzzy"] = list(iteritems(self.fuzzy)) + extras["fuzzy"] = list(self.fuzzy.items()) return rv @classmethod
diff --git a/third_party/wpt_tools/wpt/tools/manifest/jsonlib.py b/third_party/wpt_tools/wpt/tools/manifest/jsonlib.py index e7f07c3..49eaf02 100644 --- a/third_party/wpt_tools/wpt/tools/manifest/jsonlib.py +++ b/third_party/wpt_tools/wpt/tools/manifest/jsonlib.py
@@ -1,8 +1,6 @@ import re import json -from six import PY3 - MYPY = False if MYPY: @@ -49,11 +47,9 @@ 'ensure_ascii': False, 'escape_forward_slashes': False, 'indent': 1, + 'reject_bytes': True, } # type: Dict[str, Any] -if PY3: - _ujson_dump_local_kwargs['reject_bytes'] = True - _json_dump_local_kwargs = { 'ensure_ascii': False, @@ -99,10 +95,9 @@ _ujson_dump_dist_kwargs = { 'sort_keys': True, 'indent': 1, + 'reject_bytes': True, } # type: Dict[str, Any] -if PY3: - _ujson_dump_dist_kwargs['reject_bytes'] = True _json_dump_dist_kwargs = { 'sort_keys': True,
diff --git a/third_party/wpt_tools/wpt/tools/manifest/manifest.py b/third_party/wpt_tools/wpt/tools/manifest/manifest.py index 123f045..9f1e902d 100644 --- a/third_party/wpt_tools/wpt/tools/manifest/manifest.py +++ b/third_party/wpt_tools/wpt/tools/manifest/manifest.py
@@ -1,17 +1,10 @@ import io -import itertools import os import sys from atomicwrites import atomic_write from copy import deepcopy from multiprocessing import Pool, cpu_count -from six import ( - PY3, - ensure_text, - iteritems, - itervalues, - string_types, -) +from six import ensure_text from . import jsonlib from . import vcs @@ -93,7 +86,7 @@ """Dictionary subclass containing a TypeData instance for each test type, keyed by type name""" self.initialized = False # type: bool - for key, value in iteritems(item_classes): + for key, value in item_classes.items(): self[key] = TypeData(manifest, value) self.initialized = True self.json_obj = None # type: None @@ -109,7 +102,7 @@ """Get a list of all paths containing test items without actually constructing all the items""" rv = set() # type: Set[Text] - for item_data in itervalues(self): + for item_data in self.values(): for item in item_data: rv.add(os.path.sep.join(item)) return rv @@ -117,7 +110,7 @@ def type_by_path(self): # type: () -> Dict[Tuple[Text, ...], Text] rv = {} - for item_type, item_data in iteritems(self): + for item_type, item_data in self.items(): for item in item_data: rv[item] = item_type return rv @@ -159,7 +152,7 @@ tpath_len = len(tpath) for type_tests in self._data.values(): - for path, tests in iteritems(type_tests): + for path, tests in type_tests.items(): if path[:tpath_len] == tpath: for test in tests: yield test @@ -253,10 +246,8 @@ to_update, chunksize=chunksize ) # type: Iterator[Tuple[Tuple[Text, ...], Text, Set[ManifestItem], Text]] - elif PY3: - results = map(compute_manifest_items, to_update) else: - results = itertools.imap(compute_manifest_items, to_update) + results = map(compute_manifest_items, to_update) for result in results: rel_path_parts, new_type, manifest_items, file_hash = result @@ -271,7 +262,7 @@ if remaining_manifest_paths: changed = True for rel_path_parts in remaining_manifest_paths: - for test_data in itervalues(data): + for test_data in data.values(): if rel_path_parts in test_data: del test_data[rel_path_parts] @@ -291,7 +282,7 @@ """ out_items = { test_type: type_paths.to_json() - for test_type, type_paths in iteritems(self._data) if type_paths + for test_type, type_paths in self._data.items() if type_paths } if caller_owns_obj: @@ -325,7 +316,7 @@ if not hasattr(obj, "items"): raise ManifestError - for test_type, type_paths in iteritems(obj["items"]): + for test_type, type_paths in obj["items"].items(): if test_type not in item_classes: raise ManifestError @@ -358,12 +349,12 @@ allow_cached=True # type: bool ): # type: (...) -> Optional[Manifest] - manifest_path = (manifest if isinstance(manifest, string_types) + manifest_path = (manifest if isinstance(manifest, str) else manifest.name) if allow_cached and manifest_path in __load_cache: return __load_cache[manifest_path] - if isinstance(manifest, string_types): + if isinstance(manifest, str): if os.path.exists(manifest): logger.debug("Opening manifest at %s" % manifest) else:
diff --git a/third_party/wpt_tools/wpt/tools/manifest/sourcefile.py b/third_party/wpt_tools/wpt/tools/manifest/sourcefile.py index ce81c625..34e679e 100644 --- a/third_party/wpt_tools/wpt/tools/manifest/sourcefile.py +++ b/third_party/wpt_tools/wpt/tools/manifest/sourcefile.py
@@ -3,8 +3,7 @@ import os from collections import deque from io import BytesIO -from six import binary_type, iteritems, text_type -from six.moves.urllib.parse import urljoin +from urllib.parse import urljoin from fnmatch import fnmatch MYPY = False @@ -74,7 +73,7 @@ value. """ for line in f: - assert isinstance(line, binary_type), line + assert isinstance(line, bytes), line m = regexp.match(line) if not m: break @@ -85,9 +84,13 @@ _any_variants = { "window": {"suffix": ".any.html"}, "serviceworker": {"force_https": True}, + "serviceworker-module": {"force_https": True}, "sharedworker": {}, + "sharedworker-module": {}, "dedicatedworker": {"suffix": ".any.worker.html"}, + "dedicatedworker-module": {"suffix": ".any.worker-module.html"}, "worker": {"longhand": {"dedicatedworker", "sharedworker", "serviceworker"}}, + "worker-module": {}, "jsshell": {"suffix": ".any.js"}, } # type: Dict[Text, Dict[Text, Any]] @@ -97,7 +100,7 @@ """ Returns a set of variants (strings) defined by the given keyword. """ - assert isinstance(item, text_type), item + assert isinstance(item, str), item variant = _any_variants.get(item, None) if variant is None: @@ -119,7 +122,7 @@ """ Returns a set of variants (strings) defined by a comma-separated value. """ - assert isinstance(value, text_type), value + assert isinstance(value, str), value if value == "": return get_default_any_variants() @@ -138,7 +141,7 @@ variant is intended to run in a JS shell, for the variants defined by the given comma-separated value. """ - assert isinstance(value, text_type), value + assert isinstance(value, str), value rv = set() @@ -243,7 +246,7 @@ if "__cached_properties__" in rv: cached_properties = rv["__cached_properties__"] - rv = {key:value for key, value in iteritems(rv) if key not in cached_properties} + rv = {key:value for key, value in rv.items() if key not in cached_properties} del rv["__cached_properties__"] return rv @@ -304,7 +307,7 @@ content = f.read() data = b"".join((b"blob ", b"%d" % len(content), b"\0", content)) - self._hash = text_type(hashlib.sha1(data).hexdigest()) + self._hash = str(hashlib.sha1(data).hexdigest()) return self._hash
diff --git a/third_party/wpt_tools/wpt/tools/manifest/testpaths.py b/third_party/wpt_tools/wpt/tools/manifest/testpaths.py index 2197792c..6902f0c 100644 --- a/third_party/wpt_tools/wpt/tools/manifest/testpaths.py +++ b/third_party/wpt_tools/wpt/tools/manifest/testpaths.py
@@ -3,8 +3,6 @@ import os from collections import defaultdict -from six import iteritems - from .manifest import load_and_update, Manifest from .log import get_logger @@ -102,7 +100,7 @@ if as_json: print(json.dumps(path_id_map)) else: - for path, test_ids in sorted(iteritems(path_id_map)): + for path, test_ids in sorted(path_id_map.items()): print(path) for test_id in sorted(test_ids): print(" " + test_id)
diff --git a/third_party/wpt_tools/wpt/tools/manifest/typedata.py b/third_party/wpt_tools/wpt/tools/manifest/typedata.py index 01bb827..174008e 100644 --- a/third_party/wpt_tools/wpt/tools/manifest/typedata.py +++ b/third_party/wpt_tools/wpt/tools/manifest/typedata.py
@@ -1,5 +1,4 @@ -from six import itervalues, iteritems -from six.moves.collections_abc import MutableMapping +from collections.abc import MutableMapping MYPY = False @@ -181,7 +180,7 @@ if isinstance(v, set): count += 1 else: - stack.extend(itervalues(v)) + stack.extend(v.values()) stack = [self._json_data] while stack: @@ -189,7 +188,7 @@ if isinstance(v, list): count += 1 else: - stack.extend(itervalues(v)) + stack.extend(v.values()) return count @@ -270,7 +269,7 @@ stack = [(self._data, json_rv, tuple())] # type: List[Tuple[Dict[Text, Any], Dict[Text, Any], Tuple[Text, ...]]] while stack: data_node, json_node, par_full_key = stack.pop() - for k, v in iteritems(data_node): + for k, v in data_node.items(): full_key = par_full_key + (k,) if isinstance(v, set): assert k not in json_node
diff --git a/third_party/wpt_tools/wpt/tools/manifest/vcs.py b/third_party/wpt_tools/wpt/tools/manifest/vcs.py index 4f3bfda..65ba308 100644 --- a/third_party/wpt_tools/wpt/tools/manifest/vcs.py +++ b/third_party/wpt_tools/wpt/tools/manifest/vcs.py
@@ -2,9 +2,7 @@ import os import stat from collections import deque - -from six import with_metaclass, PY2 -from six.moves.collections_abc import MutableMapping +from collections.abc import MutableMapping from . import jsonlib from .utils import git @@ -19,10 +17,7 @@ # MYPY is set to True when run under Mypy. from typing import Dict, Optional, List, Set, Text, Iterable, Any, Tuple, Iterator from .manifest import Manifest # cyclic import under MYPY guard - if PY2: - stat_result = Any - else: - stat_result = os.stat_result + stat_result = os.stat_result GitIgnoreCacheType = MutableMapping[bytes, bool] else: @@ -132,7 +127,7 @@ cache.dump() -class CacheFile(with_metaclass(abc.ABCMeta)): +class CacheFile(metaclass=abc.ABCMeta): def __init__(self, cache_root, tests_root, rebuild=False): # type: (Text, Text, bool) -> None self.tests_root = tests_root
diff --git a/third_party/wpt_tools/wpt/tools/quic/commands.json b/third_party/wpt_tools/wpt/tools/quic/commands.json index d4e3ce8..4496f48 100644 --- a/third_party/wpt_tools/wpt/tools/quic/commands.json +++ b/third_party/wpt_tools/wpt/tools/quic/commands.json
@@ -3,7 +3,6 @@ "path": "serve.py", "script": "run", "parser": "get_parser", - "py3only": true, "help": "Start the QUIC server for WebTransport", "virtualenv": true, "requirements": [
diff --git a/third_party/wpt_tools/wpt/tools/serve/serve.py b/third_party/wpt_tools/wpt/tools/serve/serve.py index f09fe24..8e1aaa8 100644 --- a/third_party/wpt_tools/wpt/tools/serve/serve.py +++ b/third_party/wpt_tools/wpt/tools/serve/serve.py
@@ -4,6 +4,7 @@ import abc import argparse +import importlib import json import logging import multiprocessing @@ -16,13 +17,12 @@ import threading import time import traceback -from six.moves import urllib +import urllib import uuid from collections import defaultdict, OrderedDict from itertools import chain, product from localpaths import repo_root -from six.moves import reload_module from manifest.sourcefile import read_script_metadata, js_meta_re, parse_variants from wptserve import server as wptserve, handlers @@ -227,6 +227,22 @@ """ +class WorkerModulesHandler(HtmlWrapperHandler): + global_type = "dedicatedworker-module" + path_replace = [(".any.worker-module.html", ".any.js", ".any.worker-module.js"), + (".worker.html", ".worker.js")] + wrapper = """<!doctype html> +<meta charset=utf-8> +%(meta)s +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +fetch_tests_from_worker(new Worker("%(path)s%(query)s", { type: "module" })); +</script> +""" + + class WindowHandler(HtmlWrapperHandler): path_replace = [(".window.html", ".window.js")] wrapper = """<!doctype html> @@ -275,6 +291,21 @@ """ +class SharedWorkerModulesHandler(HtmlWrapperHandler): + global_type = "sharedworker-module" + path_replace = [(".any.sharedworker-module.html", ".any.js", ".any.worker-module.js")] + wrapper = """<!doctype html> +<meta charset=utf-8> +%(meta)s +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +fetch_tests_from_worker(new SharedWorker("%(path)s%(query)s", { type: "module" })); +</script> +""" + + class ServiceWorkersHandler(HtmlWrapperHandler): global_type = "serviceworker" path_replace = [(".any.serviceworker.html", ".any.js", ".any.worker.js")] @@ -296,8 +327,54 @@ """ -class AnyWorkerHandler(WrapperHandler): +class ServiceWorkerModulesHandler(HtmlWrapperHandler): + global_type = "serviceworker-module" + path_replace = [(".any.serviceworker-module.html", + ".any.js", ".any.worker-module.js")] + wrapper = """<!doctype html> +<meta charset=utf-8> +%(meta)s +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +(async function() { + const scope = 'does/not/exist'; + let reg = await navigator.serviceWorker.getRegistration(scope); + if (reg) await reg.unregister(); + reg = await navigator.serviceWorker.register( + "%(path)s%(query)s", + { scope, type: 'module' }, + ); + fetch_tests_from_worker(reg.installing); +})(); +</script> +""" + + +class BaseWorkerHandler(WrapperHandler): headers = [('Content-Type', 'text/javascript')] + + def _meta_replacement(self, key, value): + return None + + @abc.abstractmethod + def _create_script_import(self, attribute): + # Take attribute (a string URL to a JS script) and return JS source to import the script + # into the worker. + pass + + def _script_replacement(self, key, value): + if key == "script": + attribute = value.replace("\\", "\\\\").replace('"', '\\"') + return self._create_script_import(attribute) + if key == "title": + value = value.replace("\\", "\\\\").replace('"', '\\"') + return 'self.META_TITLE = "%s";' % value + return None + + +class ClassicWorkerHandler(BaseWorkerHandler): path_replace = [(".any.worker.js", ".any.js")] wrapper = """%(meta)s self.GLOBAL = { @@ -310,17 +387,25 @@ done(); """ - def _meta_replacement(self, key, value): - return None + def _create_script_import(self, attribute): + return 'importScripts("%s")' % attribute - def _script_replacement(self, key, value): - if key == "script": - attribute = value.replace("\\", "\\\\").replace('"', '\\"') - return 'importScripts("%s")' % attribute - if key == "title": - value = value.replace("\\", "\\\\").replace('"', '\\"') - return 'self.META_TITLE = "%s";' % value - return None + +class ModuleWorkerHandler(BaseWorkerHandler): + path_replace = [(".any.worker-module.js", ".any.js")] + wrapper = """%(meta)s +self.GLOBAL = { + isWindow: function() { return false; }, + isWorker: function() { return true; }, +}; +import "/resources/testharness.js"; +%(script)s +import "%(path)s"; +done(); +""" + + def _create_script_import(self, attribute): + return 'import "%s";' % attribute rewrites = [("GET", "/resources/WebIDLParser.js", "/resources/webidl2/lib/webidl2.js")] @@ -368,11 +453,15 @@ routes = [ ("GET", "*.worker.html", WorkersHandler), + ("GET", "*.worker-module.html", WorkerModulesHandler), ("GET", "*.window.html", WindowHandler), ("GET", "*.any.html", AnyHtmlHandler), ("GET", "*.any.sharedworker.html", SharedWorkersHandler), + ("GET", "*.any.sharedworker-module.html", SharedWorkerModulesHandler), ("GET", "*.any.serviceworker.html", ServiceWorkersHandler), - ("GET", "*.any.worker.js", AnyWorkerHandler), + ("GET", "*.any.serviceworker-module.html", ServiceWorkerModulesHandler), + ("GET", "*.any.worker.js", ClassicWorkerHandler), + ("GET", "*.any.worker-module.js", ModuleWorkerHandler), ("GET", "*.asis", handlers.AsIsHandler), ("GET", "/.well-known/origin-policy", handlers.PythonScriptHandler), ("*", "*.py", handlers.PythonScriptHandler), @@ -697,7 +786,7 @@ def start_ws_server(host, port, paths, routes, bind_address, config, **kwargs): # Ensure that when we start this in a new process we have the global lock # in the logging module unlocked - reload_module(logging) + importlib.reload(logging) release_mozlog_lock() try: return WebSocketDaemon(host, @@ -713,7 +802,7 @@ def start_wss_server(host, port, paths, routes, bind_address, config, **kwargs): # Ensure that when we start this in a new process we have the global lock # in the logging module unlocked - reload_module(logging) + importlib.reload(logging) release_mozlog_lock() try: return WebSocketDaemon(host, @@ -771,7 +860,7 @@ def start_quic_transport_server(host, port, paths, routes, bind_address, config, **kwargs): # Ensure that when we start this in a new process we have the global lock # in the logging module unlocked - reload_module(logging) + importlib.reload(logging) release_mozlog_lock() try: return QuicTransportDaemon(host,
diff --git a/third_party/wpt_tools/wpt/tools/third_party/pywebsocket3/mod_pywebsocket/standalone.py b/third_party/wpt_tools/wpt/tools/third_party/pywebsocket3/mod_pywebsocket/standalone.py index b075d98..0a3bcdb 100755 --- a/third_party/wpt_tools/wpt/tools/third_party/pywebsocket3/mod_pywebsocket/standalone.py +++ b/third_party/wpt_tools/wpt/tools/third_party/pywebsocket3/mod_pywebsocket/standalone.py
@@ -403,8 +403,7 @@ def _main(args=None): """You can call this function from your own program, but please note that this function has some side-effects that might affect your program. For - example, util.wrap_popen3_for_win use in this method replaces implementation - of os.popen3. + example, it changes the current directory. """ options, args = _parse_args_and_config(args=args) @@ -427,7 +426,6 @@ # full path of third_party/cygwin/bin. if 'CYGWIN_PATH' in os.environ: cygwin_path = os.environ['CYGWIN_PATH'] - util.wrap_popen3_for_win(cygwin_path) def __check_script(scriptpath): return util.get_script_interp(scriptpath, cygwin_path)
diff --git a/third_party/wpt_tools/wpt/tools/third_party/pywebsocket3/mod_pywebsocket/util.py b/third_party/wpt_tools/wpt/tools/third_party/pywebsocket3/mod_pywebsocket/util.py index e164e6b8..04006ec 100644 --- a/third_party/wpt_tools/wpt/tools/third_party/pywebsocket3/mod_pywebsocket/util.py +++ b/third_party/wpt_tools/wpt/tools/third_party/pywebsocket3/mod_pywebsocket/util.py
@@ -97,25 +97,6 @@ return None -def wrap_popen3_for_win(cygwin_path): - """Wrap popen3 to support #!-script on Windows. - - Args: - cygwin_path: path for cygwin binary if command path is needed to be - translated. None if no translation required. - """ - __orig_popen3 = os.popen3 - - def __wrap_popen3(cmd, mode='t', bufsize=-1): - cmdline = cmd.split(' ') - interp = get_script_interp(cmdline[0], cygwin_path) - if interp: - cmd = interp + ' ' + cmd - return __orig_popen3(cmd, mode, bufsize) - - os.popen3 = __wrap_popen3 - - def hexify(s): return ' '.join(['%02x' % x for x in six.iterbytes(s)])
diff --git a/third_party/wpt_tools/wpt/tools/third_party/pywebsocket3/setup.py b/third_party/wpt_tools/wpt/tools/third_party/pywebsocket3/setup.py index 57e9428d..b65904c9 100755 --- a/third_party/wpt_tools/wpt/tools/third_party/pywebsocket3/setup.py +++ b/third_party/wpt_tools/wpt/tools/third_party/pywebsocket3/setup.py
@@ -43,7 +43,7 @@ # This is used since python_requires field is not recognized with # pip version 9.0.0 and earlier -if sys.version < '2.7': +if sys.hexversion < 0x020700f0: print('%s requires Python 2.7 or later.' % _PACKAGE_NAME, file=sys.stderr) sys.exit(1) @@ -66,9 +66,8 @@ packages=[_PACKAGE_NAME, _PACKAGE_NAME + '.handshake'], python_requires='>=2.7', install_requires=['six'], - #TODO(suzukikeita): Update this to new Github URL - url='http://code.google.com/p/pywebsocket/', - version='3.0.0', + url='https://github.com/GoogleChromeLabs/pywebsocket3', + version='3.0.1', ) # vi:sts=4 sw=4 et
diff --git a/third_party/wpt_tools/wpt/tools/webdriver/webdriver/__init__.py b/third_party/wpt_tools/wpt/tools/webdriver/webdriver/__init__.py index 0e1a9de..a817514 100644 --- a/third_party/wpt_tools/wpt/tools/webdriver/webdriver/__init__.py +++ b/third_party/wpt_tools/wpt/tools/webdriver/webdriver/__init__.py
@@ -35,3 +35,5 @@ UnknownMethodException, UnsupportedOperationException, WebDriverException) +from .bidi import ( + BidiSession)
diff --git a/third_party/wpt_tools/wpt/tools/webdriver/webdriver/bidi.py b/third_party/wpt_tools/wpt/tools/webdriver/webdriver/bidi.py new file mode 100644 index 0000000..0bcd489 --- /dev/null +++ b/third_party/wpt_tools/wpt/tools/webdriver/webdriver/bidi.py
@@ -0,0 +1,56 @@ +import copy +import websockets + +from . import client + +class BidiSession(client.Session): + def __init__(self, + host, + port, + url_prefix="/", + capabilities=None, + extension=None): + """ + Add a capability of "webSocketUrl": True to enable + Bidirectional connection in session creation. + """ + self.websocket_transport = None + capabilities = self._enable_websocket(capabilities) + super().__init__(host, port, url_prefix, capabilities, extension) + + def _enable_websocket(self, caps): + if caps: + caps.setdefault("alwaysMatch", {}).update({"webSocketUrl": True}) + else: + caps = {"alwaysMatch": {"webSocketUrl": True}} + return caps + + def match(self, capabilities): + """Expensive match to see if capabilities is the same as previously + requested capabilities if websocket would be enabled. + + :return Boolean. + """ + caps = copy.deepcopy(capabilities) + caps = self._enable_websocket(caps) + return super().match(caps) + + async def start(self): + """Start a new WebDriver Bidirectional session + with websocket connected. + + :return: Dictionary with `capabilities` and `sessionId`. + """ + value = super().start() + + if not self.websocket_transport or not self.websocket_transport.open: + self.websocket_transport = await websockets.connect(self.capabilities["webSocketUrl"]) + return value + + async def end(self): + """Close websocket connection first before closing session. + """ + if self.websocket_transport: + await self.websocket_transport.close() + self.websocket_transport = None + super().end()
diff --git a/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py b/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py index 19fe336a..22533409 100644 --- a/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py +++ b/third_party/wpt_tools/wpt/tools/webdriver/webdriver/client.py
@@ -2,8 +2,7 @@ from . import protocol from . import transport -from six import string_types -from six.moves.urllib import parse as urlparse +from urllib import parse as urlparse def command(func): @@ -435,7 +434,7 @@ cookie = {"name": name, "value": None} - if isinstance(name, string_types): + if isinstance(name, str): cookie["value"] = value elif hasattr(value, "value"): cookie["value"] = value.value @@ -506,6 +505,9 @@ def __del__(self): self.end() + def match(self, capabilities): + return self.requested_capabilities == capabilities + def start(self): """Start a new WebDriver session. @@ -753,7 +755,6 @@ def screenshot(self): return self.send_session_command("GET", "screenshot") - class Element(object): """ Representation of a web element.
diff --git a/third_party/wpt_tools/wpt/tools/webdriver/webdriver/error.py b/third_party/wpt_tools/wpt/tools/webdriver/webdriver/error.py index 6426129..807c592 100644 --- a/third_party/wpt_tools/wpt/tools/webdriver/webdriver/error.py +++ b/third_party/wpt_tools/wpt/tools/webdriver/webdriver/error.py
@@ -1,8 +1,6 @@ import collections import json -from six import itervalues - class WebDriverException(Exception): http_status = None @@ -220,6 +218,6 @@ _errors = collections.defaultdict() -for item in list(itervalues(locals())): +for item in list(locals().values()): if type(item) == type and issubclass(item, WebDriverException): _errors[item.status_code] = item
diff --git a/third_party/wpt_tools/wpt/tools/webdriver/webdriver/protocol.py b/third_party/wpt_tools/wpt/tools/webdriver/webdriver/protocol.py index d3faa850..e71e01d6 100644 --- a/third_party/wpt_tools/wpt/tools/webdriver/webdriver/protocol.py +++ b/third_party/wpt_tools/wpt/tools/webdriver/webdriver/protocol.py
@@ -2,8 +2,6 @@ import webdriver -from six import iteritems - """WebDriver wire protocol codecs.""" @@ -45,5 +43,5 @@ elif isinstance(payload, dict) and webdriver.ShadowRoot.identifier in payload: return webdriver.ShadowRoot.from_json(payload, self.session) elif isinstance(payload, dict): - return {k: self.object_hook(v) for k, v in iteritems(payload)} + return {k: self.object_hook(v) for k, v in payload.items()} return payload
diff --git a/third_party/wpt_tools/wpt/tools/webdriver/webdriver/transport.py b/third_party/wpt_tools/wpt/tools/webdriver/webdriver/transport.py index 33142d3..15ba6b8fe 100644 --- a/third_party/wpt_tools/wpt/tools/webdriver/webdriver/transport.py +++ b/third_party/wpt_tools/wpt/tools/webdriver/webdriver/transport.py
@@ -1,10 +1,9 @@ import json import select -from six import text_type, PY3 -from six.moves.collections_abc import Mapping -from six.moves.http_client import HTTPConnection -from six.moves.urllib import parse as urlparse +from collections.abc import Mapping +from http.client import HTTPConnection +from urllib import parse as urlparse from . import error @@ -157,8 +156,6 @@ """Gets the current HTTP connection, or lazily creates one.""" if not self._conn: conn_kwargs = {} - if not PY3: - conn_kwargs["strict"] = True # We are not setting an HTTP timeout other than the default when the # connection its created. The send method has a timeout value if needed. self._conn = HTTPConnection(self.host, self.port, **conn_kwargs) @@ -240,7 +237,7 @@ return Response.from_http(response, decoder=decoder, **codec_kwargs) def _request(self, method, uri, payload, headers=None, timeout=None): - if isinstance(payload, text_type): + if isinstance(payload, str): payload = payload.encode("utf-8") if headers is None:
diff --git a/third_party/wpt_tools/wpt/tools/wpt/android.py b/third_party/wpt_tools/wpt/tools/wpt/android.py index 744e134d..8ded6e1 100644 --- a/third_party/wpt_tools/wpt/tools/wpt/android.py +++ b/third_party/wpt_tools/wpt/tools/wpt/android.py
@@ -89,8 +89,8 @@ #TODO: Not sure what's really needed here packages = ["platform-tools", - "build-tools;29.0.3", - "platforms;android-29", + "build-tools;30.0.2", + "platforms;android-30", "emulator"] # TODO: make this work non-internactively
diff --git a/third_party/wpt_tools/wpt/tools/wpt/browser.py b/third_party/wpt_tools/wpt/tools/wpt/browser.py index 800080e..2995d52 100644 --- a/third_party/wpt_tools/wpt/tools/wpt/browser.py +++ b/third_party/wpt_tools/wpt/tools/wpt/browser.py
@@ -9,7 +9,7 @@ from datetime import datetime, timedelta from distutils.spawn import find_executable -from six.moves.urllib.parse import urlsplit +from urllib.parse import urlsplit import requests from .utils import call, get, rmtree, untar, unzip, get_download_to_descriptor, sha256sum
diff --git a/third_party/wpt_tools/wpt/tools/wpt/run.py b/third_party/wpt_tools/wpt/tools/wpt/run.py index 68f8e32..1dcb1d4 100644 --- a/third_party/wpt_tools/wpt/tools/wpt/run.py +++ b/third_party/wpt_tools/wpt/tools/wpt/run.py
@@ -3,7 +3,6 @@ import platform import sys from distutils.spawn import find_executable -from six.moves import input wpt_root = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir)) sys.path.insert(0, os.path.abspath(os.path.join(wpt_root, "tools"))) @@ -757,9 +756,8 @@ def setup_wptrunner(venv, **kwargs): from wptrunner import wptcommandline - from six import iteritems - kwargs = utils.Kwargs(iteritems(kwargs)) + kwargs = utils.Kwargs(kwargs.items()) kwargs["product"] = kwargs["product"].replace("-", "_")
diff --git a/third_party/wpt_tools/wpt/tools/wpt/testfiles.py b/third_party/wpt_tools/wpt/tools/wpt/testfiles.py index fee19cd1..5c398588 100644 --- a/third_party/wpt_tools/wpt/tools/wpt/testfiles.py +++ b/third_party/wpt_tools/wpt/tools/wpt/testfiles.py
@@ -6,7 +6,7 @@ import sys from collections import OrderedDict -from six import ensure_text, ensure_str, iteritems +from six import ensure_text, ensure_str try: from ..manifest import manifest @@ -98,7 +98,7 @@ branch_point = None # if there are any commits, take the first parent that is not in commits - for commit, parents in iteritems(commit_parents): + for commit, parents in commit_parents.items(): for parent in parents: if parent not in commit_parents: branch_point = parent @@ -251,7 +251,7 @@ nontests_changed = set(files_changed) wpt_manifest = load_manifest(manifest_path, manifest_update) - test_types = ["crashtest", "testharness", "reftest", "wdspec"] + test_types = ["crashtest", "print-reftest", "reftest", "testharness", "wdspec"] support_files = {os.path.join(wpt_root, path) for _, path, _ in wpt_manifest.itertypes("support")} wdspec_test_files = {os.path.join(wpt_root, path)
diff --git a/third_party/wpt_tools/wpt/tools/wpt/utils.py b/third_party/wpt_tools/wpt/tools/wpt/utils.py index 61dcda5..30e9574 100644 --- a/third_party/wpt_tools/wpt/tools/wpt/utils.py +++ b/third_party/wpt_tools/wpt/tools/wpt/utils.py
@@ -9,7 +9,7 @@ import zipfile from io import BytesIO from socket import error as SocketError # NOQA: N812 -from six.moves.urllib.request import urlopen +from urllib.request import urlopen MYPY = False if MYPY:
diff --git a/third_party/wpt_tools/wpt/tools/wpt/virtualenv.py b/third_party/wpt_tools/wpt/tools/wpt/virtualenv.py index 51b97cea..1cfb150 100644 --- a/third_party/wpt_tools/wpt/tools/wpt/virtualenv.py +++ b/third_party/wpt_tools/wpt/tools/wpt/virtualenv.py
@@ -55,13 +55,9 @@ @property def pip_path(self): - if sys.version_info.major >= 3: - pip_executable = "pip3" - else: - pip_executable = "pip2" - path = find_executable(pip_executable, self.bin_path) + path = find_executable("pip3", self.bin_path) if path is None: - raise ValueError("%s not found" % pip_executable) + raise ValueError("pip3 not found") return path @property
diff --git a/third_party/wpt_tools/wpt/tools/wpt/wpt.py b/third_party/wpt_tools/wpt/tools/wpt/wpt.py index 9bc6ce6c..1faf7d7 100644 --- a/third_party/wpt_tools/wpt/tools/wpt/wpt.py +++ b/third_party/wpt_tools/wpt/tools/wpt/wpt.py
@@ -6,7 +6,6 @@ from tools import localpaths # noqa: F401 -from six import iteritems from . import virtualenv @@ -23,7 +22,7 @@ base_dir = os.path.dirname(abs_path) with open(abs_path, "r") as f: data = json.load(f) - for command, props in iteritems(data): + for command, props in data.items(): assert "path" in props assert "script" in props rv[command] = { @@ -31,7 +30,6 @@ "script": props["script"], "parser": props.get("parser"), "parse_known": props.get("parse_known", False), - "py3only": props.get("py3only", False), "help": props.get("help"), "virtualenv": props.get("virtualenv", True), "install": props.get("install", []), @@ -50,12 +48,8 @@ dest="skip_venv_setup", help="Whether to use the virtualenv as-is. Must set --venv as well") parser.add_argument("--debug", action="store_true", help="Run the debugger in case of an exception") - parser.add_argument("--py3", action="store_true", - help="Run with Python 3 (requires a `python3` binary on the PATH)") - parser.add_argument("--py2", action="store_true", - help="Run with Python 2 (requires a `python2` binary on the PATH)") subparsers = parser.add_subparsers(dest="command") - for command, props in iteritems(commands): + for command, props in commands.items(): subparsers.add_parser(command, help=props["help"], add_help=False) args, extra = parser.parse_known_args(argv) @@ -100,8 +94,7 @@ for command in commands: props = commands[command] - if (props["virtualenv"] and - (not props["py3only"] or sys.version_info.major == 3)): + if props["virtualenv"]: setup_virtualenv(None, False, props) subparser = import_command('wpt', command, props)[1]
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/requirements.txt b/third_party/wpt_tools/wpt/tools/wptrunner/requirements.txt index 1dd4174..440a88d 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/requirements.txt +++ b/third_party/wpt_tools/wpt/tools/wptrunner/requirements.txt
@@ -4,7 +4,7 @@ mozdebug==0.2 # Pillow 7 requires Python 3 pillow==6.2.2; python_version <= '2.7' # pyup: <7.0 -pillow==8.1.0; python_version >= '3.0' -urllib3[secure]==1.26.2 +pillow==8.1.2; python_version >= '3.0' +urllib3[secure]==1.26.4 requests==2.25.1 six==1.15.0
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/requirements_safari.txt b/third_party/wpt_tools/wpt/tools/wptrunner/requirements_safari.txt index 874980b3..55b474ba9 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/requirements_safari.txt +++ b/third_party/wpt_tools/wpt/tools/wptrunner/requirements_safari.txt
@@ -1 +1,2 @@ mozprocess==1.2.1 +psutil==5.8.0
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/tox.ini b/third_party/wpt_tools/wpt/tools/wptrunner/tox.ini index b39b5eb..2b9bca17 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/tox.ini +++ b/third_party/wpt_tools/wpt/tools/wptrunner/tox.ini
@@ -2,7 +2,7 @@ xfail_strict=true [tox] -envlist = py27-{base,chrome,edge,firefox,ie,opera,safari,sauce,servo,webkit,webkitgtk_minibrowser,epiphany},{py35,py36,py37,py38}-base +envlist = py38-{base,chrome,edge,firefox,ie,opera,safari,sauce,servo,webkit,webkitgtk_minibrowser,epiphany},{py36,py37}-base skip_missing_interpreters = False [testenv]
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/android_weblayer.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/android_weblayer.py index f68312f..ec05c76 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/android_weblayer.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/android_weblayer.py
@@ -1,9 +1,7 @@ -import subprocess - -from .base import Browser, ExecutorBrowser, require_arg +from .base import require_arg from .base import get_timeout_multiplier # noqa: F401 from .chrome import executor_kwargs as chrome_executor_kwargs -from ..webdriver_server import ChromeDriverServer +from .chrome_android import ChromeAndroidBrowserBase from ..executors.executorwebdriver import (WebDriverTestharnessExecutor, # noqa: F401 WebDriverRefTestExecutor) # noqa: F401 from ..executors.executorchrome import ChromeDriverWdspecExecutor # noqa: F401 @@ -32,7 +30,9 @@ return {"binary": kwargs["binary"], "device_serial": kwargs["device_serial"], "webdriver_binary": kwargs["webdriver_binary"], - "webdriver_args": kwargs.get("webdriver_args")} + "webdriver_args": kwargs.get("webdriver_args"), + "stackparser_script": kwargs.get("stackparser_script"), + "output_directory": kwargs.get("output_directory")} def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data, @@ -74,61 +74,22 @@ return {"server_host": "127.0.0.1"} -#TODO: refactor common elements of WeblayerShell and ChromeAndroidBrowser -class WeblayerShell(Browser): +class WeblayerShell(ChromeAndroidBrowserBase): """Chrome is backed by chromedriver, which is supplied through ``wptrunner.webdriver.ChromeDriverServer``. """ - def __init__(self, logger, binary, webdriver_binary="chromedriver", + def __init__(self, logger, binary, + webdriver_binary="chromedriver", + remote_queue=None, device_serial=None, - webdriver_args=None): + webdriver_args=None, + stackparser_script=None, + output_directory=None): """Creates a new representation of Chrome. The `binary` argument gives the browser binary to use for testing.""" - Browser.__init__(self, logger) + super(WeblayerShell, self).__init__(logger, + webdriver_binary, remote_queue, device_serial, + webdriver_args, stackparser_script, output_directory) self.binary = binary - self.device_serial = device_serial - self.server = ChromeDriverServer(self.logger, - binary=webdriver_binary, - args=webdriver_args) - self.setup_adb_reverse() - - def _adb_run(self, args): - cmd = ['adb'] - if self.device_serial: - cmd.extend(['-s', self.device_serial]) - cmd.extend(args) - self.logger.info(' '.join(cmd)) - subprocess.check_call(cmd) - - def setup_adb_reverse(self): - self._adb_run(['wait-for-device']) - self._adb_run(['forward', '--remove-all']) - self._adb_run(['reverse', '--remove-all']) - # "adb reverse" basically forwards network connection from device to - # host. - for port in _wptserve_ports: - self._adb_run(['reverse', 'tcp:%d' % port, 'tcp:%d' % port]) - - def start(self, **kwargs): - self.server.start(block=False) - - def stop(self, force=False): - self.server.stop(force=force) - - def pid(self): - return self.server.pid - - def is_alive(self): - # TODO(ato): This only indicates the driver is alive, - # and doesn't say anything about whether a browser session - # is active. - return self.server.is_alive() - - def cleanup(self): - self.stop() - self._adb_run(['forward', '--remove-all']) - self._adb_run(['reverse', '--remove-all']) - - def executor_browser(self): - return ExecutorBrowser, {"webdriver_url": self.server.url} + self.wptserver_ports = _wptserve_ports
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/android_webview.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/android_webview.py index 3cde248b..54dd128 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/android_webview.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/android_webview.py
@@ -1,9 +1,7 @@ -import subprocess - -from .base import Browser, ExecutorBrowser, require_arg +from .base import require_arg from .base import get_timeout_multiplier # noqa: F401 from .chrome import executor_kwargs as chrome_executor_kwargs -from ..webdriver_server import ChromeDriverServer +from .chrome_android import ChromeAndroidBrowserBase from ..executors.executorwebdriver import (WebDriverTestharnessExecutor, # noqa: F401 WebDriverRefTestExecutor) # noqa: F401 from ..executors.executorchrome import ChromeDriverWdspecExecutor # noqa: F401 @@ -32,7 +30,9 @@ return {"binary": kwargs["binary"], "device_serial": kwargs["device_serial"], "webdriver_binary": kwargs["webdriver_binary"], - "webdriver_args": kwargs.get("webdriver_args")} + "webdriver_args": kwargs.get("webdriver_args"), + "stackparser_script": kwargs.get("stackparser_script"), + "output_directory": kwargs.get("output_directory")} def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data, @@ -51,10 +51,11 @@ # Note that for WebView, we launch a test shell and have the test shell use WebView. # https://chromium.googlesource.com/chromium/src/+/HEAD/android_webview/docs/webview-shell.md capabilities["goog:chromeOptions"]["androidPackage"] = \ - "org.chromium.webview_shell" - capabilities["goog:chromeOptions"]["androidActivity"] = ".WebPlatformTestsActivity" - if kwargs.get('device_serial'): - capabilities["goog:chromeOptions"]["androidDeviceSerial"] = kwargs['device_serial'] + kwargs.get("package_name", "org.chromium.webview_shell") + capabilities["goog:chromeOptions"]["androidActivity"] = \ + "org.chromium.webview_shell.WebPlatformTestsActivity" + if kwargs.get("device_serial"): + capabilities["goog:chromeOptions"]["androidDeviceSerial"] = kwargs["device_serial"] # Workaround: driver.quit() cannot quit SystemWebViewShell. executor_kwargs["pause_after_test"] = False @@ -73,61 +74,21 @@ return {"server_host": "127.0.0.1"} -#TODO: refactor common elements of SystemWebViewShell and ChromeAndroidBrowser -class SystemWebViewShell(Browser): +class SystemWebViewShell(ChromeAndroidBrowserBase): """Chrome is backed by chromedriver, which is supplied through ``wptrunner.webdriver.ChromeDriverServer``. """ def __init__(self, logger, binary, webdriver_binary="chromedriver", + remote_queue=None, device_serial=None, - webdriver_args=None): + webdriver_args=None, + stackparser_script=None, + output_directory=None): """Creates a new representation of Chrome. The `binary` argument gives the browser binary to use for testing.""" - Browser.__init__(self, logger) + super(SystemWebViewShell, self).__init__(logger, + webdriver_binary, remote_queue, device_serial, + webdriver_args, stackparser_script, output_directory) self.binary = binary - self.device_serial = device_serial - self.server = ChromeDriverServer(self.logger, - binary=webdriver_binary, - args=webdriver_args) - self.setup_adb_reverse() - - def _adb_run(self, args): - cmd = ['adb'] - if self.device_serial: - cmd.extend(['-s', self.device_serial]) - cmd.extend(args) - self.logger.info(' '.join(cmd)) - subprocess.check_call(cmd) - - def setup_adb_reverse(self): - self._adb_run(['wait-for-device']) - self._adb_run(['forward', '--remove-all']) - self._adb_run(['reverse', '--remove-all']) - # "adb reverse" basically forwards network connection from device to - # host. - for port in _wptserve_ports: - self._adb_run(['reverse', 'tcp:%d' % port, 'tcp:%d' % port]) - - def start(self, **kwargs): - self.server.start(block=False) - - def stop(self, force=False): - self.server.stop(force=force) - - def pid(self): - return self.server.pid - - def is_alive(self): - # TODO(ato): This only indicates the driver is alive, - # and doesn't say anything about whether a browser session - # is active. - return self.server.is_alive() - - def cleanup(self): - self.stop() - self._adb_run(['forward', '--remove-all']) - self._adb_run(['reverse', '--remove-all']) - - def executor_browser(self): - return ExecutorBrowser, {"webdriver_url": self.server.url} + self.wptserver_ports = _wptserve_ports
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/base.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/base.py index f2205b16..f7388ad7 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/base.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/base.py
@@ -3,7 +3,6 @@ import socket from abc import ABCMeta, abstractmethod from copy import deepcopy -from six import iteritems from ..wptcommandline import require_arg # noqa: F401 @@ -163,6 +162,10 @@ with which it should be instantiated""" return ExecutorBrowser, {} + def maybe_parse_tombstone(self): + """Possibly parse tombstones on Android device for Android target""" + pass + def check_crash(self, process, test): """Check if a crash occured and output any useful information to the log. Returns a boolean indicating whether a crash occured.""" @@ -202,5 +205,5 @@ up the browser from the runner process. """ def __init__(self, **kwargs): - for k, v in iteritems(kwargs): + for k, v in kwargs.items(): setattr(self, k, v)
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/chrome.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/chrome.py index d3e27a9..04ac372 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/chrome.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/chrome.py
@@ -113,7 +113,7 @@ """ def __init__(self, logger, binary, webdriver_binary="chromedriver", - webdriver_args=None): + webdriver_args=None, **kwargs): """Creates a new representation of Chrome. The `binary` argument gives the browser binary to use for testing.""" Browser.__init__(self, logger)
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/chrome_android.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/chrome_android.py index d7e3e210..7580bed 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/chrome_android.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/chrome_android.py
@@ -1,3 +1,4 @@ +import mozprocess import subprocess from .base import Browser, ExecutorBrowser, require_arg @@ -33,7 +34,9 @@ return {"package_name": kwargs["package_name"], "device_serial": kwargs["device_serial"], "webdriver_binary": kwargs["webdriver_binary"], - "webdriver_args": kwargs.get("webdriver_args")} + "webdriver_args": kwargs.get("webdriver_args"), + "stackparser_script": kwargs.get("stackparser_script"), + "output_directory": kwargs.get("output_directory")} def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data, @@ -68,21 +71,80 @@ # allow the use of host-resolver-rules in lieu of modifying /etc/hosts file return {"server_host": "127.0.0.1"} +class LogcatRunner(object): + def __init__(self, logger, browser, remote_queue): + self.logger = logger + self.browser = browser + self.remote_queue = remote_queue -class ChromeAndroidBrowser(Browser): - """Chrome is backed by chromedriver, which is supplied through - ``wptrunner.webdriver.ChromeDriverServer``. - """ + def start(self): + try: + self._run() + except KeyboardInterrupt: + self.stop() - def __init__(self, logger, package_name, webdriver_binary="chromedriver", - device_serial=None, webdriver_args=None): - Browser.__init__(self, logger) - self.package_name = package_name + def _run(self): + try: + # TODO: adb logcat -c fail randomly with message + # "failed to clear the 'main' log" + self.browser.clear_log() + except subprocess.CalledProcessError: + self.logger.error("Failed to clear logcat buffer") + + self._cmd = self.browser.logcat_cmd() + self._proc = mozprocess.ProcessHandler( + self._cmd, + processOutputLine=self.on_output, + storeOutput=False) + self._proc.run() + + def _send_message(self, command, *args): + try: + self.remote_queue.put((command, args)) + except AssertionError: + self.logger.warning("Error when send to remote queue") + + def stop(self, force=False): + if self.is_alive(): + kill_result = self._proc.kill() + if force and kill_result != 0: + self._proc.kill(9) + + def is_alive(self): + return hasattr(self._proc, "proc") and self._proc.poll() is None + + def on_output(self, line): + data = { + "process": "LOGCAT", + "command": "logcat", + "data": line + } + self._send_message("log", "process_output", data) + +class ChromeAndroidBrowserBase(Browser): + def __init__(self, logger, + webdriver_binary="chromedriver", + remote_queue = None, + device_serial=None, + webdriver_args=None, + stackparser_script=None, + output_directory=None): + super(ChromeAndroidBrowserBase, self).__init__(logger) self.device_serial = device_serial + self.stackparser_script = stackparser_script + self.output_directory = output_directory + self.remote_queue = remote_queue self.server = ChromeDriverServer(self.logger, binary=webdriver_binary, args=webdriver_args) + if self.remote_queue is not None: + self.logcat_runner = LogcatRunner(self.logger, + self, self.remote_queue) + + def setup(self): self.setup_adb_reverse() + if self.remote_queue is not None: + self.logcat_runner.start() def _adb_run(self, args): cmd = ['adb'] @@ -92,14 +154,6 @@ self.logger.info(' '.join(cmd)) subprocess.check_call(cmd) - def setup_adb_reverse(self): - self._adb_run(['wait-for-device']) - self._adb_run(['forward', '--remove-all']) - self._adb_run(['reverse', '--remove-all']) - # "adb reverse" forwards network connection from device to host. - for port in _wptserve_ports: - self._adb_run(['reverse', 'tcp:%d' % port, 'tcp:%d' % port]) - def start(self, **kwargs): self.server.start(block=False) @@ -119,6 +173,54 @@ self.stop() self._adb_run(['forward', '--remove-all']) self._adb_run(['reverse', '--remove-all']) + if self.remote_queue is not None: + self.logcat_runner.stop(force=True) def executor_browser(self): return ExecutorBrowser, {"webdriver_url": self.server.url} + + def clear_log(self): + self._adb_run(['logcat', '-c']) + + def logcat_cmd(self): + cmd = ['adb'] + if self.device_serial: + cmd.extend(['-s', self.device_serial]) + cmd.extend(['logcat', '*:D']) + return cmd + + def maybe_parse_tombstone(self, logger): + if self.stackparser_script: + cmd = [self.stackparser_script, "-a", "-w"] + if self.device_serial: + cmd.extend(["--device", self.device_serial]) + cmd.extend(["--output-directory", self.output_directory]) + raw_output = subprocess.check_output(cmd) + for line in raw_output.splitlines(): + logger.process_output("TRACE", line, "logcat") + + def setup_adb_reverse(self): + self._adb_run(['wait-for-device']) + self._adb_run(['forward', '--remove-all']) + self._adb_run(['reverse', '--remove-all']) + # "adb reverse" forwards network connection from device to host. + for port in self.wptserver_ports: + self._adb_run(['reverse', 'tcp:%d' % port, 'tcp:%d' % port]) + +class ChromeAndroidBrowser(ChromeAndroidBrowserBase): + """Chrome is backed by chromedriver, which is supplied through + ``wptrunner.webdriver.ChromeDriverServer``. + """ + + def __init__(self, logger, package_name, + webdriver_binary="chromedriver", + remote_queue = None, + device_serial=None, + webdriver_args=None, + stackparser_script=None, + output_directory=None): + super(ChromeAndroidBrowser, self).__init__(logger, + webdriver_binary, remote_queue, device_serial, + webdriver_args, stackparser_script, output_directory) + self.package_name = package_name + self.wptserver_ports = _wptserve_ports
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/chrome_ios.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/chrome_ios.py index ecdbc3a..f349b194 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/chrome_ios.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/chrome_ios.py
@@ -51,7 +51,7 @@ init_timeout = 120 - def __init__(self, logger, webdriver_binary, webdriver_args=None): + def __init__(self, logger, webdriver_binary, webdriver_args=None, **kwargs): """Creates a new representation of Chrome.""" Browser.__init__(self, logger) self.server = CWTChromeDriverServer(self.logger,
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/chrome_spki_certs.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/chrome_spki_certs.py index 5ee5179..87bbc956 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/chrome_spki_certs.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/chrome_spki_certs.py
@@ -2,7 +2,7 @@ # DO NOT EDIT MANUALLY. # tools/certs/web-platform.test.pem -WPT_FINGERPRINT = 'OXb4O8pcDI8Nwx3KzqNuTbJ1Znf52VjEVWiYYCjHcIM=' +WPT_FINGERPRINT = 'LjjEE/m/0BKndI/KeccXvPp5wHuXfV09jw9QS7OGIvI=' # signed-exchange/resources/127.0.0.1.sxg.pem SXG_WPT_FINGERPRINT = '0Rt4mT6SJXojEMHTnKnlJ/hBKMBcI4kteBlhR1eTTdk='
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/edge.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/edge.py index b908684..db4795c 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/edge.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/edge.py
@@ -68,7 +68,8 @@ used_ports = set() init_timeout = 60 - def __init__(self, logger, webdriver_binary, timeout_multiplier=None, webdriver_args=None): + def __init__(self, logger, webdriver_binary, + timeout_multiplier=None, webdriver_args=None, **kwargs): Browser.__init__(self, logger) self.server = EdgeDriverServer(self.logger, binary=webdriver_binary,
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/edgechromium.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/edgechromium.py index 1d45983..c2275bd1 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/edgechromium.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/edgechromium.py
@@ -85,7 +85,7 @@ """ def __init__(self, logger, binary, webdriver_binary="msedgedriver", - webdriver_args=None): + webdriver_args=None, **kwargs): """Creates a new representation of MicrosoftEdge. The `binary` argument gives the browser binary to use for testing.""" Browser.__init__(self, logger)
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/epiphany.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/epiphany.py index a338443..f378170f 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/epiphany.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/epiphany.py
@@ -72,6 +72,6 @@ class EpiphanyBrowser(WebKitBrowser): def __init__(self, logger, binary=None, webdriver_binary=None, - webdriver_args=None): + webdriver_args=None, **kwargs): WebKitBrowser.__init__(self, logger, binary, webdriver_binary, webdriver_args)
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/firefox.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/firefox.py index 83a883b..3a42298 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/firefox.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/firefox.py
@@ -196,7 +196,8 @@ "fission": kwargs.get("enable_fission") or get_bool_pref("fission.autostart"), "sessionHistoryInParent": (kwargs.get("enable_fission") or get_bool_pref("fission.autostart") or - get_bool_pref("fission.sessionHistoryInParent"))} + get_bool_pref("fission.sessionHistoryInParent")), + "swgl": get_bool_pref("gfx.webrender.software")} # The value of `sw-e10s` defaults to whether the "parent_intercept" # implementation is enabled for the current build. This value, however, @@ -226,7 +227,7 @@ def update_properties(): - return (["os", "debug", "webrender", "fission", "e10s", "sw-e10s", "processor"], + return (["os", "debug", "webrender", "fission", "e10s", "sw-e10s", "processor", "swgl"], {"os": ["version"], "processor": ["bits"]})
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/ie.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/ie.py index 3a86c1b6..5fce29a 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/ie.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/ie.py
@@ -43,7 +43,7 @@ class InternetExplorerBrowser(Browser): used_ports = set() - def __init__(self, logger, webdriver_binary, webdriver_args=None): + def __init__(self, logger, webdriver_binary, webdriver_args=None, **kwargs): Browser.__init__(self, logger) self.server = InternetExplorerDriverServer(self.logger, binary=webdriver_binary,
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/opera.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/opera.py index a34f419..80e5a31 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/opera.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/opera.py
@@ -71,7 +71,7 @@ """ def __init__(self, logger, binary, webdriver_binary="operadriver", - webdriver_args=None): + webdriver_args=None, **kwargs): """Creates a new representation of Opera. The `binary` argument gives the browser binary to use for testing.""" Browser.__init__(self, logger)
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/safari.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/safari.py index 312d4db9..9565f1c 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/safari.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/safari.py
@@ -1,3 +1,9 @@ +import os +import plistlib +from distutils.spawn import find_executable + +import psutil + from .base import Browser, ExecutorBrowser, require_arg from .base import get_timeout_multiplier # noqa: F401 from ..webdriver_server import SafariDriverServer @@ -28,7 +34,8 @@ def browser_kwargs(logger, test_type, run_info_data, config, **kwargs): return {"webdriver_binary": kwargs["webdriver_binary"], - "webdriver_args": kwargs.get("webdriver_args")} + "webdriver_args": kwargs.get("webdriver_args"), + "kill_safari": kwargs.get("kill_safari", False)} def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data, @@ -58,15 +65,60 @@ ``wptrunner.webdriver.SafariDriverServer``. """ - def __init__(self, logger, webdriver_binary, webdriver_args=None): + def __init__(self, logger, webdriver_binary, webdriver_args=None, kill_safari=False, **kwargs): """Creates a new representation of Safari. The `webdriver_binary` argument gives the WebDriver binary to use for testing. (The browser binary location cannot be specified, as Safari and SafariDriver are - coupled.)""" + coupled.) If `kill_safari` is True, then `Browser.stop` will stop Safari.""" Browser.__init__(self, logger) self.server = SafariDriverServer(self.logger, binary=webdriver_binary, args=webdriver_args) + if "/" not in webdriver_binary: + wd_path = find_executable(webdriver_binary) + else: + wd_path = webdriver_binary + self.safari_path = self._findAssociatedSafariExecutable(wd_path) + + logger.debug("WebDriver executable path: %s" % wd_path) + logger.debug("Safari executable path: %s" % self.safari_path) + + self.kill_safari = kill_safari + + def _findAssociatedSafariExecutable(self, wd_path): + bundle_paths = [ + os.path.join(os.path.dirname(wd_path), "..", ".."), # bundled Safari (e.g. STP) + os.path.join(os.path.dirname(wd_path), "Safari.app"), # local Safari build + "/Applications/Safari.app", # system Safari + ] + + for bundle_path in bundle_paths: + info_path = os.path.join(bundle_path, "Contents", "Info.plist") + if not os.path.isfile(info_path): + continue + + with open(info_path, "rb") as fp: + info = plistlib.load(fp) + + # check we have a Safari family bundle + if "CFBundleIdentifier" not in info: + continue + ident = info["CFBundleIdentifier"] + if not isinstance(ident, str) or not ident.startswith("com.apple.Safari"): + continue + + # get the executable name + if "CFBundleExecutable" not in info: + continue + exe = info["CFBundleExecutable"] + if not isinstance(exe, str): + continue + + exe_path = os.path.join(bundle_path, "Contents", "MacOS", exe) + if not os.path.isfile(exe_path): + continue + + return exe_path def start(self, **kwargs): self.server.start(block=False) @@ -74,6 +126,20 @@ def stop(self, force=False): self.server.stop(force=force) + if self.kill_safari: + self.logger.debug("Going to stop Safari") + for proc in psutil.process_iter(attrs=["exe"]): + if proc.info["exe"] is not None and os.path.samefile(proc.info["exe"], self.safari_path): + self.logger.debug("Stopping Safari %s" % proc.pid) + try: + proc.terminate() + try: + proc.wait(10) + except psutil.TimeoutExpired: + proc.kill() + except psutil.NoSuchProcess: + pass + def pid(self): return self.server.pid
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/sauce.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/sauce.py index 3497c5c..99ece89d 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/sauce.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/sauce.py
@@ -12,7 +12,7 @@ import requests -from six.moves import cStringIO as StringIO +from io import StringIO from .base import Browser, ExecutorBrowser, require_arg from .base import get_timeout_multiplier # noqa: F401 @@ -228,7 +228,7 @@ class SauceBrowser(Browser): init_timeout = 300 - def __init__(self, logger, sauce_config): + def __init__(self, logger, sauce_config, **kwargs): Browser.__init__(self, logger) self.sauce_config = sauce_config
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/servo.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/servo.py index a65ed5ea..4f934aed 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/servo.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/servo.py
@@ -71,7 +71,7 @@ class ServoBrowser(NullBrowser): def __init__(self, logger, binary, debug_info=None, binary_args=None, - user_stylesheets=None, ca_certificate_path=None): + user_stylesheets=None, ca_certificate_path=None, **kwargs): NullBrowser.__init__(self, logger) self.binary = binary self.debug_info = debug_info
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/servodriver.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/servodriver.py index ed85cbf..83b9423 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/servodriver.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/servodriver.py
@@ -77,7 +77,8 @@ init_timeout = 300 # Large timeout for cases where we're booting an Android emulator def __init__(self, logger, binary, debug_info=None, webdriver_host="127.0.0.1", - server_config=None, binary_args=None, user_stylesheets=None, headless=None): + server_config=None, binary_args=None, + user_stylesheets=None, headless=None, **kwargs): Browser.__init__(self, logger) self.binary = binary self.binary_args = binary_args or []
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/webkit.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/webkit.py index 590e472..f83de29 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/webkit.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/webkit.py
@@ -82,7 +82,7 @@ """ def __init__(self, logger, binary, webdriver_binary=None, - webdriver_args=None): + webdriver_args=None, **kwargs): Browser.__init__(self, logger) self.binary = binary self.server = WebKitDriverServer(self.logger, binary=webdriver_binary,
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/webkitgtk_minibrowser.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/webkitgtk_minibrowser.py index 5b7a360f..6c1001e 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/webkitgtk_minibrowser.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/webkitgtk_minibrowser.py
@@ -76,6 +76,6 @@ class WebKitGTKMiniBrowser(WebKitBrowser): def __init__(self, logger, binary=None, webdriver_binary=None, - webdriver_args=None): + webdriver_args=None, **kwargs): WebKitBrowser.__init__(self, logger, binary, webdriver_binary, webdriver_args)
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/config.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/config.py index d46beb8e..3f5e934 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/config.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/config.py
@@ -1,4 +1,4 @@ -from six.moves.configparser import SafeConfigParser +from configparser import SafeConfigParser import os import sys from collections import OrderedDict
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/environment.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/environment.py index b68fce0..86dcb93 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/environment.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/environment.py
@@ -5,7 +5,6 @@ import socket import sys import time -from six import iteritems from mozlog import get_default_logger, handlers, proxy @@ -108,7 +107,7 @@ def __exit__(self, exc_type, exc_val, exc_tb): self.process_interrupts() - for scheme, servers in iteritems(self.servers): + for scheme, servers in self.servers.items(): for port, server in servers: server.kill() for cm in self.env_extras_cms: @@ -215,7 +214,7 @@ route_builder.add_handler("GET", "/resources/testdriver.js", StringHandler(data, "text/javascript")) - for url_base, paths in iteritems(self.test_paths): + for url_base, paths in self.test_paths.items(): if url_base == "/": continue route_builder.add_mount_point(url_base, paths["tests_path"]) @@ -247,13 +246,13 @@ failed = [] pending = [] host = self.config["server_host"] - for scheme, servers in iteritems(self.servers): + for scheme, servers in self.servers.items(): for port, server in servers: if not server.is_alive(): failed.append((scheme, port)) if not failed and self.test_server_port: - for scheme, servers in iteritems(self.servers): + for scheme, servers in self.servers.items(): # TODO(Hexcles): Find a way to test QUIC's UDP port. if scheme == "quic-transport": continue
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/base.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/base.py index 1b754219..b47d0ad 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/base.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/base.py
@@ -8,9 +8,8 @@ import socket import sys from abc import ABCMeta, abstractmethod -from six import text_type -from six.moves.http_client import HTTPConnection -from six.moves.urllib.parse import urljoin, urlsplit, urlunsplit +from http.client import HTTPConnection +from urllib.parse import urljoin, urlsplit, urlunsplit from .actions import actions from .protocol import Protocol, BaseProtocolPart @@ -287,9 +286,9 @@ """Run a particular test. :param test: The test to run""" - if test.environment != self.last_environment: - self.on_environment_change(test.environment) try: + if test.environment != self.last_environment: + self.on_environment_change(test.environment) result = self.do_test(test) except Exception as e: exception_string = traceback.format_exc() @@ -333,7 +332,7 @@ status = e.status else: status = "INTERNAL-ERROR" - message = text_type(getattr(e, "message", "")) + message = str(getattr(e, "message", "")) if message: message += "\n" message += exception_string
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorchrome.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorchrome.py index 3a70475..431d398 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorchrome.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorchrome.py
@@ -1,7 +1,7 @@ import os import traceback -from six.moves.urllib.parse import urljoin +from urllib.parse import urljoin from .base import WdspecProtocol, WdspecExecutor, get_pages from .executorwebdriver import WebDriverProtocol, WebDriverRefTestExecutor, WebDriverRun
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executormarionette.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executormarionette.py index d61e1f2..81be731b 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executormarionette.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executormarionette.py
@@ -5,8 +5,7 @@ import traceback import uuid -from six import iteritems, iterkeys -from six.moves.urllib.parse import urljoin +from urllib.parse import urljoin errors = None marionette = None @@ -727,14 +726,14 @@ def on_environment_change(self, old_environment, new_environment): #Unset all the old prefs - for name in iterkeys(old_environment.get("prefs", {})): + for name in old_environment.get("prefs", {}).keys(): value = self.executor.original_pref_values[name] if value is None: self.prefs.clear(name) else: self.prefs.set(name, value) - for name, value in iteritems(new_environment.get("prefs", {})): + for name, value in new_environment.get("prefs", {}).items(): self.executor.original_pref_values[name] = self.prefs.get(name) self.prefs.set(name, value) @@ -1000,7 +999,7 @@ result["extra"]["assertion_count"] = assertion_count if self.debug_test and result["status"] in ["PASS", "FAIL", "ERROR"] and "extra" in result: - self.parent.base.set_window(self.parent.base.window_handles()[0]) + self.protocol.base.set_window(self.protocol.base.window_handles()[0]) self.protocol.debug.load_reftest_analyzer(test, result) return self.convert_result(test, result) @@ -1048,8 +1047,7 @@ data = {"screenshot": screenshot, "isPrint": self.executor.is_print} if self.executor.group_metadata is not None: data["urlCount"] = {urljoin(self.executor.server_url(key[0]), key[1]):value - for key, value in iteritems( - self.executor.group_metadata.get("url_count", {})) + for key, value in self.executor.group_metadata.get("url_count", {}).items() if value > 1} self.chrome_scope = chrome_scope if chrome_scope:
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorselenium.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorselenium.py index 6070007..783903b9 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorselenium.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorselenium.py
@@ -6,7 +6,7 @@ import time import traceback import uuid -from six.moves.urllib.parse import urljoin +from urllib.parse import urljoin from .base import (CallbackHandler, RefTestExecutor,
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorservo.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorservo.py index efe93ab..597c879 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorservo.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorservo.py
@@ -7,7 +7,7 @@ import threading import traceback import uuid -from six import ensure_str, iteritems +from six import ensure_str from mozprocess import ProcessHandler @@ -48,7 +48,7 @@ args += ["-Z", debug_opts] for stylesheet in browser.user_stylesheets: args += ["--user-stylesheet", stylesheet] - for pref, value in iteritems(test.environment.get('prefs', {})): + for pref, value in test.environment.get('prefs', {}).items(): args += ["--pref", "%s=%s" % (pref, value)] if browser.ca_certificate_path: args += ["--certificate-path", browser.ca_certificate_path]
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py index 0a968bf3..a04a55a 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py
@@ -6,7 +6,7 @@ import time import traceback import uuid -from six.moves.urllib.parse import urljoin +from urllib.parse import urljoin from .base import (CallbackHandler, CrashtestExecutor,
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/protocol.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/protocol.py index 05e251c..ab16b0ef 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/protocol.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/protocol.py
@@ -531,7 +531,7 @@ def load_reftest_analyzer(self, test, result): import io import mozlog - from six.moves.urllib.parse import quote, urljoin + from urllib.parse import quote, urljoin debug_test_logger = mozlog.structuredlog.StructuredLogger("debug_test") output = io.StringIO()
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/expectedtree.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/expectedtree.py index 7521f25..76ade95f 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/expectedtree.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/expectedtree.py
@@ -1,6 +1,5 @@ from math import log from collections import defaultdict -from six import iteritems, itervalues class Node(object): def __init__(self, prop, value): @@ -34,7 +33,7 @@ result_counts = defaultdict(int) total = float(len(results)) - for values in itervalues(results): + for values in results.values(): # Not sure this is right, possibly want to treat multiple values as # distinct from multiple of the same value? for value in values: @@ -42,7 +41,7 @@ entropy_sum = 0 - for count in itervalues(result_counts): + for count in result_counts.values(): prop = float(count) / total entropy_sum -= prop * log(prop, 2) @@ -53,7 +52,7 @@ """Split a dictionary of results into a dictionary of dictionaries where each sub-dictionary has a specific value of the given property""" by_prop = defaultdict(dict) - for run_info, value in iteritems(results): + for run_info, value in results.items(): by_prop[run_info[prop]][run_info] = value return by_prop @@ -78,13 +77,13 @@ prop_index = {prop: i for i, prop in enumerate(properties)} all_results = defaultdict(int) - for result_values in itervalues(results): - for result_value, count in iteritems(result_values): + for result_values in results.values(): + for result_value, count in result_values.items(): all_results[result_value] += count # If there is only one result we are done if not properties or len(all_results) == 1: - for value, count in iteritems(all_results): + for value, count in all_results.items(): tree.result_values[value] += count tree.run_info |= set(results.keys()) return tree @@ -100,7 +99,7 @@ continue new_entropy = 0. results_sets_entropy = [] - for prop_value, result_set in iteritems(result_sets): + for prop_value, result_set in result_sets.items(): results_sets_entropy.append((entropy(result_set), prop_value, result_set)) new_entropy += (float(len(result_set)) / len(results)) * results_sets_entropy[-1][0] @@ -110,7 +109,7 @@ # In the case that no properties partition the space if not results_partitions: - for value, count in iteritems(all_results): + for value, count in all_results.items(): tree.result_values[value] += count tree.run_info |= set(results.keys()) return tree
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/formatters/chromium.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/formatters/chromium.py index 2ff2bd1..ae8d96a1 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/formatters/chromium.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/formatters/chromium.py
@@ -1,6 +1,5 @@ import json import time -import six from collections import defaultdict from mozlog.formatters import base @@ -88,7 +87,7 @@ :param str artifact_name: the name of the artifact :param str artifact_value: the value of the artifact """ - assert isinstance(artifact_value, six.string_types), "artifact_value must be a str" + assert isinstance(artifact_value, str), "artifact_value must be a str" if "artifacts" not in cur_dict.keys(): cur_dict["artifacts"] = defaultdict(list) cur_dict["artifacts"][artifact_name].append(artifact_value) @@ -272,5 +271,6 @@ return json.dumps(final_result) def process_output(self, data): - if 'command' in data and 'chromedriver' in data['command']: + cmd = data.get("command", "") + if any(c in cmd for c in ["chromedriver", "logcat"]): self.browser_log.append(data['data'])
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/formatters/tests/test_chromium.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/formatters/tests/test_chromium.py index 55a12b1d7..53d64df7 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/formatters/tests/test_chromium.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/formatters/tests/test_chromium.py
@@ -1,7 +1,7 @@ import json import sys from os.path import dirname, join -from six.moves import cStringIO as StringIO +from io import StringIO from mozlog import handlers, structuredlog
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/instruments.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/instruments.py index a887cf4..4e3e013 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/instruments.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/instruments.py
@@ -1,6 +1,6 @@ import time import threading -from six.moves.queue import Queue +from queue import Queue """Instrumentation for measuring high-level time spent on various tasks inside the runner.
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/manifestexpected.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/manifestexpected.py index 31c57e9..2f7f533 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/manifestexpected.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/manifestexpected.py
@@ -1,8 +1,6 @@ import os from collections import deque -from six import string_types, text_type -from six.moves.urllib.parse import urljoin - +from urllib.parse import urljoin from .wptmanifest.backends import static from .wptmanifest.backends.base import ManifestItem @@ -49,7 +47,7 @@ """List property""" try: list_prop = node.get(name) - if isinstance(list_prop, string_types): + if isinstance(list_prop, str): return [list_prop] return list(list_prop) except KeyError: @@ -59,7 +57,7 @@ def str_prop(name, node): try: prop = node.get(name) - if not isinstance(prop, string_types): + if not isinstance(prop, str): raise ValueError return prop except KeyError: @@ -70,7 +68,7 @@ """Set of tags that have been applied to the test""" try: value = node.get("tags") - if isinstance(value, text_type): + if isinstance(value, str): return {value} return set(value) except KeyError: @@ -79,7 +77,7 @@ def prefs(node): def value(ini_value): - if isinstance(ini_value, text_type): + if isinstance(ini_value, str): return tuple(pref_piece.strip() for pref_piece in ini_value.split(':', 1)) else: # this should be things like @Reset, which are apparently type 'object' @@ -87,7 +85,7 @@ try: node_prefs = node.get("prefs") - if isinstance(node_prefs, text_type): + if isinstance(node_prefs, str): rv = dict(value(node_prefs)) else: rv = dict(value(item) for item in node_prefs) @@ -99,7 +97,7 @@ def set_prop(name, node): try: node_items = node.get(name) - if isinstance(node_items, text_type): + if isinstance(node_items, str): rv = {node_items} else: rv = set(node_items) @@ -112,7 +110,7 @@ rv = {} try: node_items = node.get("leak-threshold") - if isinstance(node_items, text_type): + if isinstance(node_items, str): node_items = [node_items] for item in node_items: process, value = item.rsplit(":", 1) @@ -169,7 +167,7 @@ if not isinstance(value, list): value = [value] for item in value: - if not isinstance(item, text_type): + if not isinstance(item, str): rv.append(item) continue parts = item.rsplit(":", 1)
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/manifestinclude.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/manifestinclude.py index 79b5b19..97348e6 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/manifestinclude.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/manifestinclude.py
@@ -6,8 +6,7 @@ """ import glob import os -from six import iteritems -from six.moves.urllib.parse import urlparse, urlsplit +from urllib.parse import urlparse, urlsplit from .wptmanifest.node import DataNode from .wptmanifest.backends import conditional @@ -95,7 +94,7 @@ if paths: urls = [] for path in paths: - for manifest, data in iteritems(test_manifests): + for manifest, data in test_manifests.items(): found = False rel_path = os.path.relpath(path, data["tests_path"]) iterator = manifest.iterpath if os.path.isfile(path) else manifest.iterdir
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/manifestupdate.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/manifestupdate.py index c74632b0..5bccaa2d 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/manifestupdate.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/manifestupdate.py
@@ -1,9 +1,8 @@ from __future__ import print_function import os -from six.moves.urllib.parse import urljoin, urlsplit +from urllib.parse import urljoin, urlsplit from collections import namedtuple, defaultdict, deque from math import ceil -from six import integer_types, iterkeys, itervalues, iteritems, string_types, text_type from .wptmanifest import serialize from .wptmanifest.node import (DataNode, ConditionalNode, BinaryExpressionNode, @@ -76,7 +75,7 @@ return name in self._classes def __iter__(self): - for name in iterkeys(self._classes): + for name in self._classes.keys(): yield getattr(self, name) @@ -313,8 +312,8 @@ def build_unconditional_tree(_, run_info_properties, results): root = expectedtree.Node(None, None) - for run_info, values in iteritems(results): - for value, count in iteritems(values): + for run_info, values in results.items(): + for value, count in values.items(): root.result_values[value] += count root.run_info.add(run_info) return root @@ -411,7 +410,7 @@ for e in errors: if disable_intermittent: condition = e.cond.children[0] if e.cond else None - msg = disable_intermittent if isinstance(disable_intermittent, string_types+(text_type,)) else "unstable" + msg = disable_intermittent if isinstance(disable_intermittent, str) else "unstable" self.node.set("disabled", msg, condition) self.node.new_disabled = True else: @@ -499,7 +498,7 @@ for run_info in node.run_info} node_by_run_info = {run_info: node - for (run_info, node) in iteritems(run_info_index) + for (run_info, node) in run_info_index.items() if node.result_values} run_info_by_condition = self.run_info_by_condition(run_info_index, @@ -512,7 +511,7 @@ # using the properties we've specified and not matching any run_info top_level_props, dependent_props = self.node.root.run_info_properties update_properties = set(top_level_props) - for item in itervalues(dependent_props): + for item in dependent_props.values(): update_properties |= set(item) for condition in current_conditions: if ((not condition.variables.issubset(update_properties) and @@ -695,7 +694,7 @@ raise ConditionError counts = {} - for status, count in iteritems(new): + for status, count in new.items(): if isinstance(status, tuple): counts[status[0]] = count counts.update({intermittent: 0 for intermittent in status[1:] if intermittent not in counts}) @@ -709,9 +708,9 @@ # Counts with 0 are considered intermittent. statuses = ["OK", "PASS", "FAIL", "ERROR", "TIMEOUT", "CRASH"] status_priority = {value: i for i, value in enumerate(statuses)} - sorted_new = sorted(iteritems(counts), key=lambda x:(-1 * x[1], - status_priority.get(x[0], - len(status_priority)))) + sorted_new = sorted(counts.items(), key=lambda x:(-1 * x[1], + status_priority.get(x[0], + len(status_priority)))) expected = [] for status, count in sorted_new: # If we are not removing existing recorded intermittents, with a count of 0, @@ -777,7 +776,7 @@ for item in new: if item is None: continue - elif isinstance(item, text_type): + elif isinstance(item, str): rv.add(item) else: rv |= item @@ -825,7 +824,7 @@ return result def to_ini_value(self, data): - return ["%s:%s" % item for item in sorted(iteritems(data))] + return ["%s:%s" % item for item in sorted(data.items())] def from_ini_value(self, data): rv = {} @@ -900,10 +899,10 @@ def make_node(value): - if isinstance(value, integer_types+(float,)): + if isinstance(value, (int, float,)): node = NumberNode(value) - elif isinstance(value, text_type): - node = StringNode(text_type(value)) + elif isinstance(value, str): + node = StringNode(str(value)) elif hasattr(value, "__iter__"): node = ListNode() for item in value: @@ -912,10 +911,10 @@ def make_value_node(value): - if isinstance(value, integer_types+(float,)): + if isinstance(value, (int, float,)): node = ValueNode(value) - elif isinstance(value, text_type): - node = ValueNode(text_type(value)) + elif isinstance(value, str): + node = ValueNode(str(value)) elif hasattr(value, "__iter__"): node = ListNode() for item in value:
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/metadata.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/metadata.py index ab8d474..ddc433d 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/metadata.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/metadata.py
@@ -5,8 +5,8 @@ from collections import defaultdict, namedtuple from mozlog import structuredlog -from six import ensure_str, ensure_text, iteritems, iterkeys, itervalues, text_type -from six.moves import intern, range +from six import ensure_str, ensure_text +from sys import intern from . import manifestupdate from . import testloader @@ -45,11 +45,11 @@ return self.canonical_repr == other.canonical_repr def iteritems(self): - for key, value in iteritems(self.data): + for key, value in self.data.items(): yield key, value def items(self): - return list(iteritems(self)) + return list(self.items()) def update_expected(test_paths, serve_root, log_file_names, @@ -129,7 +129,7 @@ files_changed = set(files_changed) root_manifest = None - for manifest, paths in iteritems(manifests): + for manifest, paths in manifests.items(): if paths["url_base"] == "/": root_manifest = manifest break @@ -240,7 +240,7 @@ def unpack_result(data): if isinstance(data, int): return (status_intern.get(data), None) - if isinstance(data, text_type): + if isinstance(data, str): return (data, None) # Unpack multiple statuses into a tuple to be used in the Results named tuple below, # separating `status` and `known_intermittent`. @@ -259,7 +259,7 @@ manifests = manifest_loader.load() id_test_map = {} - for test_manifest, paths in iteritems(manifests): + for test_manifest, paths in manifests.items(): id_test_map.update(create_test_tree(paths["metadata_path"], test_manifest)) return id_test_map @@ -287,10 +287,10 @@ disable_intermittent, update_intermittent, remove_intermittent): - test_file_items = set(itervalues(id_test_map)) + test_file_items = set(id_test_map.values()) default_expected_by_type = {} - for test_type, test_cls in iteritems(wpttest.manifest_test_cls): + for test_type, test_cls in wpttest.manifest_test_cls.items(): if test_cls.result_cls: default_expected_by_type[(test_type, False)] = test_cls.result_cls.default_expected if test_cls.subtest_result_cls: @@ -431,7 +431,7 @@ action_map["lsan_leak"](item) mozleak_data = data.get("mozleak", {}) - for scope, scope_data in iteritems(mozleak_data): + for scope, scope_data in mozleak_data.items(): for key, action in [("objects", "mozleak_object"), ("total", "mozleak_total")]: for item in scope_data.get(key, []): @@ -668,11 +668,11 @@ # Return subtest nodes present in the expected file, but missing from the data rv = [] - for test_id, subtests in iteritems(self.data): + for test_id, subtests in self.data.items(): test = expected.get_test(ensure_text(test_id)) if not test: continue - seen_subtests = set(ensure_text(item) for item in iterkeys(subtests) if item is not None) + seen_subtests = set(ensure_text(item) for item in subtests.keys() if item is not None) missing_subtests = set(test.subtests.keys()) - seen_subtests for item in missing_subtests: expected_subtest = test.get_subtest(item) @@ -691,7 +691,7 @@ # since removing these may be inappropriate top_level_props, dependent_props = update_properties all_properties = set(top_level_props) - for item in itervalues(dependent_props): + for item in dependent_props.values(): all_properties |= set(item) filtered = [] @@ -741,9 +741,9 @@ test_expected = expected.get_test(test_id) expected_by_test[test_id] = test_expected - for test_id, test_data in iteritems(self.data): + for test_id, test_data in self.data.items(): test_id = ensure_str(test_id) - for subtest_id, results_list in iteritems(test_data): + for subtest_id, results_list in test_data.items(): for prop, run_info, value in results_list: # Special case directory metadata if subtest_id is None and test_id.endswith("__dir__"):
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/mpcontext.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/mpcontext.py index daade10..a50c0478 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/mpcontext.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/mpcontext.py
@@ -1,21 +1,11 @@ import multiprocessing -import six - _context = None -class MpContext(object): - def __getattr__(self, name): - return getattr(multiprocessing, name) - - def get_context(): global _context if _context is None: - if six.PY2: - _context = MpContext() - else: - _context = multiprocessing.get_context("spawn") + _context = multiprocessing.get_context("spawn") return _context
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/process.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/process.py index 8a2b894..d3ff380a 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/process.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/process.py
@@ -1,11 +1,8 @@ -import sys - import six def cast_env(env): - """Encode all the environment values as the appropriate type for each Python version + """Encode all the environment values as the appropriate type. This assumes that all the data is or can be represented as UTF8""" - env_type = six.ensure_binary if sys.version_info[0] < 3 else six.ensure_str - return {env_type(key): env_type(value) for key, value in six.iteritems(env)} + return {six.ensure_str(key): six.ensure_str(value) for key, value in env.items()}
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/products.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/products.py index abd8409..7ba30537 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/products.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/products.py
@@ -1,6 +1,5 @@ import importlib import imp -from six import iteritems from .browsers import product_list @@ -45,7 +44,7 @@ self.get_timeout_multiplier = getattr(module, data["timeout_multiplier"]) self.executor_classes = {} - for test_type, cls_name in iteritems(data["executor"]): + for test_type, cls_name in data["executor"].items(): cls = getattr(module, cls_name) self.executor_classes[test_type] = cls
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/stability.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/stability.py index 88d1c23..2265523 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/stability.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/stability.py
@@ -5,7 +5,6 @@ import os from collections import OrderedDict, defaultdict from datetime import datetime -from six import iteritems from mozlog import reader from mozlog.formatters import JSONFormatter @@ -142,10 +141,10 @@ handler = LogHandler() reader.handle_log(reader.read(log), handler) results = handler.results - for test_name, test in iteritems(results): + for test_name, test in results.items(): if is_inconsistent(test["status"], iterations): inconsistent.append((test_name, None, test["status"], [])) - for subtest_name, subtest in iteritems(test["subtests"]): + for subtest_name, subtest in test["subtests"].items(): if is_inconsistent(subtest["status"], iterations): inconsistent.append((test_name, subtest_name, subtest["status"], subtest["messages"])) @@ -235,7 +234,7 @@ "tests" if len(results) > 1 else "test")) - for test_name, test in iteritems(results): + for test_name, test in results.items(): baseurl = "http://w3c-test.org/submissions" if "https" in os.path.splitext(test_name)[0].split(".")[1:]: baseurl = "https://w3c-test.org/submissions" @@ -305,7 +304,7 @@ for kwargs_extra in kwargs_extras: if kwargs_extra: flags_string = " with flags %s" % " ".join( - "%s=%s" % item for item in iteritems(kwargs_extra)) + "%s=%s" % item for item in kwargs_extra.items()) else: flags_string = ""
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/testloader.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/testloader.py index e57619b4..346fe2a2 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/testloader.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/testloader.py
@@ -1,12 +1,11 @@ import hashlib import json import os -from six.moves.urllib.parse import urlsplit +from urllib.parse import urlsplit from abc import ABCMeta, abstractmethod -from six.moves.queue import Empty +from queue import Empty from collections import defaultdict, deque -from six import ensure_binary, iteritems -from six.moves import range +from six import ensure_binary from . import manifestinclude from . import manifestexpected @@ -41,7 +40,7 @@ raise self.group_by_test = {} - for group, test_ids in iteritems(self._data): + for group, test_ids in self._data.items(): for test_id in test_ids: self.group_by_test[test_id] = group @@ -51,6 +50,16 @@ def __getitem__(self, key): return self._data[key] +def read_include_from_file(file): + new_include = [] + with open(file) as f: + for line in f: + line = line.strip() + # Allow whole-line comments; + # fragments mean we can't have partial line #-based comments + if len(line) > 0 and not line.startswith("#"): + new_include.append(line) + return new_include def update_include_for_groups(test_groups, include): if include is None: @@ -173,7 +182,7 @@ def load(self): rv = {} - for url_base, paths in iteritems(self.test_paths): + for url_base, paths in self.test_paths.items(): manifest_file = self.load_manifest(url_base=url_base, **paths) path_data = {"url_base": url_base} @@ -472,7 +481,7 @@ mp = mpcontext.get_context() test_queue = mp.Queue() - for group_name, test_ids in iteritems(tests_by_group): + for group_name, test_ids in tests_by_group.items(): group_metadata = {"scope": group_name} group = deque()
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/testrunner.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/testrunner.py index 8dd9341..04221cb 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/testrunner.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/testrunner.py
@@ -2,7 +2,7 @@ import threading import traceback -from six.moves.queue import Empty +from queue import Empty from collections import namedtuple from mozlog import structuredlog, capture @@ -339,6 +339,7 @@ self.test_count = 0 self.unexpected_count = 0 + self.unexpected_pass_count = 0 # This may not really be what we want self.daemon = True @@ -361,7 +362,8 @@ spins.""" self.recording.set(["testrunner", "startup"]) self.logger = structuredlog.StructuredLogger(self.suite_name) - with self.browser_cls(self.logger, **self.browser_kwargs) as browser: + with self.browser_cls(self.logger, remote_queue=self.command_queue, + **self.browser_kwargs) as browser: self.browser = BrowserManager(self.logger, browser, self.command_queue, @@ -614,6 +616,9 @@ return if self.timer is not None: self.timer.cancel() + + self.browser.browser.maybe_parse_tombstone() + # Write the result of each subtest file_result, test_results = results subtest_unexpected = False @@ -634,6 +639,11 @@ self.unexpected_count += 1 self.logger.debug("Unexpected count in this thread %i" % self.unexpected_count) subtest_unexpected = True + + is_unexpected_pass = is_unexpected and result.status == "PASS" + if is_unexpected_pass: + self.unexpected_pass_count += 1 + self.logger.test_status(test.id, result.name, result.status, @@ -667,6 +677,10 @@ self.unexpected_count += 1 self.logger.debug("Unexpected count in this thread %i" % self.unexpected_count) + is_unexpected_pass = is_unexpected and status == "OK" + if is_unexpected_pass: + self.unexpected_pass_count += 1 + if "assertion_count" in file_result.extra: assertion_count = file_result.extra["assertion_count"] if assertion_count is not None and assertion_count > 0: @@ -775,14 +789,19 @@ # This might leak a file handle from the queue self.logger.warning("Forcibly terminating runner process") self.test_runner_proc.terminate() + self.logger.debug("After terminating runner process") # Multiprocessing queues are backed by operating system pipes. If # the pipe in the child process had buffered data at the time of # forced termination, the queue is no longer in a usable state # (subsequent attempts to retrieve items may block indefinitely). # Discard the potentially-corrupted queue and create a new one. + self.logger.debug("Recreating command queue") + self.command_queue.cancel_join_thread() self.command_queue.close() self.command_queue = mp.Queue() + self.logger.debug("Recreating remote queue") + self.remote_queue.cancel_join_thread() self.remote_queue.close() self.remote_queue = mp.Queue() else: @@ -925,3 +944,6 @@ def unexpected_count(self): return sum(manager.unexpected_count for manager in self.pool) + + def unexpected_pass_count(self): + return sum(manager.unexpected_pass_count for manager in self.pool)
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/update/state.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/update/state.py index 6b6ff1a..a526c24 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/update/state.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/update/state.py
@@ -1,5 +1,5 @@ import os -from six.moves import cPickle as pickle # noqa: N813 +import pickle here = os.path.abspath(os.path.dirname(__file__))
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/update/sync.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/update/sync.py index f878752..4ace28f 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/update/sync.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/update/sync.py
@@ -67,7 +67,7 @@ state.local_branch) sync_path = os.path.abspath(sync_tree.root) if sync_path not in sys.path: - from update import setup_paths + from .update import setup_paths setup_paths(sync_path) def restore(self, state):
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/update/tree.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/update/tree.py index f362770..2f43bac 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/update/tree.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/update/tree.py
@@ -3,8 +3,6 @@ import subprocess import tempfile -from six.moves import range - from .. import vcs from ..vcs import git, hg @@ -87,7 +85,7 @@ @property def is_clean(self): - return self.hg("status").strip() == "" + return self.hg("status").strip() == b"" def add_new(self, prefix=None): if prefix is not None: @@ -105,7 +103,7 @@ except subprocess.CalledProcessError: pass - patch_names = [item.strip() for item in self.hg("qseries").split("\n") if item.strip()] + patch_names = [item.strip() for item in self.hg("qseries").split(b"\n") if item.strip()] suffix = 0 test_name = patch_name @@ -142,7 +140,7 @@ def __init__(self, root=None, log_error=True): if root is None: - root = git("rev-parse", "--show-toplevel", log_error=log_error).strip() + root = git("rev-parse", "--show-toplevel", log_error=log_error).strip().decode('utf-8') self.root = root self.git = vcs.bind_to_repo(git, self.root, log_error=log_error) self.message = None @@ -178,7 +176,7 @@ @property def is_clean(self): - return self.git("status").strip() == "" + return self.git("status").strip() == b"" def add_new(self, prefix=None): """Add files to the staging area. @@ -203,7 +201,7 @@ f.seek(0) ignored_files = sync_tree.git("check-ignore", "--no-index", "--stdin", "-z", stdin=f) args = [] - for entry in ignored_files.split('\0'): + for entry in ignored_files.decode('utf-8').split('\0'): args.append(os.path.join(prefix, entry)) if args: self.git("add", "--force", *args) @@ -219,7 +217,7 @@ args.append(ref_filter) data = self.git("show-ref", *args) rv = [] - for line in data.split("\n"): + for line in data.split(b"\n"): if not line.strip(): continue sha1, ref = line.split() @@ -237,7 +235,7 @@ args.append(ref_filter) data = self.git("ls-remote", remote, *args) rv = [] - for line in data.split("\n"): + for line in data.split(b"\n"): if not line.strip(): continue sha1, ref = line.split() @@ -250,8 +248,8 @@ :param remote: the remote URL :param branch: the branch name""" for sha1, ref in self.list_remote(remote, branch): - if ref == "refs/heads/%s" % branch: - return self.commit_cls(self, sha1) + if ref.decode('utf-8') == "refs/heads/%s" % branch: + return self.commit_cls(self, sha1.decode('utf-8')) assert False def create_patch(self, patch_name, message): @@ -299,8 +297,8 @@ args = [] if branch: - branches = [ref[len("refs/heads/"):] for sha1, ref in self.list_refs() - if ref.startswith("refs/heads/")] + branches = [ref[len("refs/heads/"):].decode('utf-8') for sha1, ref in self.list_refs() + if ref.startswith(b"refs/heads/")] branch = get_unique_name(branches, branch) args += ["-b", branch] @@ -336,8 +334,8 @@ rv = [] for repo_path in repo_paths: - paths = vcs.git("ls-tree", "-r", "--name-only", "HEAD", repo=repo_path).split("\n") - rv.extend(os.path.relpath(os.path.join(repo_path, item), self.root) for item in paths + paths = vcs.git("ls-tree", "-r", "--name-only", "HEAD", repo=repo_path).split(b"\n") + rv.extend(os.path.relpath(os.path.join(repo_path, item.decode('utf-8')), self.root) for item in paths if item.strip()) return rv @@ -345,11 +343,11 @@ """List submodule directories""" output = self.git("submodule", "status", "--recursive") rv = [] - for line in output.split("\n"): + for line in output.split(b"\n"): line = line.strip() if not line: continue - parts = line.split(" ") + parts = line.split(b" ") rv.append(parts[1]) return rv @@ -403,5 +401,5 @@ self.git = self.tree.git def _get_meta(self): - author, email, message = self.git("show", "-s", "--format=format:%an\n%ae\n%B", self.sha1).split("\n", 2) + author, email, message = self.git("show", "-s", "--format=format:%an\n%ae\n%B", self.sha1).decode('utf-8').split("\n", 2) return author, email, self.msg_cls(message)
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/update/update.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/update/update.py index 80e509d..265a331 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/update/update.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/update/update.py
@@ -1,8 +1,6 @@ import os import sys -from six import itervalues - from .metadata import MetadataUpdateRunner from .sync import SyncFromUpstreamRunner from .tree import GitTree, HgTree, NoVCSTree @@ -111,7 +109,7 @@ state.tests_path = state.paths["/"]["tests_path"] state.metadata_path = state.paths["/"]["metadata_path"] - for url_paths in itervalues(paths): + for url_paths in paths.values(): tests_path = url_paths["tests_path"] metadata_path = url_paths["metadata_path"] for dirpath, dirnames, filenames in os.walk(metadata_path):
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wptcommandline.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wptcommandline.py index 2b6d4b35..90edd64 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wptcommandline.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wptcommandline.py
@@ -5,7 +5,7 @@ from collections import OrderedDict from distutils.spawn import find_executable from datetime import timedelta -from six import ensure_text, iterkeys, itervalues, iteritems +from six import ensure_text from . import config from . import wpttest @@ -16,7 +16,7 @@ def url_or_path(path): - from six.moves.urllib.parse import urlparse + from urllib.parse import urlparse parsed = urlparse(path) if len(parsed.scheme) > 2: @@ -72,6 +72,10 @@ default=True, dest="fail_on_unexpected", help="Exit with status code 0 when test expectations are violated") + parser.add_argument("--no-fail-on-unexpected-pass", action="store_false", + default=True, + dest="fail_on_unexpected_pass", + help="Exit with status code 0 when all unexpected results are PASS") mode_group = parser.add_argument_group("Mode") mode_group.add_argument("--list-test-groups", action="store_true", @@ -131,6 +135,8 @@ help="Test types to run") test_selection_group.add_argument("--include", action="append", help="URL prefix to include") + test_selection_group.add_argument("--include-file", action="store", + help="A file listing URL prefix for tests") test_selection_group.add_argument("--exclude", action="append", help="URL prefix to exclude") test_selection_group.add_argument("--include-manifest", type=abs_path, @@ -183,7 +189,10 @@ help="Path or url to symbols file used to analyse crash minidumps.") debugging_group.add_argument("--stackwalk-binary", action="store", type=abs_path, help="Path to stackwalker program used to analyse minidumps.") - + debugging_group.add_argument("--output-directory", action="store", + help="Path to chromium output directory.") + debugging_group.add_argument("--stackparser-script", action="store", type=abs_path, + help="Path to stack parser script used to analyse tombstones.") debugging_group.add_argument("--pdb", action="store_true", help="Drop into pdb on python exception") @@ -367,6 +376,10 @@ webkit_group.add_argument("--webkit-port", dest="webkit_port", help="WebKit port") + safari_group = parser.add_argument_group("Safari-specific") + safari_group.add_argument("--kill-safari", dest="kill_safari", action="store_true", default=False, + help="Kill Safari when stopping the browser") + parser.add_argument("test_list", nargs="*", help="List of URLs for tests to run, or paths including tests to run. " "(equivalent to --include)") @@ -408,7 +421,7 @@ ("host_cert_path", "host_cert_path", True), ("host_key_path", "host_key_path", True)]} - for section, values in iteritems(keys): + for section, values in keys.items(): for config_value, kw_value, is_path in values: if kw_value in kwargs and kwargs[kw_value] is None: if not is_path: @@ -444,7 +457,7 @@ # Set up test_paths test_paths = OrderedDict() - for section in iterkeys(config): + for section in config.keys(): if section.startswith("manifest:"): manifest_opts = config.get(section) url_base = manifest_opts.get("url_base", "/") @@ -470,7 +483,7 @@ def check_paths(kwargs): - for test_paths in itervalues(kwargs["test_paths"]): + for test_paths in kwargs["test_paths"].values(): if not ("tests_path" in test_paths and "metadata_path" in test_paths): print("Fatal: must specify both a test path and metadata path") @@ -478,7 +491,7 @@ if "manifest_path" not in test_paths: test_paths["manifest_path"] = os.path.join(test_paths["metadata_path"], "MANIFEST.json") - for key, path in iteritems(test_paths): + for key, path in test_paths.items(): name = key.split("_", 1)[0] if name == "manifest":
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wptmanifest/backends/base.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wptmanifest/backends/base.py index c539d43..3069e4c 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wptmanifest/backends/base.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wptmanifest/backends/base.py
@@ -1,5 +1,4 @@ import abc -from six import iteritems, iterkeys, itervalues from ..node import NodeVisitor from ..parser import parse @@ -187,21 +186,21 @@ def _flatten(self): rv = {} for node in [self, self.root]: - for name, value in iteritems(node._data): + for name, value in node._data.items(): if name not in rv: rv[name] = value return rv def iteritems(self): - for item in iteritems(self._flatten()): + for item in self._flatten().items(): yield item def iterkeys(self): - for item in iterkeys(self._flatten()): + for item in self._flatten().keys(): yield item def itervalues(self): - for item in itervalues(self._flatten()): + for item in self._flatten().values(): yield item def append(self, child):
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wptmanifest/backends/conditional.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wptmanifest/backends/conditional.py index 3b11e83..30dd144 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wptmanifest/backends/conditional.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wptmanifest/backends/conditional.py
@@ -1,5 +1,5 @@ import operator -from six import ensure_text, iteritems, iterkeys, text_type +from six import ensure_text from ..node import NodeVisitor, DataNode, ConditionalNode, KeyValueNode, ListNode, ValueNode, BinaryExpressionNode, VariableNode from ..parser import parse @@ -300,9 +300,9 @@ if isinstance(value, list): value_node = ListNode() for item in value: - value_node.append(ValueNode(text_type(item))) + value_node.append(ValueNode(str(item))) else: - value_node = ValueNode(text_type(value)) + value_node = ValueNode(str(value)) if condition is not None: if not isinstance(condition, ConditionalNode): conditional_node = ConditionalNode() @@ -368,17 +368,17 @@ def _flatten(self): rv = {} for node in [self, self.root]: - for name, value in iteritems(node._data): + for name, value in node._data.items(): if name not in rv: rv[name] = value return rv def iteritems(self): - for item in iteritems(self._flatten()): + for item in self._flatten().items(): yield item def iterkeys(self): - for item in iterkeys(self._flatten()): + for item in self._flatten().keys(): yield item def iter_properties(self):
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wptmanifest/node.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wptmanifest/node.py index 0f82d70..5e9d2b6 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wptmanifest/node.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wptmanifest/node.py
@@ -1,5 +1,3 @@ -from six.moves import range - class NodeVisitor(object): def visit(self, node): # This is ugly as hell, but we don't have multimethods and
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wptmanifest/parser.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wptmanifest/parser.py index 911efac80..f6ae1e2 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wptmanifest/parser.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wptmanifest/parser.py
@@ -14,8 +14,7 @@ from __future__ import unicode_literals -from six import binary_type, text_type, BytesIO, unichr -from six.moves import range +from io import BytesIO from .node import (Node, AtomNode, BinaryExpressionNode, BinaryOperatorNode, ConditionalNode, DataNode, IndexNode, KeyValueNode, ListNode, @@ -50,7 +49,7 @@ "Reset": object()} def decode(s): - assert isinstance(s, text_type) + assert isinstance(s, str) return s @@ -79,7 +78,7 @@ def tokenize(self, stream): self.reset() - assert not isinstance(stream, text_type) + assert not isinstance(stream, str) if isinstance(stream, bytes): stream = BytesIO(stream) if not hasattr(stream, "name"): @@ -89,7 +88,7 @@ self.next_line_state = self.line_start_state for i, line in enumerate(stream): - assert isinstance(line, binary_type) + assert isinstance(line, bytes) self.state = self.next_line_state assert self.state is not None states = [] @@ -97,7 +96,7 @@ self.line_number = i + 1 self.index = 0 self.line = line.decode('utf-8').rstrip() - assert isinstance(self.line, text_type) + assert isinstance(self.line, str) while self.state != self.eol_state: states.append(self.state) tokens = self.state() @@ -505,7 +504,7 @@ value += self.escape_value(c) self.consume() - return unichr(value) + return chr(value) def escape_value(self, c): if '0' <= c <= '9':
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wptrunner.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wptrunner.py index 7182510..bb1e570e 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wptrunner.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wptrunner.py
@@ -4,8 +4,6 @@ import os import sys -from six import iteritems, itervalues - import wptserve from wptserve import sslutils @@ -67,6 +65,8 @@ manifest_filters = [] include = kwargs["include"] + if kwargs["include_file"]: + include.extend(testloader.read_include_from_file(kwargs["include_file"])) if test_groups: include = testloader.update_include_for_groups(test_groups, include) @@ -117,7 +117,7 @@ run_info, test_loader = get_loader(test_paths, product, run_info_extras=run_info_extras, **kwargs) - for test_type, tests in iteritems(test_loader.disabled_tests): + for test_type, tests in test_loader.disabled_tests.items(): for test in tests: rv.append({"test": test.id, "reason": test.disabled()}) print(json.dumps(rv, indent=2)) @@ -144,7 +144,7 @@ if kwargs["debug_test"]: return True tests = test_loader.tests - is_single_testharness = (sum(len(item) for item in itervalues(tests)) == 1 and + is_single_testharness = (sum(len(item) for item in tests.values()) == 1 and len(tests.get("testharness", [])) == 1) if kwargs["repeat"] == 1 and kwargs["rerun"] == 1 and is_single_testharness: return True @@ -201,6 +201,7 @@ skipped_tests = 0 test_total = 0 unexpected_total = 0 + unexpected_pass_total = 0 if len(test_loader.test_ids) == 0 and kwargs["test_list"]: logger.critical("Unable to find any tests at the path(s):") @@ -255,6 +256,7 @@ test_count = 0 unexpected_count = 0 + unexpected_pass_count = 0 tests = [] for test_type in test_loader.test_types: @@ -345,10 +347,13 @@ raise test_count += manager_group.test_count() unexpected_count += manager_group.unexpected_count() + unexpected_pass_count += manager_group.unexpected_pass_count() recording.set(["after-end"]) test_total += test_count unexpected_total += unexpected_count - logger.info("Got %i unexpected results" % unexpected_count) + unexpected_pass_total += unexpected_pass_count + logger.info("Got %i unexpected results, with %i unexpected passes" % + (unexpected_count, unexpected_pass_count)) logger.suite_end() if repeat_until_unexpected and unexpected_total > 0: break @@ -370,6 +375,13 @@ logger.info("Tolerating %s unexpected results" % unexpected_total) return True + all_unexpected_passed = (unexpected_total and + unexpected_total == unexpected_pass_total) + if all_unexpected_passed and not kwargs["fail_on_unexpected_pass"]: + logger.info("Tolerating %i unexpected results because they all PASS" % + unexpected_pass_total) + return True + return unexpected_total == 0
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wpttest.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wpttest.py index ed9184e..b7a7cec1 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wpttest.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wpttest.py
@@ -1,9 +1,8 @@ import os import subprocess import sys -from six.moves.urllib.parse import urljoin from collections import defaultdict -from six import iteritems, string_types +from urllib.parse import urljoin from .wptmanifest.parser import atoms @@ -307,7 +306,7 @@ rv = {} for meta in self.itermeta(None): threshold = meta.leak_threshold - for key, value in iteritems(threshold): + for key, value in threshold.items(): if key not in rv: rv[key] = value return rv @@ -349,7 +348,7 @@ try: expected = metadata.get("expected") - if isinstance(expected, string_types): + if isinstance(expected, str): return expected elif isinstance(expected, list): return expected[0]
diff --git a/third_party/wpt_tools/wpt/tools/wptserve/wptserve/config.py b/third_party/wpt_tools/wpt/tools/wptserve/wptserve/config.py index 4d653f5..843f6e6 100644 --- a/third_party/wpt_tools/wpt/tools/wptserve/wptserve/config.py +++ b/third_party/wpt_tools/wpt/tools/wptserve/wptserve/config.py
@@ -2,9 +2,7 @@ import logging import os from collections import defaultdict - -from six.moves.collections_abc import Mapping -from six import integer_types, iteritems, itervalues, string_types +from collections.abc import Mapping from . import sslutils from .utils import get_port @@ -20,7 +18,7 @@ def _merge_dict(base_dict, override_dict): rv = base_dict.copy() - for key, value in iteritems(base_dict): + for key, value in base_dict.items(): if key in override_dict: if isinstance(value, dict): rv[key] = _merge_dict(value, override_dict[key]) @@ -89,7 +87,7 @@ target = target[part] value = target[key[-1]] if isinstance(value, dict): - target[key[-1]] = {k:v for (k,v) in iteritems(value) if not k.startswith("op")} + target[key[-1]] = {k:v for (k,v) in value.items() if not k.startswith("op")} else: target[key[-1]] = [x for x in value if not x.startswith("op")] @@ -98,9 +96,9 @@ def json_types(obj): if isinstance(obj, dict): - return {key: json_types(value) for key, value in iteritems(obj)} - if (isinstance(obj, string_types) or - isinstance(obj, integer_types) or + return {key: json_types(value) for key, value in obj.items()} + if (isinstance(obj, str) or + isinstance(obj, int) or isinstance(obj, float) or isinstance(obj, bool) or obj is None): @@ -203,13 +201,13 @@ self.log_level = level_name self._logger_name = logger.name - for k, v in iteritems(self._default): + for k, v in self._default.items(): self._data[k] = kwargs.pop(k, v) self._data["subdomains"] = subdomains self._data["not_subdomains"] = not_subdomains - for k, new_k in iteritems(_renamed_props): + for k, new_k in _renamed_props.items(): if k in kwargs: self.logger.warning( "%s in config is deprecated; use %s instead" % ( @@ -242,7 +240,7 @@ if k in override: self._set_override(k, override.pop(k)) - for k, new_k in iteritems(_renamed_props): + for k, new_k in _renamed_props.items(): if k in override: self.logger.warning( "%s in config is deprecated; use %s instead" % ( @@ -287,7 +285,7 @@ def _get_ports(self, data): new_ports = defaultdict(list) - for scheme, ports in iteritems(data["ports"]): + for scheme, ports in data["ports"].items(): if scheme in ["wss", "https"] and not sslutils.get_cls(data["ssl"]["type"]).ssl_enabled: continue for i, port in enumerate(ports): @@ -301,7 +299,7 @@ hosts[""] = data["browser_host"] rv = {} - for name, host in iteritems(hosts): + for name, host in hosts.items(): rv[name] = {subdomain: (subdomain.encode("idna").decode("ascii") + u"." + host) for subdomain in data["subdomains"]} rv[name][""] = host @@ -313,7 +311,7 @@ hosts[""] = data["browser_host"] rv = {} - for name, host in iteritems(hosts): + for name, host in hosts.items(): rv[name] = {subdomain: (subdomain.encode("idna").decode("ascii") + u"." + host) for subdomain in data["not_subdomains"]} return rv @@ -327,13 +325,13 @@ def _get_domains_set(self, data): return {domain - for per_host_domains in itervalues(data["domains"]) - for domain in itervalues(per_host_domains)} + for per_host_domains in data["domains"].values() + for domain in per_host_domains.values()} def _get_not_domains_set(self, data): return {domain - for per_host_domains in itervalues(data["not_domains"]) - for domain in itervalues(per_host_domains)} + for per_host_domains in data["not_domains"].values() + for domain in per_host_domains.values()} def _get_all_domains_set(self, data): return data["domains_set"] | data["not_domains_set"]
diff --git a/third_party/wpt_tools/wpt/tools/wptserve/wptserve/handlers.py b/third_party/wpt_tools/wpt/tools/wptserve/wptserve/handlers.py index 0fc11c19..9eb4a44c 100644 --- a/third_party/wpt_tools/wpt/tools/wptserve/wptserve/handlers.py +++ b/third_party/wpt_tools/wpt/tools/wptserve/wptserve/handlers.py
@@ -3,8 +3,7 @@ import traceback from collections import defaultdict -from six.moves.urllib.parse import quote, unquote, urljoin -from six import iteritems +from urllib.parse import quote, unquote, urljoin from .constants import content_types from .pipes import Pipeline, template @@ -482,7 +481,7 @@ self.data = data self.resp_headers = [("Content-Type", content_type)] - for k, v in iteritems(headers): + for k, v in headers.items(): self.resp_headers.append((k.replace("_", "-"), v)) self.handler = handler(self.handle_request)
diff --git a/third_party/wpt_tools/wpt/tools/wptserve/wptserve/pipes.py b/third_party/wpt_tools/wpt/tools/wptserve/wptserve/pipes.py index bbf25e6f..6845c33 100644 --- a/third_party/wpt_tools/wpt/tools/wptserve/wptserve/pipes.py +++ b/third_party/wpt_tools/wpt/tools/wptserve/wptserve/pipes.py
@@ -7,8 +7,7 @@ import time import uuid -from six.moves import StringIO -from six import text_type, binary_type +from io import BytesIO try: from html import escape @@ -305,7 +304,7 @@ return ("var", token) def tokenize(self, string): - assert isinstance(string, binary_type) + assert isinstance(string, bytes) return self.scanner.scan(string)[0] scanner = re.Scanner([(br"\$\w+:", var), @@ -320,7 +319,7 @@ def __getitem__(self, key): try: - if isinstance(key, text_type): + if isinstance(key, str): key = key.encode('iso-8859-1') return self.params.first(key) except KeyError: @@ -408,7 +407,7 @@ @staticmethod def file_hash(request, algorithm, path): - assert isinstance(algorithm, text_type) + assert isinstance(algorithm, str) if algorithm not in SubFunctions.supported_algorithms: raise ValueError("Unsupported encryption algorithm: '%s'" % algorithm) @@ -460,12 +459,12 @@ tokens = deque(tokens) token_type, field = tokens.popleft() - assert isinstance(field, text_type) + assert isinstance(field, str) if token_type == "var": variable = field token_type, field = tokens.popleft() - assert isinstance(field, text_type) + assert isinstance(field, str) else: variable = None @@ -516,7 +515,7 @@ "unexpected token type %s (token '%r'), expected ident or arguments" % (ttype, field) ) - assert isinstance(value, (int, (binary_type, text_type))), tokens + assert isinstance(value, (int, (bytes, str))), tokens if variable is not None: variables[variable] = value @@ -527,10 +526,10 @@ # Should possibly support escaping for other contexts e.g. script # TODO: read the encoding of the response # cgi.escape() only takes text strings in Python 3. - if isinstance(value, binary_type): + if isinstance(value, bytes): value = value.decode("utf-8") elif isinstance(value, int): - value = text_type(value) + value = str(value) return escape_func(value).encode("utf-8") template_regexp = re.compile(br"{{([^}]*)}}") @@ -549,7 +548,7 @@ content = resolve_content(response) response.headers.set("Content-Encoding", "gzip") - out = StringIO() + out = BytesIO() with gzip_module.GzipFile(fileobj=out, mode="w") as f: f.write(content) response.content = out.getvalue()
diff --git a/third_party/wpt_tools/wpt/tools/wptserve/wptserve/request.py b/third_party/wpt_tools/wpt/tools/wptserve/wptserve/request.py index dbfe067..76644cc49 100644 --- a/third_party/wpt_tools/wpt/tools/wptserve/wptserve/request.py +++ b/third_party/wpt_tools/wpt/tools/wptserve/wptserve/request.py
@@ -2,9 +2,9 @@ import cgi import tempfile -from six import BytesIO, binary_type, iteritems, PY3 -from six.moves.http_cookies import BaseCookie -from six.moves.urllib.parse import parse_qsl, urlsplit +from http.cookies import BaseCookie +from io import BytesIO +from urllib.parse import parse_qsl, urlsplit from . import stash from .utils import HTTPException, isomorphic_encode, isomorphic_decode @@ -301,9 +301,8 @@ if self._GET is None: kwargs = { "keep_blank_values": True, + "encoding": "iso-8859-1", } - if PY3: - kwargs["encoding"] = "iso-8859-1" params = parse_qsl(self.url_parts.query, **kwargs) self._GET = MultiDict() for key, value in params: @@ -321,9 +320,8 @@ "environ": {"REQUEST_METHOD": self.method}, "headers": self.raw_headers, "keep_blank_values": True, + "encoding": "iso-8859-1", } - if PY3: - kwargs["encoding"] = "iso-8859-1" fs = cgi.FieldStorage(**kwargs) self._POST = MultiDict.from_field_storage(fs) self.raw_input.seek(pos) @@ -336,7 +334,7 @@ cookie_headers = self.headers.get("cookie", b"") parser.load(cookie_headers) cookies = Cookies() - for key, value in iteritems(parser): + for key, value in parser.items(): cookies[isomorphic_encode(key)] = CookieValue(value) self._cookies = cookies return self._cookies @@ -630,11 +628,9 @@ This overrides and calls BaseCookie.load. Unlike BaseCookie.load, it does not accept dictionaries. """ - assert isinstance(rawdata, binary_type) - if PY3: - # BaseCookie.load expects a native string, which in Python 3 is text. - rawdata = isomorphic_decode(rawdata) - super(BinaryCookieParser, self).load(rawdata) + assert isinstance(rawdata, bytes) + # BaseCookie.load expects a native string + super(BinaryCookieParser, self).load(isomorphic_decode(rawdata)) class Cookies(MultiDict): @@ -675,7 +671,7 @@ if "authorization" in headers: header = headers.get("authorization") - assert isinstance(header, binary_type) + assert isinstance(header, bytes) auth_type, data = header.split(b" ", 1) if auth_type in auth_schemes: self.username, self.password = auth_schemes[auth_type](data) @@ -683,6 +679,6 @@ raise HTTPException(400, "Unsupported authentication scheme %s" % auth_type) def decode_basic(self, data): - assert isinstance(data, binary_type) + assert isinstance(data, bytes) decoded_data = base64.b64decode(data) return decoded_data.split(b":", 1)
diff --git a/third_party/wpt_tools/wpt/tools/wptserve/wptserve/response.py b/third_party/wpt_tools/wpt/tools/wptserve/wptserve/response.py index 6e5ee11..8763cca 100644 --- a/third_party/wpt_tools/wpt/tools/wptserve/wptserve/response.py +++ b/third_party/wpt_tools/wpt/tools/wptserve/wptserve/response.py
@@ -6,9 +6,8 @@ import uuid from hpack.struct import HeaderTuple +from http.cookies import BaseCookie, Morsel from hyperframe.frame import HeadersFrame, DataFrame, ContinuationFrame -from six import binary_type, text_type, integer_types, itervalues, PY3 -from six.moves.http_cookies import BaseCookie, Morsel from .constants import response_codes, h2_headers from .logger import get_logger @@ -91,7 +90,7 @@ message = value[1] # Only call str() if message is not a string type, so that we # don't get `str(b"foo") == "b'foo'"` in Python 3. - if not isinstance(message, (binary_type, text_type)): + if not isinstance(message, (bytes, str)): message = str(message) self._status = (code, message) else: @@ -122,9 +121,8 @@ max_age = 0 expires = timedelta(days=-1) - if PY3: - name = isomorphic_decode(name) - value = isomorphic_decode(value) + name = isomorphic_decode(name) + value = isomorphic_decode(value) days = {i+1: name for i, name in enumerate(["jan", "feb", "mar", "apr", "may", "jun", @@ -163,15 +161,11 @@ def unset_cookie(self, name): """Remove a cookie from those that are being sent with the response""" - if PY3: - name = isomorphic_decode(name) + name = isomorphic_decode(name) cookies = self.headers.get("Set-Cookie") parser = BaseCookie() for cookie in cookies: - if PY3: - # BaseCookie.load expects a text string. - cookie = isomorphic_decode(cookie) - parser.load(cookie) + parser.load(isomorphic_decode(cookie)) if name in parser.keys(): del self.headers["Set-Cookie"] @@ -199,9 +193,9 @@ string facilitating non-streaming operations like template substitution. """ - if isinstance(self.content, binary_type): + if isinstance(self.content, bytes): yield self.content - elif isinstance(self.content, text_type): + elif isinstance(self.content, str): yield self.content.encode(self.encoding) elif hasattr(self.content, "read"): if read_file: @@ -256,7 +250,7 @@ def __init__(self, boundary=None, default_content_type=None): self.items = [] if boundary is None: - boundary = text_type(uuid.uuid4()) + boundary = str(uuid.uuid4()) self.boundary = boundary self.default_content_type = default_content_type @@ -284,7 +278,7 @@ class MultipartPart(object): def __init__(self, data, content_type=None, headers=None): - assert isinstance(data, binary_type), data + assert isinstance(data, bytes), data self.headers = ResponseHeaders() if content_type is not None: @@ -303,8 +297,8 @@ def to_bytes(self): rv = [] for key, value in self.headers: - assert isinstance(key, binary_type) - assert isinstance(value, binary_type) + assert isinstance(key, bytes) + assert isinstance(value, bytes) rv.append(b"%s: %s" % (key, value)) rv.append(b"") rv.append(self.data) @@ -313,7 +307,7 @@ def _maybe_encode(s): """Encode a string or an int into binary data using isomorphic_encode().""" - if isinstance(s, integer_types): + if isinstance(s, int): return b"%i" % (s,) return isomorphic_encode(s) @@ -377,7 +371,7 @@ self.set(key, value) def __iter__(self): - for key, values in itervalues(self.data): + for key, values in self.data.values(): for value in values: yield key, value @@ -447,10 +441,10 @@ for header, value in headers: # h2_headers are native strings # header field names are strings of ASCII - if isinstance(header, binary_type): + if isinstance(header, bytes): header = header.decode('ascii') # value in headers can be either string or integer - if isinstance(value, binary_type): + if isinstance(value, bytes): value = self.decode(value) if header in h2_headers: header = ':' + header @@ -482,7 +476,7 @@ :param last: Flag to signal if this is the last frame in stream. :param stream_id: Id of stream to send frame on. Will use the request stream ID if None """ - if isinstance(item, (text_type, binary_type)): + if isinstance(item, (str, bytes)): data = BytesIO(self.encode(item)) else: data = item @@ -638,18 +632,18 @@ def decode(self, data): """Convert bytes to unicode according to response.encoding.""" - if isinstance(data, binary_type): + if isinstance(data, bytes): return data.decode(self._response.encoding) - elif isinstance(data, text_type): + elif isinstance(data, str): return data else: raise ValueError(type(data)) def encode(self, data): """Convert unicode to bytes according to response.encoding.""" - if isinstance(data, binary_type): + if isinstance(data, bytes): return data - elif isinstance(data, text_type): + elif isinstance(data, str): return data.encode(self._response.encoding) else: raise ValueError @@ -707,7 +701,7 @@ if not self.write(b": "): return False if isinstance(value, int): - if not self.write(text_type(value)): + if not self.write(str(value)): return False elif not self.write(value): return False @@ -720,7 +714,7 @@ if not self.write_header(name, f()): return False - if (isinstance(self._response.content, (binary_type, text_type)) and + if (isinstance(self._response.content, (bytes, str)) and not self._seen_header("content-length")): #Would be nice to avoid double-encoding here if not self.write_header("Content-Length", len(self.encode(self._response.content))): @@ -767,7 +761,7 @@ """Writes the data 'as is'""" if data is None: raise ValueError('data cannot be None') - if isinstance(data, (text_type, binary_type)): + if isinstance(data, (str, bytes)): # Deliberately allows both text and binary types. See `self.encode`. return self.write(data) else: @@ -805,9 +799,9 @@ def encode(self, data): """Convert unicode to bytes according to response.encoding.""" - if isinstance(data, binary_type): + if isinstance(data, bytes): return data - elif isinstance(data, text_type): + elif isinstance(data, str): return data.encode(self._response.encoding) else: raise ValueError("data %r should be text or binary, but is %s" % (data, type(data)))
diff --git a/third_party/wpt_tools/wpt/tools/wptserve/wptserve/router.py b/third_party/wpt_tools/wpt/tools/wptserve/wptserve/router.py index d1704a7..5a91de30 100644 --- a/third_party/wpt_tools/wpt/tools/wptserve/wptserve/router.py +++ b/third_party/wpt_tools/wpt/tools/wptserve/wptserve/router.py
@@ -3,7 +3,6 @@ import sys from .logger import get_logger -from six import binary_type, text_type any_method = object() @@ -146,7 +145,7 @@ object and the response object. """ - if isinstance(methods, (binary_type, text_type)) or methods is any_method: + if isinstance(methods, (bytes, str)) or methods is any_method: methods = [methods] for method in methods: self.routes.append((method, compile_path_match(path), handler))
diff --git a/third_party/wpt_tools/wpt/tools/wptserve/wptserve/server.py b/third_party/wpt_tools/wpt/tools/wptserve/wptserve/server.py index 2b5ed4a2..cfa86f99 100644 --- a/third_party/wpt_tools/wpt/tools/wptserve/wptserve/server.py +++ b/third_party/wpt_tools/wpt/tools/wptserve/wptserve/server.py
@@ -1,18 +1,16 @@ -from six.moves import BaseHTTPServer import errno +import http.server import os import socket -from six.moves.socketserver import ThreadingMixIn +from socketserver import ThreadingMixIn import ssl import sys import threading import time import traceback -from six import binary_type, text_type import uuid from collections import OrderedDict - -from six.moves.queue import Queue +from queue import Queue from h2.config import H2Configuration from h2.connection import H2Connection @@ -21,7 +19,7 @@ from h2.settings import SettingCodes from h2.utilities import extract_method_header -from six.moves.urllib.parse import urlsplit, urlunsplit +from urllib.parse import urlsplit, urlunsplit from mod_pywebsocket import dispatch from mod_pywebsocket.handshake import HandshakeException @@ -38,13 +36,12 @@ # We need to stress test that browsers can send/receive many headers (there is # no specified limit), but the Python stdlib has an arbitrary limit of 100 -# headers. Hitting the limit would produce an exception that is silently caught -# in Python 2 but leads to HTTP 431 in Python 3, so we monkey patch it higher. +# headers. Hitting the limit leads to HTTP 431, so we monkey patch it higher. # https://bugs.python.org/issue26586 # https://github.com/web-platform-tests/wpt/pull/24451 -from six.moves import http_client -assert isinstance(getattr(http_client, '_MAXHEADERS'), int) -setattr(http_client, '_MAXHEADERS', 512) +import http.client +assert isinstance(getattr(http.client, '_MAXHEADERS'), int) +setattr(http.client, '_MAXHEADERS', 512) """ HTTP server designed for testing purposes. @@ -106,7 +103,7 @@ :param output_path: Path to replace the input path with in the request. """ - if isinstance(methods, (binary_type, text_type)): + if isinstance(methods, (bytes, str)): methods = [methods] self.rules[input_path] = (methods, output_path) @@ -129,7 +126,7 @@ request_handler.path = new_url -class WebTestServer(ThreadingMixIn, BaseHTTPServer.HTTPServer): +class WebTestServer(ThreadingMixIn, http.server.HTTPServer): allow_reuse_address = True acceptable_errors = (errno.EPIPE, errno.ECONNABORTED) request_queue_size = 2000 @@ -190,8 +187,7 @@ else: hostname_port = ("",server_address[1]) - #super doesn't work here because BaseHTTPServer.HTTPServer is old-style - BaseHTTPServer.HTTPServer.__init__(self, hostname_port, request_handler_cls, **kwargs) + http.server.HTTPServer.__init__(self, hostname_port, request_handler_cls, **kwargs) if config is not None: Server.config = config @@ -236,12 +232,12 @@ self.logger.error(traceback.format_exc()) -class BaseWebTestRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): +class BaseWebTestRequestHandler(http.server.BaseHTTPRequestHandler): """RequestHandler for WebTestHttpd""" def __init__(self, *args, **kwargs): self.logger = get_logger() - BaseHTTPServer.BaseHTTPRequestHandler.__init__(self, *args, **kwargs) + http.server.BaseHTTPRequestHandler.__init__(self, *args, **kwargs) def finish_handling_h1(self, request_line_is_valid): @@ -482,14 +478,19 @@ try: handshaker.do_handshake() except HandshakeException as e: - self.logger.info('Handshake failed for error: %s', e) + self.logger.info('Handshake failed for error: %s' % e) h2response.set_error(e.status) h2response.write() return # h2 Handshaker prepares the headers but does not send them down the # wire. Flush the headers here. - h2response.write_status_headers() + try: + h2response.write_status_headers() + except StreamClosedError: + # work around https://github.com/web-platform-tests/wpt/issues/27786 + # The stream was already closed. + return request_wrapper._dispatcher = dispatcher @@ -522,7 +523,13 @@ def _stream_ws_sub_thread(self, request, stream_handler, queue): dispatcher = request._dispatcher - dispatcher.transfer_data(request) + try: + dispatcher.transfer_data(request) + except StreamClosedError: + # work around https://github.com/web-platform-tests/wpt/issues/27786 + # The stream was already closed. + queue.put(None) + return stream_id = stream_handler.h2_stream_id with stream_handler.conn as connection:
diff --git a/third_party/wpt_tools/wpt/tools/wptserve/wptserve/sslutils/openssl.py b/third_party/wpt_tools/wpt/tools/wptserve/wptserve/sslutils/openssl.py index 64f6d5f..87a8cc9 100644 --- a/third_party/wpt_tools/wpt/tools/wptserve/wptserve/sslutils/openssl.py +++ b/third_party/wpt_tools/wpt/tools/wptserve/wptserve/sslutils/openssl.py
@@ -6,8 +6,6 @@ import tempfile from datetime import datetime, timedelta -from six import iteritems, PY2 - # Amount of time beyond the present to consider certificates "expired." This # allows certificates to be proactively re-generated in the "buffer" period # prior to their exact expiration time. @@ -18,11 +16,7 @@ """makes sure s is an instance of str, converting with encoding if needed""" if isinstance(s, str): return s - - if PY2: - return s.encode(encoding) - else: - return s.decode(encoding) + return s.decode(encoding) class OpenSSL(object): @@ -79,7 +73,7 @@ # Copy the environment, converting to plain strings. Win32 StartProcess # is picky about all the keys/values being str (on both Py2/3). env = {} - for k, v in iteritems(os.environ): + for k, v in os.environ.items(): env[_ensure_str(k, "utf8")] = _ensure_str(v, "utf8") if self.base_conf_path is not None: @@ -324,7 +318,7 @@ end_date_str = openssl("x509", "-noout", "-enddate", - "-in", cert_path).split("=", 1)[1].strip() + "-in", cert_path).decode("utf8").split("=", 1)[1].strip() # Not sure if this works in other locales end_date = datetime.strptime(end_date_str, "%b %d %H:%M:%S %Y %Z") time_buffer = timedelta(**CERT_EXPIRY_BUFFER)
diff --git a/third_party/wpt_tools/wpt/tools/wptserve/wptserve/stash.py b/third_party/wpt_tools/wpt/tools/wptserve/wptserve/stash.py index bf6e5992..66c2713 100644 --- a/third_party/wpt_tools/wpt/tools/wptserve/wptserve/stash.py +++ b/third_party/wpt_tools/wpt/tools/wptserve/wptserve/stash.py
@@ -1,12 +1,10 @@ import base64 import json import os -import six import threading import uuid from multiprocessing.managers import AcquirerProxy, BaseManager, DictProxy -from six import text_type, binary_type from .utils import isomorphic_encode @@ -67,10 +65,10 @@ def start_server(address=None, authkey=None, mp_context=None): - if isinstance(authkey, text_type): + if isinstance(authkey, str): authkey = authkey.encode("ascii") kwargs = {} - if six.PY3 and mp_context is not None: + if mp_context is not None: kwargs["ctx"] = mp_context manager = ServerDictManager(address, authkey, **kwargs) manager.start() @@ -160,7 +158,7 @@ # This key format is required to support using the path. Since the data # passed into the stash can be a DictProxy which wouldn't detect # changes when writing to a subdict. - if isinstance(key, binary_type): + if isinstance(key, bytes): # UUIDs are within the ASCII charset. key = key.decode('ascii') return (isomorphic_encode(path), uuid.UUID(key).bytes)
diff --git a/third_party/wpt_tools/wpt/tools/wptserve/wptserve/utils.py b/third_party/wpt_tools/wpt/tools/wptserve/wptserve/utils.py index df0b3f3..ed74b73 100644 --- a/third_party/wpt_tools/wpt/tools/wptserve/wptserve/utils.py +++ b/third_party/wpt_tools/wpt/tools/wptserve/wptserve/utils.py
@@ -1,6 +1,5 @@ import socket -from six import binary_type, text_type from .logger import get_logger @@ -8,18 +7,18 @@ def isomorphic_decode(s): """Decodes a binary string into a text string using iso-8859-1. - Returns `unicode` in Python 2 and `str` in Python 3. The function is a - no-op if the argument already has a text type. iso-8859-1 is chosen because - it is an 8-bit encoding whose code points range from 0x0 to 0xFF and the - values are the same as the binary representations, so any binary string can - be decoded into and encoded from iso-8859-1 without any errors or data - loss. Python 3 also uses iso-8859-1 (or latin-1) extensively in http: + Returns `str`. The function is a no-op if the argument already has a text + type. iso-8859-1 is chosen because it is an 8-bit encoding whose code + points range from 0x0 to 0xFF and the values are the same as the binary + representations, so any binary string can be decoded into and encoded from + iso-8859-1 without any errors or data loss. Python 3 also uses iso-8859-1 + (or latin-1) extensively in http: https://github.com/python/cpython/blob/273fc220b25933e443c82af6888eb1871d032fb8/Lib/http/client.py#L213 """ - if isinstance(s, text_type): + if isinstance(s, str): return s - if isinstance(s, binary_type): + if isinstance(s, bytes): return s.decode("iso-8859-1") raise TypeError("Unexpected value (expecting string-like): %r" % s) @@ -28,14 +27,13 @@ def isomorphic_encode(s): """Encodes a text-type string into binary data using iso-8859-1. - Returns `str` in Python 2 and `bytes` in Python 3. The function is a no-op - if the argument already has a binary type. This is the counterpart of - isomorphic_decode. + Returns `bytes`. The function is a no-op if the argument already has a + binary type. This is the counterpart of isomorphic_decode. """ - if isinstance(s, binary_type): + if isinstance(s, bytes): return s - if isinstance(s, text_type): + if isinstance(s, str): return s.encode("iso-8859-1") raise TypeError("Unexpected value (expecting string-like): %r" % s) @@ -88,6 +86,7 @@ 42, # name 43, # nicname 53, # domain + 69, # tftp 77, # priv-rjs 79, # finger 87, # ttylink @@ -105,8 +104,10 @@ 119, # nntp 123, # ntp 135, # loc-srv / epmap - 139, # netbios + 137, # netbios-ns + 139, # netbios-ssn 143, # imap2 + 161, # snmp 179, # bgp 389, # ldap 427, # afp (alternate) @@ -129,6 +130,7 @@ 636, # ldap+ssl 993, # ldap+ssl 995, # pop3+ssl + 1719, # h323gatestat 1720, # h323hostcall 1723, # pptp 2049, # nfs @@ -137,6 +139,7 @@ 5060, # sip 5061, # sips 6000, # x11 + 6566, # sane-port 6665, # irc (alternate) 6666, # irc (alternate) 6667, # irc (default)
diff --git a/third_party/wpt_tools/wpt/tools/wptserve/wptserve/ws_h2_handshake.py b/third_party/wpt_tools/wpt/tools/wptserve/wptserve/ws_h2_handshake.py index 98796c0..c813ecb 100644 --- a/third_party/wpt_tools/wpt/tools/wptserve/wptserve/ws_h2_handshake.py +++ b/third_party/wpt_tools/wpt/tools/wptserve/wptserve/ws_h2_handshake.py
@@ -11,8 +11,6 @@ from mod_pywebsocket.stream import Stream from mod_pywebsocket.stream import StreamOptions from mod_pywebsocket import util -from six.moves import map -from six.moves import range # TODO: We are using "private" methods of pywebsocket. We might want to # refactor pywebsocket to expose those methods publicly. Also, _get_origin
diff --git a/third_party/wpt_tools/wpt/wpt b/third_party/wpt_tools/wpt/wpt index 36d0bed4..eac84b6 100755 --- a/third_party/wpt_tools/wpt/wpt +++ b/third_party/wpt_tools/wpt/wpt
@@ -1,34 +1,11 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 if __name__ == "__main__": import sys - from tools.wpt import wpt - args, extra = wpt.parse_args(sys.argv[1:]) - commands = wpt.load_commands() - py3only = commands[args.command]["py3only"] + if (sys.version_info.major < 3 or + (sys.version_info.major == 3 and sys.version_info.minor < 6)): + sys.stderr.write("wpt requires Python 3.6 or higher\n") + sys.exit(1) - if (args.py2) and sys.version_info.major > 2: - if py3only: - sys.stderr.write("This command only works with Python 3\n") - sys.exit(1) - from subprocess import call - try: - sys.exit(call(['python2'] + sys.argv)) - except OSError as e: - if e.errno == 2: - sys.stderr.write("python2 is needed to run this command\n") - sys.exit(1) - else: - raise - elif (not args.py2) and sys.version_info.major < 3: - from subprocess import call - try: - sys.exit(call(['python3'] + sys.argv)) - except OSError as e: - if e.errno == 2: - sys.stderr.write("python3 is needed to run this command\n") - sys.exit(1) - else: - raise - else: - wpt.main() + from tools.wpt import wpt + wpt.main()
diff --git a/tools/licenses.py b/tools/licenses.py index c548ac8f..aaa520b 100755 --- a/tools/licenses.py +++ b/tools/licenses.py
@@ -122,7 +122,6 @@ os.path.join('chrome', 'common', 'extensions', 'docs', 'examples'), os.path.join('chrome', 'test', 'chromeos', 'autotest'), os.path.join('chrome', 'test', 'data'), - os.path.join('clank', 'third_party', 'elements'), os.path.join('native_client'), os.path.join('testing', 'gmock'), os.path.join('testing', 'gtest'), @@ -506,7 +505,7 @@ third_party_dirs.update([os.path.join(dirname, p) for p in extra_paths]) -def FindThirdPartyDirs(prune_paths, root): +def FindThirdPartyDirs(prune_paths, root, extra_third_party_dirs=None): """Find all third_party directories underneath the source root.""" third_party_dirs = set() for path, dirs, files in os.walk(root): @@ -542,7 +541,11 @@ if path in ADDITIONAL_PATHS: dirs[:] = [] - for dir in ADDITIONAL_PATHS: + extra_paths = set(ADDITIONAL_PATHS) + if extra_third_party_dirs: + extra_paths.update(extra_third_party_dirs) + + for dir in extra_paths: if dir not in prune_paths: third_party_dirs.add(dir) ProcessAdditionalReadmePathsJson(root, dir, third_party_dirs) @@ -647,9 +650,14 @@ return len(errors) == 0 -def GenerateCredits( - file_template_file, entry_template_file, output_file, target_os, - gn_out_dir, gn_target, depfile=None): +def GenerateCredits(file_template_file, + entry_template_file, + output_file, + target_os, + gn_out_dir, + gn_target, + extra_third_party_dirs=None, + depfile=None): """Generate about:credits.""" def EvaluateTemplate(template, env, escape=True): @@ -681,7 +689,8 @@ if not third_party_dirs: raise RuntimeError("No deps found.") else: - third_party_dirs = FindThirdPartyDirs(PRUNE_PATHS, _REPOSITORY_ROOT) + third_party_dirs = FindThirdPartyDirs(PRUNE_PATHS, _REPOSITORY_ROOT, + extra_third_party_dirs) if not file_template_file: file_template_file = os.path.join(_REPOSITORY_ROOT, 'components', @@ -821,6 +830,9 @@ '--file-template', help='Template HTML to use for the license page.') parser.add_argument( '--entry-template', help='Template HTML to use for each license.') + parser.add_argument( + '--extra-third-party-dirs', + help='Gn list of additional third_party dirs to look through.') parser.add_argument('--target-os', help='OS that this build is targeting.') parser.add_argument( '--gn-out-dir', help='GN output directory for scanning dependencies.') @@ -830,6 +842,8 @@ parser.add_argument('output_file', nargs='?') build_utils.AddDepfileOption(parser) args = parser.parse_args() + args.extra_third_party_dirs = build_utils.ParseGnList( + args.extra_third_party_dirs) if args.command == 'scan': if not ScanThirdPartyDirs(): @@ -837,7 +851,8 @@ elif args.command == 'credits': if not GenerateCredits(args.file_template, args.entry_template, args.output_file, args.target_os, args.gn_out_dir, - args.gn_target, args.depfile): + args.gn_target, args.extra_third_party_dirs, + args.depfile): return 1 elif args.command == 'license_file': try:
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 08693954..9487f93 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -10096,6 +10096,16 @@ <int value="0" label="Unknown"/> </enum> +<enum name="CellularConnectResult"> + <int value="0" label="Unknown"/> + <int value="1" label="Invalid GUID"/> + <int value="2" label="Invalid state"/> + <int value="3" label="Canceled"/> + <int value="4" label="Not configured"/> + <int value="5" label="Blocked"/> + <int value="6" label="Success"/> +</enum> + <enum name="CertificateChainPosition"> <obsolete> Deprecated as of 01/2016. CertCacheTrial has been removed. @@ -46378,6 +46388,7 @@ <int value="408190863" label="OmniboxDisableInstantExtendedLimit:disabled"/> <int value="409566604" label="IntentPickerPWAPersistence:enabled"/> <int value="409622437" label="disable-buffer-bw-compression"/> + <int value="410400234" label="WebAppEnableProtocolHandlers:disabled"/> <int value="411250226" label="AutoplayMutedVideos:disabled"/> <int value="412957264" label="tab-close-buttons-hidden-with-touch"/> <int value="413062443" label="MessagesForAndroidInfrastructure:disabled"/> @@ -47746,6 +47757,7 @@ <int value="1645479440" label="HistoryManipulationIntervention:disabled"/> <int value="1646498561" label="OfflineBookmarks:disabled"/> <int value="1649121568" label="DynamicTcmallocTuning:disabled"/> + <int value="1651030066" label="WebAppEnableProtocolHandlers:enabled"/> <int value="1651141490" label="SaveEditedPDFForm:enabled"/> <int value="1652798696" label="InterestFeedV1ClickAndViewActionsConditionalUpload:disabled"/>
diff --git a/tools/metrics/histograms/histograms_xml/gpu/histograms.xml b/tools/metrics/histograms/histograms_xml/gpu/histograms.xml index 8b118a4..63f9eff 100644 --- a/tools/metrics/histograms/histograms_xml/gpu/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/gpu/histograms.xml
@@ -1100,6 +1100,32 @@ </summary> </histogram> +<histogram name="GPU.Scheduler.TaskDependencyTime" units="microseconds" + expires_after="2022-03-31"> + <owner>berlu@chromium.org</owner> + <owner>chrome-gpu-metrics@google.com</owner> + <summary> + Records the wall time taken spent by each GPU scheduler task waiting on it's + dependencies to resolve. The time delta starts when the waiting fence is + added and finishes when the last fence is removed. Only recorded for clients + with high resolution clocks. + </summary> +</histogram> + +<histogram name="GPU.Scheduler.TaskSchedulingDelayTime" units="microseconds" + expires_after="2022-03-31"> + <owner>berlu@chromium.org</owner> + <owner>chrome-gpu-metrics@google.com</owner> + <summary> + Records the wall time taken spent by each GPU scheduler task waiting on to + be scheduled once all its dependencies have been resolved. The time delta + starts when the last waiting fence is passed and stops when the tasks starts + running. If the schedulers is working properly, for a high priority task, + this metric should be minimal. Only recorded for clients with high + resolution clocks. + </summary> +</histogram> + <histogram name="GPU.setIsAcceleratedCompositingActive" enum="GPUsetIsAcceleratedCompositingActive" expires_after="M85"> <owner>vmiura@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml b/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml index 33dcbaa..f912fe81 100644 --- a/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml +++ b/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml
@@ -875,6 +875,10 @@ <owner>boliu@google.com</owner> <owner>ssid@chromium.org</owner> <suffix name="Browser" label="Recorded for Browser crashes."/> + <suffix name="Browser.Background" + label="Recorded for background Browser crashes."/> + <suffix name="Browser.Foreground" + label="Recorded for foregound Browser crashes."/> <suffix name="GpuForegroundOom" label="Recorded for foreground GPU process OOM crashes."/> <suffix name="UtilityForegroundOom"
diff --git a/tools/metrics/histograms/histograms_xml/network/histograms.xml b/tools/metrics/histograms/histograms_xml/network/histograms.xml index f59cfa49..25d62f1 100644 --- a/tools/metrics/histograms/histograms_xml/network/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/network/histograms.xml
@@ -104,6 +104,10 @@ <histogram name="Network.Cellular.Connection.Disconnections" enum="NetworkCellularConnectionState" expires_after="2021-08-29"> + <obsolete> + Split into Network.Cellular.PSim.Disconnections and + Network.Cellular.ESim.Disconnections on 03/2021. + </obsolete> <owner>azeemarshad@chromium.org</owner> <owner>cros-system-services-networking@google.com</owner> <summary> @@ -114,6 +118,10 @@ <histogram name="Network.Cellular.Connection.TimeToConnected" units="ms" expires_after="2021-08-29"> + <obsolete> + Split into Network.Cellular.ESim.TimeToConnected and + Network.Cellular.ESim.TimeToConnected on 03/2021. + </obsolete> <owner>azeemarshad@chromium.org</owner> <owner>cros-connectivity@google.com</owner> <summary> @@ -270,6 +278,53 @@ </summary> </histogram> +<histogram name="Network.Cellular.{SimType}.ConnectionSuccess" + enum="CellularConnectResult" expires_after="2022-03-01"> + <owner>azeemarshad@chromium.org</owner> + <owner>cros-connectivity@google.com</owner> + <owner>hsuregan@chromium.org</owner> + <summary> + Tracks the result of connecting to a cellular network. Logged when a + {SimType} connection succeeds or fails. In the case of failure, which can + occur in the Chrome or Shill layers, the error reason is emitted. Note that + Shill errors are mapped to Unknown. Refer to + go/cros-cellular-success-metrics for details. + </summary> + <token key="SimType"> + <variant name="ESim"/> + <variant name="PSim"/> + </token> +</histogram> + +<histogram name="Network.Cellular.{SimType}.Disconnections" + enum="NetworkCellularConnectionState" expires_after="2022-03-01"> + <owner>azeemarshad@chromium.org</owner> + <owner>cros-system-services-networking@google.com</owner> + <summary> + Tracks when cellular {SimType} network is connected and when cellular + network is disconnected without explicit user action. + </summary> + <token key="SimType"> + <variant name="ESim"/> + <variant name="PSim"/> + </token> +</histogram> + +<histogram name="Network.Cellular.{SimType}.TimeToConnected" units="ms" + expires_after="2022-03-01"> + <owner>azeemarshad@chromium.org</owner> + <owner>cros-connectivity@google.com</owner> + <owner>hsuregan@chromium.org</owner> + <summary> + Tracks the amount fo time taken between when cellular device starts and + finishes connecting for {SimType} networks. + </summary> + <token key="SimType"> + <variant name="ESim"/> + <variant name="PSim"/> + </token> +</histogram> + <histogram name="Network.Cellular.{SimType}.Usage.Duration" units="seconds" expires_after="2022-03-01"> <owner>azeemarshad@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/new_tab_page/histograms.xml b/tools/metrics/histograms/histograms_xml/new_tab_page/histograms.xml index 0a4bf624..dc83ae8 100644 --- a/tools/metrics/histograms/histograms_xml/new_tab_page/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/new_tab_page/histograms.xml
@@ -742,9 +742,7 @@ </summary> </histogram> -<histogram name="NewTabPage.LoadTime" units="ms" expires_after="never"> -<!-- expires-never: "heartbeat" metric (internal: go/uma-heartbeats) --> - +<histogram name="NewTabPage.LoadTime" units="ms" expires_after="2022-01-01"> <owner>tiborg@chromium.org</owner> <owner>yyushkina@chromium.org</owner> <owner>chrome-desktop-ntp@google.com</owner>
diff --git a/tools/metrics/histograms/histograms_xml/page/histograms.xml b/tools/metrics/histograms/histograms_xml/page/histograms.xml index f36fce2..82fc66c2 100644 --- a/tools/metrics/histograms/histograms_xml/page/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/page/histograms.xml
@@ -1866,7 +1866,8 @@ </histogram> <histogram name="PageLoad.Internal.Renderer.PresentationTime.DeltaFromSwapTime" - units="ms" expires_after="2020-09-27"> + units="ms" expires_after="2021-12-31"> + <owner>jonross@chromium.org</owner> <owner>sadrul@chromium.org</owner> <summary> 'Swap time' is the timestamp of the renderer submitting a CompositorFrame, @@ -1878,17 +1879,24 @@ compositor-frames that report a paint-timing metric (e.g. FirstContentfulPaint etc.), and after that frame has been displayed on screen. + + The metric had expired on 2020-09-27, and re-enabled on 2021-03-17. So the + data within this period is incomplete. </summary> </histogram> <histogram name="PageLoad.Internal.Renderer.PresentationTime.Valid" - enum="Boolean" expires_after="2020-09-27"> + enum="Boolean" expires_after="2021-12-31"> + <owner>jonross@chromium.org</owner> <owner>sadrul@chromium.org</owner> <summary> This boolean keeps track of whether a valid presentation-timestamp was received or not. This is reported only for compositor-frames that report a paint-timing metric (e.g. FirstContentfulPaint etc.), and after that frame has been displayed on screen. + + The metric had expired on 2020-09-27, and re-enabled on 2021-03-17. So the + data within this period is incomplete. </summary> </histogram>
diff --git a/tools/metrics/histograms/histograms_xml/phonehub/histograms.xml b/tools/metrics/histograms/histograms_xml/phonehub/histograms.xml index de6d5369..8e25bdb 100644 --- a/tools/metrics/histograms/histograms_xml/phonehub/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/phonehub/histograms.xml
@@ -105,21 +105,31 @@ enum="PhoneHubInterstitialScreenEvent" expires_after="2021-10-31"> <owner>tengs@chromium.org</owner> <owner>khorimoto@chromium.org</owner> - <summary>Events for the given PhoneHub interstitial screen.</summary> + <summary>Events for the given PhoneHub interstitial screen. {Screen}</summary> <!-- The entries below should be a subset of the PhoneHubScreen enum --> <token key="Screen"> - <variant name="BluetoothOrWifiDisabled"/> - <variant name="InitialConnecting"> + <variant name="BluetoothOrWifiDisabled" summary=""/> + <variant name="InitialConnecting" summary=""> <obsolete> Combined into PhoneConnecting on Nov 2020. </obsolete> </variant> - <variant name="Onboarding.ExistingMultideviceUser"/> - <variant name="Onboarding.NewMultideviceUser"/> - <variant name="OnboardingDismissPrompt"/> - <variant name="PhoneConnecting"/> - <variant name="PhoneDisconnected"/> + <variant name="Onboarding.ExistingMultideviceUser" + summary="NOTE(https://crbug.com/1187255): This metric is actually + logging new multi-device users. For continuity, we continue + to log this metric in reverse. See ExistingMultideviceUser2 + for the correct logging."/> + <variant name="Onboarding.ExistingMultideviceUser2" summary=""/> + <variant name="Onboarding.NewMultideviceUser" + summary="NOTE(https://crbug.com/1187255): This metric is actually + logging existing multi-device users. For continuity, we + continue to log this metric in reverse. See + NewMultideviceUser2 for the correct logging."/> + <variant name="Onboarding.NewMultideviceUser2" summary=""/> + <variant name="OnboardingDismissPrompt" summary=""/> + <variant name="PhoneConnecting" summary=""/> + <variant name="PhoneDisconnected" summary=""/> </token> </histogram>
diff --git a/tools/metrics/histograms/histograms_xml/stability/histograms.xml b/tools/metrics/histograms/histograms_xml/stability/histograms.xml index f5ecd5e..4f223298 100644 --- a/tools/metrics/histograms/histograms_xml/stability/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/stability/histograms.xml
@@ -129,7 +129,9 @@ <owner>ssid@chromium.org</owner> <owner>wnwen@chromium.org</owner> <summary> - Reason given by Android ActivityManager for the exit of the process. + Reason given by Android ActivityManager for the exit of the process, only + recorded in Android R+. Recorded on the next browser startup for browser + exits, or right after the process died for child processes. </summary> </histogram>
diff --git a/tools/metrics/histograms/histograms_xml/translate/histograms.xml b/tools/metrics/histograms/histograms_xml/translate/histograms.xml index 3d5f53e..ec0081f 100644 --- a/tools/metrics/histograms/histograms_xml/translate/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/translate/histograms.xml
@@ -1062,7 +1062,7 @@ <owner>megjablon@google.com</owner> <owner>chrome-language@google.com</owner> <summary> - Records the target language used for a translation. This is the langauge + Records the target language used for a translation. This is the language being translated to. This is recorded when a translation (both manual and automatic) is started.
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index cad2baac..b7c915f5 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -1,16 +1,16 @@ { "trace_processor_shell": { "win": { - "hash": "c80b858c77b82ec7e89933de81938d53be761d22", - "remote_path": "perfetto_binaries/trace_processor_shell/win/e7a3007adf25b4c59b99aef58ff41b179b3b66ef/trace_processor_shell.exe" + "hash": "70109c7140b950fc50cfb6b7b0064f361c5a767d", + "remote_path": "perfetto_binaries/trace_processor_shell/win/371d8955a1cbc43fc7b2ec19b30c250d6466291c/trace_processor_shell.exe" }, "mac": { - "hash": "59667644a3ec6354704a6933d5df2dfb903fd734", - "remote_path": "perfetto_binaries/trace_processor_shell/mac/e7a3007adf25b4c59b99aef58ff41b179b3b66ef/trace_processor_shell" + "hash": "8c080f6337a2f1e880197daf242690a6980093be", + "remote_path": "perfetto_binaries/trace_processor_shell/mac/371d8955a1cbc43fc7b2ec19b30c250d6466291c/trace_processor_shell" }, "linux": { "hash": "b053a22b4b34b7da28445e2e26d19695a6d8edbf", - "remote_path": "perfetto_binaries/trace_processor_shell/linux/375eac05933d48f729014597f8f34e5733d7cedb/trace_processor_shell" + "remote_path": "perfetto_binaries/trace_processor_shell/linux/371d8955a1cbc43fc7b2ec19b30c250d6466291c/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/ui/accessibility/ax_enum_util_unittest.cc b/ui/accessibility/ax_enum_util_unittest.cc index 34be7b3..284b68cf 100644 --- a/ui/accessibility/ax_enum_util_unittest.cc +++ b/ui/accessibility/ax_enum_util_unittest.cc
@@ -103,8 +103,17 @@ TEST(AXEnumUtilTest, StringAttribute) { TestEnumStringConversion<ax::mojom::StringAttribute>(); - TestAXNodeDataSetter<ax::mojom::StringAttribute>( - &AXNodeData::AddStringAttribute, std::string()); + + AXNodeData node_data; + for (int i = static_cast<int>(ax::mojom::StringAttribute::kMinValue) + 1; + i <= static_cast<int>(ax::mojom::StringAttribute::kMaxValue); ++i) { + ax::mojom::StringAttribute attr = + static_cast<ax::mojom::StringAttribute>(i); + if (attr == ax::mojom::StringAttribute::kChildTreeId) + continue; + node_data.AddStringAttribute(attr, std::string()); + } + EXPECT_TRUE(!node_data.ToString().empty()); } TEST(AXEnumUtilTest, IntAttribute) {
diff --git a/ui/accessibility/ax_node_data.cc b/ui/accessibility/ax_node_data.cc index 2880aa94..9c38702 100644 --- a/ui/accessibility/ax_node_data.cc +++ b/ui/accessibility/ax_node_data.cc
@@ -19,6 +19,7 @@ #include "ui/accessibility/ax_enum_util.h" #include "ui/accessibility/ax_enums.mojom.h" #include "ui/accessibility/ax_role_properties.h" +#include "ui/accessibility/ax_tree_id.h" #include "ui/gfx/transform.h" namespace ui { @@ -450,11 +451,21 @@ void AXNodeData::AddStringAttribute(ax::mojom::StringAttribute attribute, const std::string& value) { DCHECK_NE(attribute, ax::mojom::StringAttribute::kNone); + DCHECK_NE(attribute, ax::mojom::StringAttribute::kChildTreeId) + << "Use AddChildTreeId"; if (HasStringAttribute(attribute)) RemoveStringAttribute(attribute); string_attributes.push_back(std::make_pair(attribute, value)); } +void AXNodeData::AddChildTreeId(const ui::AXTreeID& tree_id) { + ax::mojom::StringAttribute attribute = + ax::mojom::StringAttribute::kChildTreeId; + if (HasStringAttribute(attribute)) + RemoveStringAttribute(attribute); + string_attributes.push_back(std::make_pair(attribute, tree_id.ToString())); +} + void AXNodeData::AddIntAttribute(ax::mojom::IntAttribute attribute, int value) { DCHECK_NE(attribute, ax::mojom::IntAttribute::kNone); if (HasIntAttribute(attribute))
diff --git a/ui/accessibility/ax_node_data.h b/ui/accessibility/ax_node_data.h index 31dd8efc..0dabcb6 100644 --- a/ui/accessibility/ax_node_data.h +++ b/ui/accessibility/ax_node_data.h
@@ -22,6 +22,8 @@ namespace ui { +class AXTreeID; + // Defines the type used for AXNode IDs. using AXNodeID = int32_t; @@ -117,8 +119,11 @@ // have wanted or what existing code already assumes. // + // This method cannot be used to set kChildTreeId due to a common + // misuse of base::UnguessableToken serialization. Use AddChildTreeId instead. void AddStringAttribute(ax::mojom::StringAttribute attribute, const std::string& value); + void AddChildTreeId(const ui::AXTreeID& tree_id); void AddIntAttribute(ax::mojom::IntAttribute attribute, int32_t value); void AddFloatAttribute(ax::mojom::FloatAttribute attribute, float value); void AddBoolAttribute(ax::mojom::BoolAttribute attribute, bool value);
diff --git a/ui/accessibility/ax_node_position_unittest.cc b/ui/accessibility/ax_node_position_unittest.cc index 4f2acc0..c9c8e81 100644 --- a/ui/accessibility/ax_node_position_unittest.cc +++ b/ui/accessibility/ax_node_position_unittest.cc
@@ -417,8 +417,7 @@ SetTree(std::make_unique<AXTree>(initial_state)); AXTreeUpdate views_tree_update; - web_view.AddStringAttribute(ax::mojom::StringAttribute::kChildTreeId, - GetTreeID().ToString()); + web_view.AddChildTreeId(GetTreeID()); views_tree_update.nodes = {web_view}; ASSERT_TRUE(views_tree->Unserialize(views_tree_update)); views_tree_manager_ = TestAXTreeManager(std::move(views_tree)); @@ -587,14 +586,12 @@ CreateAXTree({iframe_root}, webpage_tree->GetAXTreeID()); AXTreeUpdate views_tree_update; - web_view.AddStringAttribute(ax::mojom::StringAttribute::kChildTreeId, - webpage_tree->GetAXTreeID().ToString()); + web_view.AddChildTreeId(webpage_tree->GetAXTreeID()); views_tree_update.nodes = {web_view}; ASSERT_TRUE(views_tree->Unserialize(views_tree_update)); AXTreeUpdate webpage_tree_update; - iframe.AddStringAttribute(ax::mojom::StringAttribute::kChildTreeId, - iframe_tree->GetAXTreeID().ToString()); + iframe.AddChildTreeId(iframe_tree->GetAXTreeID()); webpage_tree_update.nodes = {iframe}; ASSERT_TRUE(webpage_tree->Unserialize(webpage_tree_update)); @@ -11122,8 +11119,7 @@ root.child_ids = {embed_object.id}; embed_object.role = ax::mojom::Role::kEmbeddedObject; - embed_object.AddStringAttribute(ax::mojom::StringAttribute::kChildTreeId, - child_tree_id.ToString()); + embed_object.AddChildTreeId(child_tree_id); SetTree(CreateAXTree({root, embed_object})); // Create tree manager for child tree.
diff --git a/ui/accessibility/ax_tree_combiner_unittest.cc b/ui/accessibility/ax_tree_combiner_unittest.cc index 0bf8893..36889a7d 100644 --- a/ui/accessibility/ax_tree_combiner_unittest.cc +++ b/ui/accessibility/ax_tree_combiner_unittest.cc
@@ -55,8 +55,7 @@ parent_tree.nodes[1].role = ax::mojom::Role::kButton; parent_tree.nodes[2].id = 3; parent_tree.nodes[2].role = ax::mojom::Role::kIframe; - parent_tree.nodes[2].AddStringAttribute( - ax::mojom::StringAttribute::kChildTreeId, tree_id_2.ToString()); + parent_tree.nodes[2].AddChildTreeId(tree_id_2); AXTreeUpdate child_tree; child_tree.root_id = 1; @@ -181,8 +180,7 @@ parent_tree.nodes[1].role = ax::mojom::Role::kButton; parent_tree.nodes[2].id = 3; parent_tree.nodes[2].role = ax::mojom::Role::kIframe; - parent_tree.nodes[2].AddStringAttribute( - ax::mojom::StringAttribute::kChildTreeId, tree_id_2.ToString()); + parent_tree.nodes[2].AddChildTreeId(tree_id_2); AXTreeUpdate child_tree; child_tree.has_tree_data = true;
diff --git a/ui/accessibility/ax_tree_unittest.cc b/ui/accessibility/ax_tree_unittest.cc index 22f87bf..e169e7d 100644 --- a/ui/accessibility/ax_tree_unittest.cc +++ b/ui/accessibility/ax_tree_unittest.cc
@@ -3114,14 +3114,11 @@ initial_state.nodes[0].child_ids.push_back(3); initial_state.nodes[0].child_ids.push_back(4); initial_state.nodes[1].id = 2; - initial_state.nodes[1].AddStringAttribute( - ax::mojom::StringAttribute::kChildTreeId, tree_id_2.ToString()); + initial_state.nodes[1].AddChildTreeId(tree_id_2); initial_state.nodes[2].id = 3; - initial_state.nodes[2].AddStringAttribute( - ax::mojom::StringAttribute::kChildTreeId, tree_id_3.ToString()); + initial_state.nodes[2].AddChildTreeId(tree_id_3); initial_state.nodes[3].id = 4; - initial_state.nodes[3].AddStringAttribute( - ax::mojom::StringAttribute::kChildTreeId, tree_id_3.ToString()); + initial_state.nodes[3].AddChildTreeId(tree_id_3); AXTree tree(initial_state); auto child_tree_1_nodes = tree.GetNodeIdsForChildTreeId(tree_id_1); @@ -3138,8 +3135,7 @@ AXTreeUpdate update = initial_state; update.nodes[2].string_attributes.clear(); - update.nodes[2].AddStringAttribute(ax::mojom::StringAttribute::kChildTreeId, - tree_id_2.ToString()); + update.nodes[2].AddChildTreeId(tree_id_2); update.nodes[3].string_attributes.clear(); EXPECT_TRUE(tree.Unserialize(update));
diff --git a/ui/color/color_id.h b/ui/color/color_id.h index 7163d04d..3cc431c 100644 --- a/ui/color/color_id.h +++ b/ui/color/color_id.h
@@ -18,21 +18,27 @@ E(kColorAlertLowSeverity, NativeTheme::kColorId_AlertSeverityLow) \ E(kColorAlertMediumSeverity, NativeTheme::kColorId_AlertSeverityMedium) \ E_CPONLY(kColorDisabledForeground) \ + E_CPONLY(kColorEndpointBackground) \ + E_CPONLY(kColorEndpointForeground) \ E_CPONLY(kColorItemSelectionBackground) \ E_CPONLY(kColorMidground) \ E_CPONLY(kColorPrimaryBackground) \ E_CPONLY(kColorPrimaryForeground) \ E_CPONLY(kColorSecondaryForeground) \ + E_CPONLY(kColorSubtleAccent) \ E_CPONLY(kColorSubtleEmphasisBackground) \ E_CPONLY(kColorTextSelectionBackground) \ + E_CPONLY(kColorTextSelectionForeground) \ \ /* Further UI element colors */ \ E(kColorAvatarHeaderArt, NativeTheme::kColorId_AvatarHeaderArt) \ E(kColorAvatarIconGuest, NativeTheme::kColorId_AvatarIconGuest) \ E(kColorAvatarIconIncognito, NativeTheme::kColorId_AvatarIconIncognito) \ E(kColorBubbleBackground, NativeTheme::kColorId_BubbleBackground) \ + E(kColorBubbleBorder, NativeTheme::kColorId_BubbleBorder) \ E(kColorBubbleFooterBackground, \ NativeTheme::kColorId_BubbleFooterBackground) \ + E(kColorBubbleFooterBorder, NativeTheme::kColorId_BubbleFooterBorder) \ E(kColorButtonBackground, NativeTheme::kColorId_ButtonColor) \ /* TODO(https://crbug.com/1003612): Map this to old color id. */ \ E_CPONLY(kColorButtonBackgroundPressed) \ @@ -46,6 +52,7 @@ E(kColorButtonBorderDisabled, \ NativeTheme::kColorId_DisabledButtonBorderColor) \ E(kColorButtonForeground, NativeTheme::kColorId_ButtonEnabledColor) \ + E(kColorButtonForegroundChecked, NativeTheme::kColorId_ButtonCheckedColor) \ E(kColorButtonForegroundDisabled, NativeTheme::kColorId_ButtonDisabledColor) \ E(kColorButtonForegroundProminent, \ NativeTheme::kColorId_TextOnProminentButtonColor) \ @@ -53,10 +60,21 @@ NativeTheme::kColorId_ButtonUncheckedColor) \ E(kColorDialogBackground, NativeTheme::kColorId_DialogBackground) \ E(kColorDialogForeground, NativeTheme::kColorId_DialogForeground) \ + E(kColorDropdownBackground, NativeTheme::kColorId_DropdownBackgroundColor) \ + E(kColorDropdownBackgroundSelected, \ + NativeTheme::kColorId_DropdownSelectedBackgroundColor) \ + E(kColorDropdownForeground, NativeTheme::kColorId_DropdownForegroundColor) \ + E(kColorDropdownForegroundSelected, \ + NativeTheme::kColorId_DropdownSelectedForegroundColor) \ E(kColorFocusableBorderFocused, NativeTheme::kColorId_FocusedBorderColor) \ E(kColorFocusableBorderUnfocused, \ NativeTheme::kColorId_UnfocusedBorderColor) \ + E(kColorFrameActive, NativeTheme::kColorId_CustomFrameActiveColor) \ + E(kColorFrameInactive, NativeTheme::kColorId_CustomFrameInactiveColor) \ + E(kColorHelpIconActive, NativeTheme::kColorId_TooltipIconHovered) \ + E(kColorHelpIconInactive, NativeTheme::kColorId_TooltipIcon) \ E(kColorIcon, NativeTheme::kColorId_DefaultIconColor) \ + E(kColorIconDisabled, NativeTheme::kColorId_DisabledIconColor) \ E(kColorLabelForeground, NativeTheme::kColorId_LabelEnabledColor) \ E(kColorLabelForegroundDisabled, NativeTheme::kColorId_LabelDisabledColor) \ E(kColorLabelForegroundSecondary, NativeTheme::kColorId_LabelSecondaryColor) \ @@ -69,6 +87,7 @@ E(kColorLinkForegroundPressed, NativeTheme::kColorId_LinkPressed) \ E(kColorMenuBackground, NativeTheme::kColorId_MenuBackgroundColor) \ E(kColorMenuBorder, NativeTheme::kColorId_MenuBorderColor) \ + E(kColorMenuDropmarker, NativeTheme::kColorId_MenuDropIndicator) \ E(kColorMenuIcon, NativeTheme::kColorId_MenuIconColor) \ E(kColorMenuItemBackgroundAlertedInitial, \ NativeTheme::kColorId_MenuItemInitialAlertBackgroundColor) \ @@ -89,6 +108,61 @@ E(kColorMenuItemForegroundSelected, \ NativeTheme::kColorId_SelectedMenuItemForegroundColor) \ E(kColorMenuSeparator, NativeTheme::kColorId_MenuSeparatorColor) \ + E(kColorNotificationActionsBackground, \ + NativeTheme::kColorId_NotificationActionsRowBackground) \ + E(kColorNotificationBackgroundActive, \ + NativeTheme::kColorId_NotificationBackgroundActive) \ + E(kColorNotificationBackgroundInactive, \ + NativeTheme::kColorId_NotificationBackground) \ + E(kColorNotificationHeaderForeground, \ + NativeTheme::kColorId_NotificationDefaultAccentColor) \ + E(kColorNotificationIconBackground, \ + NativeTheme::kColorId_MessageCenterSmallImageMaskBackground) \ + E(kColorNotificationIconForeground, \ + NativeTheme::kColorId_MessageCenterSmallImageMaskForeground) \ + E(kColorNotificationImageBackground, \ + NativeTheme::kColorId_NotificationLargeImageBackground) \ + E(kColorNotificationInputBackground, \ + NativeTheme::kColorId_NotificationInkDropBase) \ + E(kColorNotificationInputForeground, \ + NativeTheme::kColorId_NotificationColor) \ + E(kColorNotificationInputPlaceholderForeground, \ + NativeTheme::kColorId_NotificationPlaceholderColor) \ + E(kColorOverlayScrollbarFill, \ + NativeTheme::kColorId_OverlayScrollbarThumbFill) \ + E(kColorOverlayScrollbarFillHovered, \ + NativeTheme::kColorId_OverlayScrollbarThumbHoveredFill) \ + E(kColorOverlayScrollbarStroke, \ + NativeTheme::kColorId_OverlayScrollbarThumbStroke) \ + E(kColorOverlayScrollbarStrokeHovered, \ + NativeTheme::kColorId_OverlayScrollbarThumbHoveredStroke) \ + E(kColorPwaSecurityChipForeground, \ + NativeTheme::kColorId_CustomTabBarSecurityChipDefaultColor) \ + E(kColorPwaSecurityChipForegroundDangerous, \ + NativeTheme::kColorId_CustomTabBarSecurityChipDangerousColor) \ + E(kColorPwaSecurityChipForegroundPolicyCert, \ + NativeTheme::kColorId_CustomTabBarSecurityChipWithCertColor) \ + E(kColorPwaSecurityChipForegroundSecure, \ + NativeTheme::kColorId_CustomTabBarSecurityChipSecureColor) \ + E(kColorPwaToolbarBackground, \ + NativeTheme::kColorId_CustomTabBarBackgroundColor) \ + E(kColorPwaToolbarForeground, \ + NativeTheme::kColorId_CustomTabBarForegroundColor) \ + E(kColorSeparator, NativeTheme::kColorId_SeparatorColor) \ + E(kColorSliderThumb, NativeTheme::kColorId_SliderThumbDefault) \ + E(kColorSliderThumbMinimal, NativeTheme::kColorId_SliderThumbMinimal) \ + E(kColorSliderTrack, NativeTheme::kColorId_SliderTroughDefault) \ + E(kColorSliderTrackMinimal, NativeTheme::kColorId_SliderTroughMinimal) \ + E(kColorSyncInfoBackground, \ + NativeTheme::kColorId_SyncInfoContainerNoPrimaryAccount) \ + E(kColorSyncInfoBackgroundError, \ + NativeTheme::kColorId_SyncInfoContainerError) \ + E(kColorSyncInfoBackgroundPaused, \ + NativeTheme::kColorId_SyncInfoContainerPaused) \ + E(kColorTabBackgroundHighlighted, \ + NativeTheme::kColorId_TabHighlightBackground) \ + E(kColorTabBackgroundHighlightedFocused, \ + NativeTheme::kColorId_TabHighlightFocusedBackground) \ E(kColorTabBorderSelected, NativeTheme::kColorId_TabSelectedBorderColor) \ E(kColorTabContentSeparator, NativeTheme::kColorId_TabBottomBorder) \ E(kColorTabForeground, NativeTheme::kColorId_TabTitleColorInactive) \ @@ -123,6 +197,14 @@ E(kColorTextfieldSelectionForeground, \ NativeTheme::kColorId_TextfieldSelectionColor) \ E(kColorThrobber, NativeTheme::kColorId_ThrobberSpinningColor) \ + E(kColorThrobberPreconnect, NativeTheme::kColorId_ThrobberWaitingColor) \ + E(kColorToggleButtonShadow, NativeTheme::kColorId_ToggleButtonShadowColor) \ + E(kColorToggleButtonThumbOff, \ + NativeTheme::kColorId_ToggleButtonThumbColorOff) \ + E(kColorToggleButtonThumbOn, NativeTheme::kColorId_ToggleButtonThumbColorOn) \ + E(kColorToggleButtonTrackOff, \ + NativeTheme::kColorId_ToggleButtonTrackColorOff) \ + E(kColorToggleButtonTrackOn, NativeTheme::kColorId_ToggleButtonTrackColorOn) \ E(kColorTooltipBackground, NativeTheme::kColorId_TooltipBackground) \ E(kColorTooltipForeground, NativeTheme::kColorId_TooltipText) \ E(kColorTreeBackground, NativeTheme::kColorId_TreeBackground) \
diff --git a/ui/color/color_mixers.h b/ui/color/color_mixers.h index 48ae995..062ac353 100644 --- a/ui/color/color_mixers.h +++ b/ui/color/color_mixers.h
@@ -33,7 +33,10 @@ // Adds a color mixer to |provider| that combine the above color sets with // recipes as necessary to produce all colors needed by ui/. -COMPONENT_EXPORT(COLOR) void AddUiColorMixer(ColorProvider* provider); +COMPONENT_EXPORT(COLOR) +void AddUiColorMixer(ColorProvider* provider, + bool dark_window, + bool high_contrast); // Adds a color mixer to |provider| that can add to kColorSetNative. // Intended for colors needed by ui/ that this platform overrides but
diff --git a/ui/color/color_provider_manager.cc b/ui/color/color_provider_manager.cc index 56cfa51..15ab8e57 100644 --- a/ui/color/color_provider_manager.cc +++ b/ui/color/color_provider_manager.cc
@@ -60,7 +60,7 @@ contrast_mode == ColorProviderManager::ContrastMode::kHigh; ui::AddCoreDefaultColorMixer(provider, dark_mode, high_contrast); ui::AddNativeCoreColorMixer(provider, dark_mode, high_contrast); - ui::AddUiColorMixer(provider); + ui::AddUiColorMixer(provider, dark_mode, high_contrast); ui::AddNativeUiColorMixer(provider, dark_mode, high_contrast); #if defined(OS_MAC) // Always keep this mixer at the last so the system tint will be
diff --git a/ui/color/core_default_color_mixer.cc b/ui/color/core_default_color_mixer.cc index 0e443fe3..178717a2 100644 --- a/ui/color/core_default_color_mixer.cc +++ b/ui/color/core_default_color_mixer.cc
@@ -22,20 +22,18 @@ ColorMixer& AddMixerForDarkMode(ColorProvider* provider, bool high_contrast) { ColorMixer& mixer = provider->AddMixer(); - mixer.AddSet( - {kColorSetCoreDefaults, - { - {kColorAccent, gfx::kGoogleBlue300}, - {kColorAlertHighSeverity, gfx::kGoogleRed300}, - {kColorAlertLowSeverity, gfx::kGoogleGreen300}, - {kColorAlertMediumSeverity, gfx::kGoogleYellow300}, - {kColorMidground, gfx::kGoogleGrey800}, - {kColorPrimaryBackground, SkColorSetRGB(0x29, 0x2A, 0x2D)}, - {kColorPrimaryForeground, gfx::kGoogleGrey200}, - {kColorSecondaryForeground, gfx::kGoogleGrey500}, - {kColorSubtleEmphasisBackground, SkColorSetRGB(0x32, 0x36, 0x39)}, - {kColorTextSelectionBackground, gfx::kGoogleBlue800}, - }}); + mixer.AddSet({kColorSetCoreDefaults, + { + {kColorAccent, gfx::kGoogleBlue300}, + {kColorAlertHighSeverity, gfx::kGoogleRed300}, + {kColorAlertLowSeverity, gfx::kGoogleGreen300}, + {kColorAlertMediumSeverity, gfx::kGoogleYellow300}, + {kColorMidground, gfx::kGoogleGrey800}, + {kColorPrimaryBackground, SkColorSetRGB(0x29, 0x2A, 0x2D)}, + {kColorPrimaryForeground, gfx::kGoogleGrey200}, + {kColorSecondaryForeground, gfx::kGoogleGrey500}, + {kColorTextSelectionBackground, gfx::kGoogleBlue800}, + }}); return mixer; } @@ -51,7 +49,6 @@ {kColorPrimaryBackground, SK_ColorWHITE}, {kColorPrimaryForeground, gfx::kGoogleGrey900}, {kColorSecondaryForeground, gfx::kGoogleGrey700}, - {kColorSubtleEmphasisBackground, gfx::kGoogleGrey050}, {kColorTextSelectionBackground, gfx::kGoogleBlue200}, }}); @@ -71,8 +68,18 @@ : AddMixerForLightMode(provider, high_contrast); mixer[kColorDisabledForeground] = BlendForMinContrast( gfx::kGoogleGrey600, kColorPrimaryBackground, kColorPrimaryForeground); + mixer[kColorEndpointBackground] = + GetColorWithMaxContrast(kColorEndpointForeground); + mixer[kColorEndpointForeground] = + GetColorWithMaxContrast(kColorPrimaryBackground); mixer[kColorItemSelectionBackground] = BlendForMinContrastWithSelf(kColorPrimaryBackground, 1.67f); + mixer[kColorSubtleAccent] = AlphaBlend(kColorAccent, kColorPrimaryBackground, + gfx::kGoogleGreyAlpha400); + mixer[kColorSubtleEmphasisBackground] = + BlendTowardMaxContrast(kColorPrimaryBackground, gfx::kGoogleGreyAlpha100); + mixer[kColorTextSelectionForeground] = + GetColorWithMaxContrast(kColorTextSelectionBackground); } } // namespace ui
diff --git a/ui/color/mac/native_color_mixers.mm b/ui/color/mac/native_color_mixers.mm index 4cc08cd..f4be384c 100644 --- a/ui/color/mac/native_color_mixers.mm +++ b/ui/color/mac/native_color_mixers.mm
@@ -26,9 +26,8 @@ ui::kColorMenuItemForegroundDisabled, ui::kColorMenuItemForeground, ui::kColorMenuSeparator, - ui::kColorTextSelectionBackground, - ui::kColorTextfieldSelectionBackground, - ui::kColorTableBackgroundAlternate}); + ui::kColorTableBackgroundAlternate, + ui::kColorTextfieldSelectionBackground}); // clang-format on } @@ -64,14 +63,8 @@ skia::NSSystemColorToSkColor([NSColor disabledControlTextColor])}, {kColorMenuItemForeground, skia::NSSystemColorToSkColor([NSColor controlTextColor])}, - {kColorTextSelectionBackground, - skia::NSSystemColorToSkColor( - [NSColor selectedTextBackgroundColor])}, }}); - mixer[kColorMenuItemForegroundHighlighted] = {kColorPrimaryForeground}; - mixer[kColorMenuItemForegroundSelected] = {kColorPrimaryForeground}; - if (@available(macOS 10.14, *)) { mixer[kColorTableBackgroundAlternate] = {skia::NSSystemColorToSkColor( NSColor.alternatingContentBackgroundColors[1])};
diff --git a/ui/color/ui_color_mixer.cc b/ui/color/ui_color_mixer.cc index ecf814bb..23686a8 100644 --- a/ui/color/ui_color_mixer.cc +++ b/ui/color/ui_color_mixer.cc
@@ -12,90 +12,163 @@ namespace ui { -void AddUiColorMixer(ColorProvider* provider) { +void AddUiColorMixer(ColorProvider* provider, + bool dark_window, + bool high_contrast) { ColorMixer& mixer = provider->AddMixer(); - const auto button_disabled_background = - BlendForMinContrastWithSelf(kColorButtonBackground, 1.2f); - mixer[kColorAvatarHeaderArt] = {kColorMidground}; mixer[kColorAvatarIconGuest] = {kColorSecondaryForeground}; mixer[kColorAvatarIconIncognito] = {kColorPrimaryForeground}; mixer[kColorBubbleBackground] = {kColorPrimaryBackground}; + mixer[kColorBubbleBorder] = {kColorMidground}; mixer[kColorBubbleFooterBackground] = {kColorSubtleEmphasisBackground}; + mixer[kColorBubbleFooterBorder] = {kColorMidground}; mixer[kColorButtonBackground] = {kColorPrimaryBackground}; - mixer[kColorButtonBorder] = {kColorMidground}; - mixer[kColorButtonBorderDisabled] = button_disabled_background; - mixer[kColorButtonForegroundDisabled] = {kColorDisabledForeground}; - mixer[kColorButtonForeground] = {kColorAccent}; mixer[kColorButtonBackgroundPressed] = {kColorButtonBackground}; mixer[kColorButtonBackgroundProminent] = {kColorAccent}; - mixer[kColorButtonBackgroundProminentDisabled] = button_disabled_background; + mixer[kColorButtonBackgroundProminentDisabled] = { + kColorSubtleEmphasisBackground}; mixer[kColorButtonBackgroundProminentFocused] = BlendForMinContrastWithSelf(kColorButtonBackgroundProminent, 1.3f); + mixer[kColorButtonBorder] = {kColorMidground}; + mixer[kColorButtonBorderDisabled] = {kColorSubtleEmphasisBackground}; + mixer[kColorButtonForeground] = {kColorAccent}; + mixer[kColorButtonForegroundChecked] = {kColorButtonForeground}; + mixer[kColorButtonForegroundDisabled] = {kColorDisabledForeground}; mixer[kColorButtonForegroundProminent] = GetColorWithMaxContrast(kColorButtonBackgroundProminent); mixer[kColorButtonForegroundUnchecked] = {kColorSecondaryForeground}; mixer[kColorDialogBackground] = {kColorPrimaryBackground}; mixer[kColorDialogForeground] = {kColorSecondaryForeground}; + mixer[kColorDropdownBackground] = {kColorPrimaryBackground}; + mixer[kColorDropdownBackgroundSelected] = {kColorItemSelectionBackground}; + mixer[kColorDropdownForeground] = {kColorPrimaryForeground}; + mixer[kColorDropdownForegroundSelected] = {kColorPrimaryForeground}; mixer[kColorFocusableBorderFocused] = SetAlpha(kColorAccent, 0x4D); mixer[kColorFocusableBorderUnfocused] = {kColorMidground}; + mixer[kColorFrameActive] = {dark_window ? gfx::kGoogleGrey900 + : SkColorSetRGB(0xDE, 0xE1, 0xE6)}; + mixer[kColorFrameInactive] = {dark_window ? gfx::kGoogleGrey800 + : gfx::kGoogleGrey200}; + mixer[kColorHelpIconActive] = {kColorPrimaryForeground}; + mixer[kColorHelpIconInactive] = {kColorSecondaryForeground}; mixer[kColorIcon] = {kColorSecondaryForeground}; - mixer[kColorMenuIcon] = {kColorIcon}; - mixer[kColorLabelForegroundDisabled] = {kColorDisabledForeground}; + mixer[kColorIconDisabled] = SetAlpha(kColorIcon, gfx::kDisabledControlAlpha); mixer[kColorLabelForeground] = {kColorPrimaryForeground}; + mixer[kColorLabelForegroundDisabled] = {kColorDisabledForeground}; mixer[kColorLabelForegroundSecondary] = {kColorSecondaryForeground}; mixer[kColorLabelSelectionBackground] = {kColorTextSelectionBackground}; - mixer[kColorLabelSelectionForeground] = {kColorLabelForeground}; + mixer[kColorLabelSelectionForeground] = {kColorTextSelectionForeground}; + mixer[kColorLinkForeground] = {kColorAccent}; mixer[kColorLinkForegroundDisabled] = {kColorDisabledForeground}; mixer[kColorLinkForegroundPressed] = {kColorLinkForeground}; - mixer[kColorLinkForeground] = {kColorAccent}; mixer[kColorMenuBackground] = {kColorPrimaryBackground}; mixer[kColorMenuBorder] = {kColorMidground}; + mixer[kColorMenuDropmarker] = {kColorPrimaryForeground}; + mixer[kColorMenuIcon] = {kColorIcon}; mixer[kColorMenuItemBackgroundAlertedInitial] = SetAlpha(kColorAccent, 0x4D); - mixer[kColorMenuItemBackgroundAlertedTarget] = SetAlpha(kColorAccent, 0x1A); - mixer[kColorMenuItemForegroundDisabled] = {kColorDisabledForeground}; - mixer[kColorMenuItemForeground] = {kColorPrimaryForeground}; + mixer[kColorMenuItemBackgroundAlertedTarget] = + SetAlpha(kColorAccent, gfx::kGoogleGreyAlpha200); mixer[kColorMenuItemBackgroundHighlighted] = {kColorSubtleEmphasisBackground}; + mixer[kColorMenuItemBackgroundSelected] = {kColorItemSelectionBackground}; + mixer[kColorMenuItemForeground] = {kColorPrimaryForeground}; + mixer[kColorMenuItemForegroundDisabled] = {kColorDisabledForeground}; mixer[kColorMenuItemForegroundHighlighted] = {kColorMenuItemForeground}; mixer[kColorMenuItemForegroundSecondary] = {kColorSecondaryForeground}; - mixer[kColorMenuItemBackgroundSelected] = {kColorItemSelectionBackground}; mixer[kColorMenuItemForegroundSelected] = {kColorMenuItemForeground}; mixer[kColorMenuSeparator] = {kColorMidground}; + mixer[kColorNotificationActionsBackground] = { + kColorNotificationBackgroundActive}; + mixer[kColorNotificationBackgroundActive] = {kColorSubtleEmphasisBackground}; + mixer[kColorNotificationBackgroundInactive] = {kColorPrimaryBackground}; + mixer[kColorNotificationHeaderForeground] = {kColorSecondaryForeground}; + mixer[kColorNotificationIconBackground] = { + kColorNotificationHeaderForeground}; + mixer[kColorNotificationIconForeground] = { + kColorNotificationBackgroundInactive}; + mixer[kColorNotificationImageBackground] = { + kColorNotificationBackgroundActive}; + mixer[kColorNotificationInputBackground] = {kColorAccent}; + mixer[kColorNotificationInputForeground] = + GetColorWithMaxContrast(kColorNotificationInputBackground); + mixer[kColorNotificationInputPlaceholderForeground] = + SetAlpha(kColorNotificationInputForeground, gfx::kGoogleGreyAlpha700); + mixer[kColorOverlayScrollbarFill] = + SetAlpha(kColorEndpointForeground, gfx::kGoogleGreyAlpha700); + mixer[kColorOverlayScrollbarFillHovered] = + SetAlpha(kColorEndpointForeground, gfx::kGoogleGreyAlpha800); + mixer[kColorOverlayScrollbarStroke] = + SetAlpha(kColorEndpointBackground, gfx::kGoogleGreyAlpha400); + mixer[kColorOverlayScrollbarStrokeHovered] = + SetAlpha(kColorEndpointBackground, gfx::kGoogleGreyAlpha500); + mixer[kColorPwaSecurityChipForeground] = {kColorSecondaryForeground}; + mixer[kColorPwaSecurityChipForegroundDangerous] = {kColorAlertHighSeverity}; + mixer[kColorPwaSecurityChipForegroundPolicyCert] = {kColorDisabledForeground}; + mixer[kColorPwaSecurityChipForegroundSecure] = { + kColorPwaSecurityChipForeground}; + mixer[kColorPwaToolbarBackground] = {kColorEndpointBackground}; + mixer[kColorPwaToolbarForeground] = {kColorEndpointForeground}; + mixer[kColorSeparator] = {kColorMidground}; + mixer[kColorSliderThumb] = {kColorAccent}; + mixer[kColorSliderThumbMinimal] = {kColorSecondaryForeground}; + mixer[kColorSliderTrack] = {kColorSubtleAccent}; + mixer[kColorSliderTrackMinimal] = {kColorMidground}; + mixer[kColorSyncInfoBackground] = {kColorSubtleEmphasisBackground}; + mixer[kColorSyncInfoBackgroundError] = + SetAlpha(kColorAlertHighSeverity, gfx::kGoogleGreyAlpha100); + mixer[kColorSyncInfoBackgroundPaused] = + SetAlpha(kColorAccent, gfx::kGoogleGreyAlpha100); + mixer[kColorTabBackgroundHighlighted] = SetAlpha(gfx::kGoogleBlue300, 0x2B); + mixer[kColorTabBackgroundHighlightedFocused] = + SetAlpha(gfx::kGoogleBlue300, 0x53); + mixer[kColorTabBorderSelected] = {kColorAccent}; mixer[kColorTabContentSeparator] = {kColorMidground}; mixer[kColorTabForeground] = {kColorSecondaryForeground}; - mixer[kColorTabBorderSelected] = {kColorAccent}; mixer[kColorTabForegroundSelected] = {kColorAccent}; mixer[kColorTableBackground] = {kColorPrimaryBackground}; + mixer[kColorTableBackgroundSelectedFocused] = {kColorItemSelectionBackground}; + mixer[kColorTableBackgroundSelectedUnfocused] = { + kColorTableBackgroundSelectedFocused}; mixer[kColorTableForeground] = {kColorPrimaryForeground}; + mixer[kColorTableForegroundSelectedFocused] = {kColorTableForeground}; + mixer[kColorTableForegroundSelectedUnfocused] = { + kColorTableForegroundSelectedFocused}; mixer[kColorTableGroupingIndicator] = {kColorTableBackgroundSelectedFocused}; mixer[kColorTableHeaderBackground] = {kColorTableBackground}; mixer[kColorTableHeaderForeground] = {kColorTableForeground}; mixer[kColorTableHeaderSeparator] = {kColorMidground}; - mixer[kColorTableBackgroundSelectedFocused] = {kColorItemSelectionBackground}; - mixer[kColorTableForegroundSelectedFocused] = {kColorTableForeground}; - mixer[kColorTableBackgroundSelectedUnfocused] = { - kColorTableBackgroundSelectedFocused}; - mixer[kColorTableForegroundSelectedUnfocused] = { - kColorTableForegroundSelectedFocused}; - mixer[kColorTextfieldBackground] = - GetColorWithMaxContrast(kColorTextfieldForeground); + mixer[kColorTextfieldBackground] = {kColorEndpointBackground}; mixer[kColorTextfieldBackgroundDisabled] = {kColorPrimaryBackground}; + mixer[kColorTextfieldForeground] = {kColorPrimaryForeground}; mixer[kColorTextfieldForegroundDisabled] = {kColorDisabledForeground}; mixer[kColorTextfieldForegroundPlaceholder] = { kColorTextfieldForegroundDisabled}; - mixer[kColorTextfieldForeground] = {kColorPrimaryForeground}; mixer[kColorTextfieldSelectionBackground] = {kColorTextSelectionBackground}; - mixer[kColorTextfieldSelectionForeground] = {kColorTextfieldForeground}; + mixer[kColorTextfieldSelectionForeground] = {kColorTextSelectionForeground}; mixer[kColorThrobber] = {kColorAccent}; + mixer[kColorThrobberPreconnect] = {kColorSubtleAccent}; + mixer[kColorToggleButtonShadow] = {kColorMidground}; + mixer[kColorToggleButtonThumbOff] = {kColorSecondaryForeground}; + mixer[kColorToggleButtonThumbOn] = {kColorAccent}; + if (dark_window) { + mixer[kColorToggleButtonThumbOff] += + AlphaBlend(kColorPrimaryForeground, FromTransformInput(), 0x0D); + mixer[kColorToggleButtonThumbOn] += + AlphaBlend(kColorPrimaryForeground, FromTransformInput(), 0x0D); + } + mixer[kColorToggleButtonTrackOff] = { + dark_window ? ColorTransform(gfx::kGoogleGrey700) : kColorMidground}; + mixer[kColorToggleButtonTrackOn] = {dark_window ? gfx::kGoogleBlue600 + : gfx::kGoogleBlue300}; mixer[kColorTooltipBackground] = SetAlpha(kColorPrimaryBackground, 0xCC); mixer[kColorTooltipForeground] = SetAlpha(kColorPrimaryForeground, 0xDE); mixer[kColorTreeBackground] = {kColorPrimaryBackground}; - mixer[kColorTreeNodeForeground] = {kColorPrimaryForeground}; mixer[kColorTreeNodeBackgroundSelectedFocused] = { kColorItemSelectionBackground}; - mixer[kColorTreeNodeForegroundSelectedFocused] = {kColorTreeNodeForeground}; mixer[kColorTreeNodeBackgroundSelectedUnfocused] = { kColorTreeNodeBackgroundSelectedFocused}; + mixer[kColorTreeNodeForeground] = {kColorPrimaryForeground}; + mixer[kColorTreeNodeForegroundSelectedFocused] = {kColorTreeNodeForeground}; mixer[kColorTreeNodeForegroundSelectedUnfocused] = { kColorTreeNodeForegroundSelectedFocused}; mixer[kColorWindowBackground] = {kColorPrimaryBackground};
diff --git a/ui/message_center/views/notification_view_md_unittest.cc b/ui/message_center/views/notification_view_md_unittest.cc index cd00246..c67b0e2 100644 --- a/ui/message_center/views/notification_view_md_unittest.cc +++ b/ui/message_center/views/notification_view_md_unittest.cc
@@ -994,8 +994,10 @@ } TEST_F(NotificationViewMDTest, TestAccentColor) { + // TODO(pkasting): These hardcoded colors are fragile and should be obtained + // dynamically. const SkColor kNotificationBackgroundColor = SK_ColorWHITE; - const SkColor kActionButtonBackgroundColor = SkColorSetRGB(0xEE, 0xEE, 0xEE); + const SkColor kActionButtonBackgroundColor = SkColorSetRGB(0xF2, 0xF2, 0xF2); const SkColor kActionButtonTextColor = DeriveMinContrastColor(gfx::kGoogleBlue600, kActionButtonBackgroundColor); @@ -1004,7 +1006,12 @@ std::unique_ptr<Notification> notification = CreateSimpleNotification(); notification->set_buttons(CreateButtons(2)); + + // The code below is not prepared to deal with dark mode. + notification_view()->GetWidget()->GetNativeTheme()->set_use_dark_colors( + false); UpdateNotificationViews(*notification); + notification_view()->GetWidget()->Show(); // Action buttons are hidden by collapsed state.
diff --git a/ui/native_theme/common_theme.cc b/ui/native_theme/common_theme.cc index ec16386..8b361bb 100644 --- a/ui/native_theme/common_theme.cc +++ b/ui/native_theme/common_theme.cc
@@ -60,10 +60,6 @@ case NativeTheme::kColorId_AlertSeverityMedium: return GetAlertSeverityColor(color_id, true); - // Bubble - case NativeTheme::kColorId_FootnoteContainerBorder: - return gfx::kGoogleGrey900; - // Button case NativeTheme::kColorId_ProminentButtonColor: return gfx::kGoogleBlue300; @@ -82,29 +78,33 @@ case NativeTheme::kColorId_LabelTextSelectionBackgroundFocused: return gfx::kGoogleBlue800; - // Menu - case NativeTheme::kColorId_HighlightedMenuItemBackgroundColor: - return SkColorSetRGB(0x32, 0x36, 0x39); - // Separator case NativeTheme::kColorId_SeparatorColor: return gfx::kGoogleGrey800; - // Tabbed pane - case NativeTheme::kColorId_TabHighlightFocusedBackground: - return SkColorSetRGB(0x32, 0x36, 0x39); - case NativeTheme::kColorId_TabHighlightBackground: - return gfx::kGoogleGrey800; - - // Tooltip - case NativeTheme::kColorId_TooltipIcon: - return SkColorSetA(gfx::kGoogleGrey200, 0xBD); - case NativeTheme::kColorId_TooltipIconHovered: - return SK_ColorWHITE; + // Toggle button + case ui::NativeTheme::kColorId_ToggleButtonThumbColorOff: { + const SkColor enabled = + *GetDarkSchemeColor(NativeTheme::kColorId_LabelEnabledColor); + const SkColor secondary = + *GetDarkSchemeColor(NativeTheme::kColorId_LabelSecondaryColor); + return color_utils::AlphaBlend(enabled, secondary, 0.05f); + } + case ui::NativeTheme::kColorId_ToggleButtonThumbColorOn: { + const SkColor enabled = + *GetDarkSchemeColor(NativeTheme::kColorId_LabelEnabledColor); + const SkColor prominent = + *GetDarkSchemeColor(NativeTheme::kColorId_ProminentButtonColor); + return color_utils::AlphaBlend(enabled, prominent, 0.05f); + } + case ui::NativeTheme::kColorId_ToggleButtonTrackColorOff: + return gfx::kGoogleGrey700; + case ui::NativeTheme::kColorId_ToggleButtonTrackColorOn: + return gfx::kGoogleBlue600; // Window case NativeTheme::kColorId_WindowBackground: - return color_utils::AlphaBlend(SK_ColorWHITE, gfx::kGoogleGrey900, 0.04f); + return color_utils::BlendTowardMaxContrast(gfx::kGoogleGrey900, 0x0A); default: return base::nullopt; @@ -151,7 +151,6 @@ NativeTheme::kColorId_HighlightedMenuItemBackgroundColor, color_scheme); case NativeTheme::kColorId_FootnoteContainerBorder: - return gfx::kGoogleGrey200; case NativeTheme::kColorId_BubbleBorder: return base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_SeparatorColor, color_scheme); @@ -165,12 +164,10 @@ base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_ProminentButtonColor, color_scheme)); case NativeTheme::kColorId_ProminentButtonDisabledColor: - case NativeTheme::kColorId_DisabledButtonBorderColor: { - const SkColor bg = base_theme->GetUnprocessedSystemColor( - NativeTheme::kColorId_WindowBackground, color_scheme); - return color_utils::BlendForMinContrast(bg, bg, base::nullopt, 1.2f) - .color; - } + case NativeTheme::kColorId_DisabledButtonBorderColor: + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_HighlightedMenuItemBackgroundColor, + color_scheme); case NativeTheme::kColorId_ButtonBorderColor: return base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_SeparatorColor, color_scheme); @@ -240,7 +237,7 @@ case NativeTheme::kColorId_CustomFrameActiveColor: return SkColorSetRGB(0xDE, 0xE1, 0xE6); case NativeTheme::kColorId_CustomFrameInactiveColor: - return SkColorSetRGB(0xE7, 0xEA, 0xED); + return gfx::kGoogleGrey200; // Icon case NativeTheme::kColorId_DefaultIconColor: @@ -265,9 +262,12 @@ return gfx::kGoogleGrey700; case NativeTheme::kColorId_LabelEnabledColor: return gfx::kGoogleGrey900; - case NativeTheme::kColorId_LabelTextSelectionColor: - return base_theme->GetUnprocessedSystemColor( - NativeTheme::kColorId_LabelEnabledColor, color_scheme); + case NativeTheme::kColorId_LabelTextSelectionColor: { + const SkColor bg = base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_LabelTextSelectionBackgroundFocused, + color_scheme); + return color_utils::GetColorWithMaxContrast(bg); + } case NativeTheme::kColorId_LabelTextSelectionBackgroundFocused: return gfx::kGoogleBlue200; @@ -284,8 +284,11 @@ case NativeTheme::kColorId_MenuBackgroundColor: return base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_WindowBackground, color_scheme); - case NativeTheme::kColorId_HighlightedMenuItemBackgroundColor: - return gfx::kGoogleGrey050; + case NativeTheme::kColorId_HighlightedMenuItemBackgroundColor: { + const SkColor bg = base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_WindowBackground, color_scheme); + return color_utils::BlendTowardMaxContrast(bg, gfx::kGoogleGreyAlpha100); + } case NativeTheme::kColorId_MenuBorderColor: case NativeTheme::kColorId_MenuSeparatorColor: return base_theme->GetUnprocessedSystemColor( @@ -316,57 +319,55 @@ accent, (color_id == kInitial) ? 0x4D : gfx::kGoogleGreyAlpha200); } - // Message Center - case NativeTheme::kColorId_MessageCenterSmallImageMaskForeground: - return SK_ColorWHITE; - case NativeTheme::kColorId_MessageCenterSmallImageMaskBackground: - return SkColorSetRGB(0xa3, 0xa3, 0xa3); - // Notification + case NativeTheme::kColorId_MessageCenterSmallImageMaskForeground: case NativeTheme::kColorId_NotificationBackground: - case NativeTheme::kColorId_NotificationColor: return base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_WindowBackground, color_scheme); #if BUILDFLAG(IS_CHROMEOS_ASH) case NativeTheme::kColorId_NotificationButtonBackground: return SkColorSetA(SK_ColorWHITE, 0.9 * 0xff); #endif - case NativeTheme::kColorId_NotificationPlaceholderColor: - return SkColorSetA(SK_ColorWHITE, gfx::kDisabledControlAlpha); + case NativeTheme::kColorId_NotificationPlaceholderColor: { + const SkColor color = base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_TextOnProminentButtonColor, color_scheme); + return SkColorSetA(color, gfx::kGoogleGreyAlpha700); + } + case NativeTheme::kColorId_NotificationColor: + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_TextOnProminentButtonColor, color_scheme); case NativeTheme::kColorId_NotificationActionsRowBackground: - case NativeTheme::kColorId_NotificationBackgroundActive: { - const SkColor bg = base_theme->GetUnprocessedSystemColor( - NativeTheme::kColorId_WindowBackground, color_scheme); - return color_utils::BlendTowardMaxContrast(bg, 0x14); - } - case NativeTheme::kColorId_NotificationLargeImageBackground: { - const SkColor bg = base_theme->GetUnprocessedSystemColor( - NativeTheme::kColorId_WindowBackground, color_scheme); - return color_utils::BlendTowardMaxContrast(bg, 0x0C); - } + case NativeTheme::kColorId_NotificationBackgroundActive: + case NativeTheme::kColorId_NotificationLargeImageBackground: + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_HighlightedMenuItemBackgroundColor, + color_scheme); + case NativeTheme::kColorId_MessageCenterSmallImageMaskBackground: case NativeTheme::kColorId_NotificationDefaultAccentColor: - return gfx::kGoogleGrey700; + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_LabelSecondaryColor, color_scheme); case NativeTheme::kColorId_NotificationInkDropBase: - return gfx::kGoogleBlue600; + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_ProminentButtonColor, color_scheme); // Scrollbar case NativeTheme::kColorId_OverlayScrollbarThumbFill: case NativeTheme::kColorId_OverlayScrollbarThumbHoveredFill: { - SkColor fill = base_theme->GetUnprocessedSystemColor( + const SkColor fill = base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_CustomTabBarForegroundColor, color_scheme); - fill = color_utils::IsDark(fill) ? SK_ColorBLACK : SK_ColorWHITE; const bool hovered = color_id == NativeTheme::kColorId_OverlayScrollbarThumbHoveredFill; - return SkColorSetA(fill, (hovered ? 0.7 : 0.5) * SK_AlphaOPAQUE); + return SkColorSetA( + fill, hovered ? gfx::kGoogleGreyAlpha800 : gfx::kGoogleGreyAlpha700); } case NativeTheme::kColorId_OverlayScrollbarThumbStroke: case NativeTheme::kColorId_OverlayScrollbarThumbHoveredStroke: { - SkColor stroke = base_theme->GetUnprocessedSystemColor( + const SkColor stroke = base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_CustomTabBarBackgroundColor, color_scheme); - stroke = color_utils::IsDark(stroke) ? SK_ColorBLACK : SK_ColorWHITE; const bool hovered = color_id == NativeTheme::kColorId_OverlayScrollbarThumbHoveredStroke; - return SkColorSetA(stroke, (hovered ? 0.5 : 0.3) * SK_AlphaOPAQUE); + return SkColorSetA(stroke, hovered ? gfx::kGoogleGreyAlpha500 + : gfx::kGoogleGreyAlpha400); } // Separator @@ -375,29 +376,37 @@ // Slider case NativeTheme::kColorId_SliderThumbMinimal: - return SkColorSetA(gfx::kGoogleGrey100, gfx::kGoogleGreyAlpha500); + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_LabelSecondaryColor, color_scheme); case NativeTheme::kColorId_SliderTroughMinimal: - return SkColorSetA(gfx::kGoogleGrey100, 0x19); + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_SeparatorColor, color_scheme); case NativeTheme::kColorId_SliderThumbDefault: - return gfx::kGoogleBlueDark600; - case NativeTheme::kColorId_SliderTroughDefault: - return SkColorSetA(gfx::kGoogleBlueDark600, 0x40); + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_ProminentButtonColor, color_scheme); + case NativeTheme::kColorId_SliderTroughDefault: { + const SkColor bg = base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_WindowBackground, color_scheme); + const SkColor fg = base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_ProminentButtonColor, color_scheme); + return color_utils::AlphaBlend(fg, bg, gfx::kGoogleGreyAlpha400); + } // Sync info container case NativeTheme::kColorId_SyncInfoContainerNoPrimaryAccount: return base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_HighlightedMenuItemBackgroundColor, color_scheme); - case NativeTheme::kColorId_SyncInfoContainerPaused: - return SkColorSetA( - base_theme->GetUnprocessedSystemColor( - NativeTheme::kColorId_ProminentButtonColor, color_scheme), - 0x10); - case NativeTheme::kColorId_SyncInfoContainerError: - return SkColorSetA( - base_theme->GetUnprocessedSystemColor( - NativeTheme::kColorId_AlertSeverityHigh, color_scheme), - 0x10); + case NativeTheme::kColorId_SyncInfoContainerPaused: { + const SkColor fg = base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_ProminentButtonColor, color_scheme); + return SkColorSetA(fg, gfx::kGoogleGreyAlpha100); + } + case NativeTheme::kColorId_SyncInfoContainerError: { + const SkColor fg = base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_AlertSeverityHigh, color_scheme); + return SkColorSetA(fg, gfx::kGoogleGreyAlpha100); + } // Tabbed pane case NativeTheme::kColorId_TabBottomBorder: @@ -407,9 +416,9 @@ return base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_LabelSecondaryColor, color_scheme); case NativeTheme::kColorId_TabHighlightBackground: - return gfx::kGoogleBlue050; + return SkColorSetA(gfx::kGoogleBlue300, 0x2B); case NativeTheme::kColorId_TabHighlightFocusedBackground: - return gfx::kGoogleBlue100; + return SkColorSetA(gfx::kGoogleBlue300, 0x53); case NativeTheme::kColorId_TabTitleColorActive: case NativeTheme::kColorId_TabSelectedBorderColor: return base_theme->GetUnprocessedSystemColor( @@ -450,9 +459,11 @@ return base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_LabelDisabledColor, color_scheme); case NativeTheme::kColorId_TextfieldDefaultColor: - case NativeTheme::kColorId_TextfieldSelectionColor: return base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_LabelEnabledColor, color_scheme); + case NativeTheme::kColorId_TextfieldSelectionColor: + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_LabelTextSelectionColor, color_scheme); case NativeTheme::kColorId_TextfieldSelectionBackgroundFocused: return base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_LabelTextSelectionBackgroundFocused, @@ -461,28 +472,26 @@ // Throbber case NativeTheme::kColorId_ThrobberWaitingColor: return base_theme->GetUnprocessedSystemColor( - NativeTheme::kColorId_LabelTextSelectionBackgroundFocused, - color_scheme); + NativeTheme::kColorId_SliderTroughDefault, color_scheme); case NativeTheme::kColorId_ThrobberSpinningColor: return base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_ProminentButtonColor, color_scheme); // Toggle button case NativeTheme::kColorId_ToggleButtonShadowColor: - return SkColorSetA( - base_theme->GetUnprocessedSystemColor( - NativeTheme::kColorId_LabelEnabledColor, color_scheme), - 0x99); + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_SeparatorColor, color_scheme); + case ui::NativeTheme::kColorId_ToggleButtonThumbColorOff: + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_LabelSecondaryColor, color_scheme); + case ui::NativeTheme::kColorId_ToggleButtonThumbColorOn: + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_ProminentButtonColor, color_scheme); case ui::NativeTheme::kColorId_ToggleButtonTrackColorOff: - case ui::NativeTheme::kColorId_ToggleButtonTrackColorOn: { - const ui::NativeTheme::ColorId base_color_id = - color_id == ui::NativeTheme::kColorId_ToggleButtonTrackColorOff - ? ui::NativeTheme::kColorId_LabelEnabledColor - : ui::NativeTheme::kColorId_ProminentButtonColor; - return SkColorSetA( - base_theme->GetUnprocessedSystemColor(base_color_id, color_scheme), - 0x66); - } + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_SeparatorColor, color_scheme); + case ui::NativeTheme::kColorId_ToggleButtonTrackColorOn: + return gfx::kGoogleBlue300; // Tooltip case NativeTheme::kColorId_TooltipBackground: { @@ -490,24 +499,31 @@ NativeTheme::kColorId_WindowBackground, color_scheme); return SkColorSetA(bg, 0xCC); } - case NativeTheme::kColorId_TooltipIcon: - return SkColorSetA(gfx::kGoogleGrey800, 0xBD); case NativeTheme::kColorId_TooltipText: { const SkColor text = base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_LabelEnabledColor, color_scheme); return SkColorSetA(text, 0xDE); } + + // Tooltip icon + case NativeTheme::kColorId_TooltipIcon: + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_LabelSecondaryColor, color_scheme); case NativeTheme::kColorId_TooltipIconHovered: - return SkColorSetA(SK_ColorBLACK, 0xBD); + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_LabelEnabledColor, color_scheme); // Tree case NativeTheme::kColorId_TreeBackground: return base_theme->GetUnprocessedSystemColor( NativeTheme::kColorId_WindowBackground, color_scheme); case NativeTheme::kColorId_TreeSelectionBackgroundFocused: + return base_theme->GetUnprocessedSystemColor( + NativeTheme::kColorId_TableSelectionBackgroundFocused, color_scheme); case NativeTheme::kColorId_TreeSelectionBackgroundUnfocused: return base_theme->GetUnprocessedSystemColor( - NativeTheme::kColorId_DropdownSelectedBackgroundColor, color_scheme); + NativeTheme::kColorId_TableSelectionBackgroundUnfocused, + color_scheme); case NativeTheme::kColorId_TreeSelectedText: case NativeTheme::kColorId_TreeSelectedTextUnfocused: case NativeTheme::kColorId_TreeText:
diff --git a/ui/native_theme/native_theme.cc b/ui/native_theme/native_theme.cc index 3396f06..e56022d 100644 --- a/ui/native_theme/native_theme.cc +++ b/ui/native_theme/native_theme.cc
@@ -37,31 +37,54 @@ {NTCID::kColorId_AvatarIconGuest, kColorAvatarIconGuest}, {NTCID::kColorId_AvatarIconIncognito, kColorAvatarIconIncognito}, {NTCID::kColorId_BubbleBackground, kColorBubbleBackground}, + {NTCID::kColorId_BubbleBorder, kColorBubbleBorder}, {NTCID::kColorId_BubbleFooterBackground, kColorBubbleFooterBackground}, - {NTCID::kColorId_ButtonColor, kColorButtonBackground}, {NTCID::kColorId_ButtonBorderColor, kColorButtonBorder}, - {NTCID::kColorId_DisabledButtonBorderColor, kColorButtonBorderDisabled}, + {NTCID::kColorId_ButtonCheckedColor, kColorButtonForegroundChecked}, + {NTCID::kColorId_ButtonColor, kColorButtonBackground}, {NTCID::kColorId_ButtonDisabledColor, kColorButtonForegroundDisabled}, {NTCID::kColorId_ButtonEnabledColor, kColorButtonForeground}, - {NTCID::kColorId_ProminentButtonColor, - kColorButtonBackgroundProminent}, - {NTCID::kColorId_ProminentButtonDisabledColor, - kColorButtonBackgroundProminentDisabled}, - {NTCID::kColorId_ProminentButtonFocusedColor, - kColorButtonBackgroundProminentFocused}, - {NTCID::kColorId_TextOnProminentButtonColor, - kColorButtonForegroundProminent}, {NTCID::kColorId_ButtonUncheckedColor, kColorButtonForegroundUnchecked}, + {NTCID::kColorId_CustomFrameActiveColor, kColorFrameActive}, + {NTCID::kColorId_CustomFrameInactiveColor, kColorFrameInactive}, + {NTCID::kColorId_CustomTabBarBackgroundColor, + kColorPwaToolbarBackground}, + {NTCID::kColorId_CustomTabBarForegroundColor, + kColorPwaToolbarForeground}, + {NTCID::kColorId_CustomTabBarSecurityChipDangerousColor, + kColorPwaSecurityChipForegroundDangerous}, + {NTCID::kColorId_CustomTabBarSecurityChipDefaultColor, + kColorPwaSecurityChipForeground}, + {NTCID::kColorId_CustomTabBarSecurityChipSecureColor, + kColorPwaSecurityChipForegroundSecure}, + {NTCID::kColorId_CustomTabBarSecurityChipWithCertColor, + kColorPwaSecurityChipForegroundPolicyCert}, + {NTCID::kColorId_DefaultIconColor, kColorIcon}, {NTCID::kColorId_DialogBackground, kColorDialogBackground}, {NTCID::kColorId_DialogForeground, kColorDialogForeground}, + {NTCID::kColorId_DisabledButtonBorderColor, kColorButtonBorderDisabled}, + {NTCID::kColorId_DisabledIconColor, kColorIconDisabled}, + {NTCID::kColorId_DisabledMenuItemForegroundColor, + kColorMenuItemForegroundDisabled}, + {NTCID::kColorId_DropdownBackgroundColor, kColorDropdownBackground}, + {NTCID::kColorId_DropdownForegroundColor, kColorDropdownForeground}, + {NTCID::kColorId_DropdownSelectedBackgroundColor, + kColorDropdownBackgroundSelected}, + {NTCID::kColorId_DropdownSelectedForegroundColor, + kColorDropdownForegroundSelected}, + {NTCID::kColorId_EnabledMenuItemForegroundColor, + kColorMenuItemForeground}, {NTCID::kColorId_FocusedBorderColor, kColorFocusableBorderFocused}, - {NTCID::kColorId_UnfocusedBorderColor, - kColorFocusableBorderUnfocused}, - {NTCID::kColorId_MenuIconColor, kColorMenuIcon}, - {NTCID::kColorId_DefaultIconColor, kColorIcon}, + {NTCID::kColorId_FocusedMenuItemBackgroundColor, + kColorMenuItemBackgroundSelected}, + {NTCID::kColorId_FootnoteContainerBorder, kColorBubbleFooterBorder}, + {NTCID::kColorId_HighlightedMenuItemBackgroundColor, + kColorMenuItemBackgroundHighlighted}, + {NTCID::kColorId_HighlightedMenuItemForegroundColor, + kColorMenuItemForegroundHighlighted}, {NTCID::kColorId_LabelDisabledColor, kColorLabelForegroundDisabled}, {NTCID::kColorId_LabelEnabledColor, kColorLabelForeground}, {NTCID::kColorId_LabelSecondaryColor, @@ -75,76 +98,123 @@ {NTCID::kColorId_LinkPressed, kColorLinkForegroundPressed}, {NTCID::kColorId_MenuBackgroundColor, kColorMenuBackground}, {NTCID::kColorId_MenuBorderColor, kColorMenuBorder}, + {NTCID::kColorId_MenuDropIndicator, kColorMenuDropmarker}, + {NTCID::kColorId_MenuIconColor, kColorMenuIcon}, {NTCID::kColorId_MenuItemInitialAlertBackgroundColor, kColorMenuItemBackgroundAlertedInitial}, - {NTCID::kColorId_MenuItemTargetAlertBackgroundColor, - kColorMenuItemBackgroundAlertedTarget}, - {NTCID::kColorId_DisabledMenuItemForegroundColor, - kColorMenuItemForegroundDisabled}, - {NTCID::kColorId_EnabledMenuItemForegroundColor, - kColorMenuItemForeground}, - {NTCID::kColorId_HighlightedMenuItemBackgroundColor, - kColorMenuItemBackgroundHighlighted}, - {NTCID::kColorId_HighlightedMenuItemForegroundColor, - kColorMenuItemForegroundHighlighted}, {NTCID::kColorId_MenuItemMinorTextColor, kColorMenuItemForegroundSecondary}, - {NTCID::kColorId_FocusedMenuItemBackgroundColor, - kColorMenuItemBackgroundSelected}, + {NTCID::kColorId_MenuItemTargetAlertBackgroundColor, + kColorMenuItemBackgroundAlertedTarget}, + {NTCID::kColorId_MenuSeparatorColor, kColorMenuSeparator}, + {NTCID::kColorId_MessageCenterSmallImageMaskBackground, + kColorNotificationIconBackground}, + {NTCID::kColorId_MessageCenterSmallImageMaskForeground, + kColorNotificationIconForeground}, + {NTCID::kColorId_NotificationActionsRowBackground, + kColorNotificationActionsBackground}, + {NTCID::kColorId_NotificationBackground, + kColorNotificationBackgroundInactive}, + {NTCID::kColorId_NotificationBackgroundActive, + kColorNotificationBackgroundActive}, + {NTCID::kColorId_NotificationColor, kColorNotificationInputForeground}, + {NTCID::kColorId_NotificationDefaultAccentColor, + kColorNotificationHeaderForeground}, + {NTCID::kColorId_NotificationInkDropBase, + kColorNotificationInputBackground}, + {NTCID::kColorId_NotificationLargeImageBackground, + kColorNotificationImageBackground}, + {NTCID::kColorId_NotificationPlaceholderColor, + kColorNotificationInputPlaceholderForeground}, + {NTCID::kColorId_OverlayScrollbarThumbFill, kColorOverlayScrollbarFill}, + {NTCID::kColorId_OverlayScrollbarThumbHoveredFill, + kColorOverlayScrollbarFillHovered}, + {NTCID::kColorId_OverlayScrollbarThumbHoveredStroke, + kColorOverlayScrollbarStrokeHovered}, + {NTCID::kColorId_OverlayScrollbarThumbStroke, + kColorOverlayScrollbarStroke}, + {NTCID::kColorId_ProminentButtonColor, + kColorButtonBackgroundProminent}, + {NTCID::kColorId_ProminentButtonDisabledColor, + kColorButtonBackgroundProminentDisabled}, + {NTCID::kColorId_ProminentButtonFocusedColor, + kColorButtonBackgroundProminentFocused}, {NTCID::kColorId_SelectedMenuItemForegroundColor, kColorMenuItemForegroundSelected}, - {NTCID::kColorId_MenuSeparatorColor, kColorMenuSeparator}, + {NTCID::kColorId_SeparatorColor, kColorSeparator}, + {NTCID::kColorId_SliderThumbDefault, kColorSliderThumb}, + {NTCID::kColorId_SliderThumbMinimal, kColorSliderThumbMinimal}, + {NTCID::kColorId_SliderTroughDefault, kColorSliderTrack}, + {NTCID::kColorId_SliderTroughMinimal, kColorSliderTrackMinimal}, + {NTCID::kColorId_SyncInfoContainerError, kColorSyncInfoBackgroundError}, + {NTCID::kColorId_SyncInfoContainerNoPrimaryAccount, + kColorSyncInfoBackground}, + {NTCID::kColorId_SyncInfoContainerPaused, + kColorSyncInfoBackgroundPaused}, {NTCID::kColorId_TabBottomBorder, kColorTabContentSeparator}, - {NTCID::kColorId_TabTitleColorInactive, kColorTabForeground}, - {NTCID::kColorId_TabSelectedBorderColor, kColorTabBorderSelected}, - {NTCID::kColorId_TabTitleColorActive, kColorTabForegroundSelected}, + {NTCID::kColorId_TabHighlightBackground, + kColorTabBackgroundHighlighted}, + {NTCID::kColorId_TabHighlightFocusedBackground, + kColorTabBackgroundHighlightedFocused}, {NTCID::kColorId_TableBackground, kColorTableBackground}, #if defined(OS_APPLE) {NTCID::kColorId_TableBackgroundAlternate, kColorTableBackgroundAlternate}, #endif - {NTCID::kColorId_TableText, kColorTableForeground}, {NTCID::kColorId_TableGroupingIndicatorColor, kColorTableGroupingIndicator}, - {NTCID::kColorId_TableHeaderBackground, - kColorTableHeaderBackground}, + {NTCID::kColorId_TableHeaderBackground, kColorTableHeaderBackground}, + {NTCID::kColorId_TableHeaderSeparator, kColorTableHeaderSeparator}, {NTCID::kColorId_TableHeaderText, kColorTableHeaderForeground}, - // TODO(http://crbug.com/1057754): kColorId_TableHeaderSeparator, - // which is implemented as a native theme override on Mac. - {NTCID::kColorId_TableSelectionBackgroundFocused, - kColorTableBackgroundSelectedFocused}, {NTCID::kColorId_TableSelectedText, kColorTableForegroundSelectedFocused}, - {NTCID::kColorId_TableSelectionBackgroundUnfocused, - kColorTableBackgroundSelectedUnfocused}, {NTCID::kColorId_TableSelectedTextUnfocused, kColorTableForegroundSelectedUnfocused}, + {NTCID::kColorId_TableSelectionBackgroundFocused, + kColorTableBackgroundSelectedFocused}, + {NTCID::kColorId_TableSelectionBackgroundUnfocused, + kColorTableBackgroundSelectedUnfocused}, + {NTCID::kColorId_TableText, kColorTableForeground}, + {NTCID::kColorId_TabSelectedBorderColor, kColorTabBorderSelected}, + {NTCID::kColorId_TabTitleColorActive, kColorTabForegroundSelected}, + {NTCID::kColorId_TabTitleColorInactive, kColorTabForeground}, {NTCID::kColorId_TextfieldDefaultBackground, kColorTextfieldBackground}, + {NTCID::kColorId_TextfieldDefaultColor, kColorTextfieldForeground}, + {NTCID::kColorId_TextfieldPlaceholderColor, + kColorTextfieldForegroundPlaceholder}, {NTCID::kColorId_TextfieldReadOnlyBackground, kColorTextfieldBackgroundDisabled}, {NTCID::kColorId_TextfieldReadOnlyColor, kColorTextfieldForegroundDisabled}, - {NTCID::kColorId_TextfieldPlaceholderColor, - kColorTextfieldForegroundPlaceholder}, - {NTCID::kColorId_TextfieldDefaultColor, kColorTextfieldForeground}, {NTCID::kColorId_TextfieldSelectionBackgroundFocused, kColorTextfieldSelectionBackground}, {NTCID::kColorId_TextfieldSelectionColor, kColorTextfieldSelectionForeground}, + {NTCID::kColorId_TextOnProminentButtonColor, + kColorButtonForegroundProminent}, {NTCID::kColorId_ThrobberSpinningColor, kColorThrobber}, + {NTCID::kColorId_ThrobberWaitingColor, kColorThrobberPreconnect}, + {NTCID::kColorId_ToggleButtonShadowColor, kColorToggleButtonShadow}, + {NTCID::kColorId_ToggleButtonThumbColorOff, kColorToggleButtonThumbOff}, + {NTCID::kColorId_ToggleButtonThumbColorOn, kColorToggleButtonThumbOn}, + {NTCID::kColorId_ToggleButtonTrackColorOff, kColorToggleButtonTrackOff}, + {NTCID::kColorId_ToggleButtonTrackColorOn, kColorToggleButtonTrackOn}, {NTCID::kColorId_TooltipBackground, kColorTooltipBackground}, + {NTCID::kColorId_TooltipIcon, kColorHelpIconInactive}, + {NTCID::kColorId_TooltipIconHovered, kColorHelpIconActive}, {NTCID::kColorId_TooltipText, kColorTooltipForeground}, {NTCID::kColorId_TreeBackground, kColorTreeBackground}, - {NTCID::kColorId_TreeText, kColorTreeNodeForeground}, - {NTCID::kColorId_TreeSelectionBackgroundFocused, - kColorTreeNodeBackgroundSelectedFocused}, {NTCID::kColorId_TreeSelectedText, kColorTreeNodeForegroundSelectedFocused}, - {NTCID::kColorId_TreeSelectionBackgroundUnfocused, - kColorTreeNodeBackgroundSelectedUnfocused}, {NTCID::kColorId_TreeSelectedTextUnfocused, kColorTreeNodeForegroundSelectedUnfocused}, + {NTCID::kColorId_TreeSelectionBackgroundFocused, + kColorTreeNodeBackgroundSelectedFocused}, + {NTCID::kColorId_TreeSelectionBackgroundUnfocused, + kColorTreeNodeBackgroundSelectedUnfocused}, + {NTCID::kColorId_TreeText, kColorTreeNodeForeground}, + {NTCID::kColorId_UnfocusedBorderColor, kColorFocusableBorderUnfocused}, {NTCID::kColorId_WindowBackground, kColorWindowBackground}, }); auto* color_it = map.find(native_theme_color_id);
diff --git a/ui/native_theme/native_theme_color_id.h b/ui/native_theme/native_theme_color_id.h index 3117e88..6019757 100644 --- a/ui/native_theme/native_theme_color_id.h +++ b/ui/native_theme/native_theme_color_id.h
@@ -38,6 +38,8 @@ OP(kColorId_TextOnProminentButtonColor), \ /* ToggleButton */ \ OP(kColorId_ToggleButtonShadowColor), \ + OP(kColorId_ToggleButtonThumbColorOff), \ + OP(kColorId_ToggleButtonThumbColorOn), \ OP(kColorId_ToggleButtonTrackColorOff), \ OP(kColorId_ToggleButtonTrackColorOn), \ /* MenuItem */ \
diff --git a/ui/views/accessibility/ax_window_obj_wrapper.cc b/ui/views/accessibility/ax_window_obj_wrapper.cc index 869e5ae7..d58593a 100644 --- a/ui/views/accessibility/ax_window_obj_wrapper.cc +++ b/ui/views/accessibility/ax_window_obj_wrapper.cc
@@ -145,25 +145,27 @@ out_node_data->relative_bounds.bounds = gfx::RectF(window_->GetBoundsInScreen()); std::string* child_ax_tree_id_ptr = window_->GetProperty(ui::kChildAXTreeID); - if (child_ax_tree_id_ptr && ui::AXTreeID::FromString(*child_ax_tree_id_ptr) != - ui::AXTreeIDUnknown()) { - // Most often, child AX trees are parented to Views. We need to handle - // the case where they're not here, but we don't want the same AX tree - // to be a child of two different parents. - // - // To avoid this double-parenting, only add the child tree ID of this - // window if the top-level window doesn't have an associated Widget. - // - // Also, if this window is not visible, its child tree should also be - // non-visible so prune it. - if (!window_->GetToplevelWindow() || - GetWidgetForWindow(window_->GetToplevelWindow()) || - !window_->IsVisible()) { - return; - } + if (child_ax_tree_id_ptr) { + ui::AXTreeID child_ax_tree_id = + ui::AXTreeID::FromString(*child_ax_tree_id_ptr); + if (child_ax_tree_id != ui::AXTreeIDUnknown()) { + // Most often, child AX trees are parented to Views. We need to handle + // the case where they're not here, but we don't want the same AX tree + // to be a child of two different parents. + // + // To avoid this double-parenting, only add the child tree ID of this + // window if the top-level window doesn't have an associated Widget. + // + // Also, if this window is not visible, its child tree should also be + // non-visible so prune it. + if (!window_->GetToplevelWindow() || + GetWidgetForWindow(window_->GetToplevelWindow()) || + !window_->IsVisible()) { + return; + } - out_node_data->AddStringAttribute(ax::mojom::StringAttribute::kChildTreeId, - *child_ax_tree_id_ptr); + out_node_data->AddChildTreeId(child_ax_tree_id); + } } out_node_data->AddStringAttribute(ax::mojom::StringAttribute::kClassName,
diff --git a/ui/views/accessibility/view_accessibility.cc b/ui/views/accessibility/view_accessibility.cc index 5fd22a8..8cfb389a 100644 --- a/ui/views/accessibility/view_accessibility.cc +++ b/ui/views/accessibility/view_accessibility.cc
@@ -276,8 +276,7 @@ << "Please annotate child tree ids using " "ViewAccessibility::OverrideChildTreeID."; if (child_tree_id_) { - data->AddStringAttribute(ax::mojom::StringAttribute::kChildTreeId, - child_tree_id_->ToString()); + data->AddChildTreeId(child_tree_id_.value()); } }
diff --git a/ui/views/controls/button/toggle_button.cc b/ui/views/controls/button/toggle_button.cc index e64e389..82a636b 100644 --- a/ui/views/controls/button/toggle_button.cc +++ b/ui/views/controls/button/toggle_button.cc
@@ -92,10 +92,12 @@ cc::PaintFlags thumb_flags; thumb_flags.setLooper(gfx::CreateShadowDrawLooper(shadows)); thumb_flags.setAntiAlias(true); - const SkColor thumb_on_color = thumb_on_color_.value_or( - theme->GetSystemColor(ui::NativeTheme::kColorId_ProminentButtonColor)); - const SkColor thumb_off_color = thumb_off_color_.value_or( - theme->GetSystemColor(ui::NativeTheme::kColorId_ButtonColor)); + const SkColor thumb_on_color = + thumb_on_color_.value_or(theme->GetSystemColor( + ui::NativeTheme::kColorId_ToggleButtonThumbColorOn)); + const SkColor thumb_off_color = + thumb_off_color_.value_or(theme->GetSystemColor( + ui::NativeTheme::kColorId_ToggleButtonThumbColorOff)); thumb_flags.setColor( color_utils::AlphaBlend(thumb_on_color, thumb_off_color, color_ratio_));
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page.html b/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page.html index 85b5832..747a4f1d 100644 --- a/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page.html +++ b/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page.html
@@ -76,6 +76,14 @@ cursor: default; } + .scan-error-header { + --iron-icon-fill-color: #D93025; + } + + .scan-error-message { + color: var(--google-red-600); + } + .blue-icon { --iron-icon-fill-color: #1A73E8; } @@ -91,14 +99,9 @@ } #scanFailureHeader { - --iron-icon-fill-color: #D93025; margin-bottom: 4px; } - #scanFailureMessage { - color: var(--google-red-600); - } - #useCameraAgainButton { display: block; font-weight: 500; @@ -177,12 +180,20 @@ <div> <div id="scanSuccessContainer" hidden$="[[isUiElementHidden_(UiElement.SCAN_SUCCESS, state_)]]"> - <div id=scanSucessHeader> + <div id=scanSucessHeader + hidden$="[[isUiElementHidden_(UiElement.CODE_DETECTED, state_)]]"> <iron-icon class="scan-finish-image" icon="cellular-setup:checked"></iron-icon> <span class="label scan-finish-message" id="scanSuccessMessage"> [[i18n('scanQRCodeSuccess')]] </span> </div> + <div id="scanInstallFailureHeader" class="scan-error-header" + hidden$="[[isUiElementHidden_(UiElement.SCAN_INSTALL_FAILURE, state_)]]"> + <iron-icon class="scan-finish-image" icon="cellular-setup:error"></iron-icon> + <span class="label scan-finish-message scan-error-message"> + [[i18n('scanQrCodeInvalid')]] + </span> + </div> <cr-button id="useCameraAgainButton" class="blue-icon" on-click="startScanning_" disabled="[[isUiElementDisabled_(UiElement.SCAN_SUCCESS, state_, showBusy)]]"> @@ -192,9 +203,9 @@ </div> <div id="scanFailureContainer" hidden$="[[isUiElementHidden_(UiElement.SCAN_FAILURE, state_)]]"> - <div id="scanFailureHeader" class="blue-icon"> + <div id="scanFailureHeader" class="scan-error-header"> <iron-icon class="scan-finish-image" icon="cellular-setup:error"></iron-icon> - <span class="label scan-finish-message" id="scanFailureMessage"> + <span class="label scan-finish-message scan-error-message"> [[i18n('scanQrCodeError')]] </span> </div> @@ -215,7 +226,7 @@ value="{{activationCode}}" disabled="[[showBusy]]" on-keydown="onKeyDown_" - invalid="[[showError]]" + invalid="[[shouldActivationCodeInputBeInvalid_(state_)]]" error-message="[[i18n('scanQrCodeInvalid')]]"> </cr-input> <paper-spinner-lite active
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page.js b/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page.js index 0dfb6bb..86a0df9 100644 --- a/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page.js +++ b/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page.js
@@ -18,6 +18,7 @@ SCANNING_SUCCESS: 6, SCANNING_FAILURE: 7, MANUAL_ENTRY_INSTALL_FAILURE: 8, + SCANNING_INSTALL_FAILURE: 9, }; /** @enum {number} */ @@ -28,6 +29,8 @@ SCAN_FINISH: 4, SCAN_SUCCESS: 5, SCAN_FAILURE: 6, + CODE_DETECTED: 7, + SCAN_INSTALL_FAILURE: 8, }; /** @@ -395,18 +398,22 @@ /** @private */ onShowErrorChanged_() { - // TODO(crbug.com/1093185) Handle install failure from scanning. if (this.showError) { - this.state_ = PageState.MANUAL_ENTRY_INSTALL_FAILURE; - Polymer.RenderStatus.afterNextRender(this, () => { - cr.ui.focusWithoutInk(this.$.activationCode); - }); + if (this.state_ === PageState.MANUAL_ENTRY) { + this.state_ = PageState.MANUAL_ENTRY_INSTALL_FAILURE; + Polymer.RenderStatus.afterNextRender(this, () => { + cr.ui.focusWithoutInk(this.$.activationCode); + }); + } else if (this.state_ === PageState.SCANNING_SUCCESS) { + this.state_ = PageState.SCANNING_INSTALL_FAILURE; + } } }, /** @private */ onStateChanged_() { - if (this.state_ !== PageState.MANUAL_ENTRY_INSTALL_FAILURE) { + if (this.state_ !== PageState.MANUAL_ENTRY_INSTALL_FAILURE && + this.state_ !== PageState.SCANNING_INSTALL_FAILURE) { this.showError = false; } if (this.state_ === PageState.MANUAL_ENTRY) { @@ -451,11 +458,17 @@ return !(isScanning && this.cameraCount_ > 1); case UiElement.SCAN_FINISH: return state !== PageState.SCANNING_SUCCESS && - state !== PageState.SCANNING_FAILURE; + state !== PageState.SCANNING_FAILURE && + state !== PageState.SCANNING_INSTALL_FAILURE; case UiElement.SCAN_SUCCESS: - return state !== PageState.SCANNING_SUCCESS; + return state !== PageState.SCANNING_SUCCESS && + state !== PageState.SCANNING_INSTALL_FAILURE; case UiElement.SCAN_FAILURE: return state !== PageState.SCANNING_FAILURE; + case UiElement.CODE_DETECTED: + return state !== PageState.SCANNING_SUCCESS; + case UiElement.SCAN_INSTALL_FAILURE: + return state !== PageState.SCANNING_INSTALL_FAILURE; } }, @@ -489,4 +502,13 @@ return this.showNoProfilesMessage ? this.i18n('scanQRCodeNoProfiles') : this.i18n('scanQRCode'); }, + + /** + * @param {PageState} state + * @return {boolean} + * @private + */ + shouldActivationCodeInputBeInvalid_(state) { + return state === PageState.MANUAL_ENTRY_INSTALL_FAILURE; + } });
diff --git a/weblayer/browser/background_fetch/background_fetch_download.cc b/weblayer/browser/background_fetch/background_fetch_download.cc index c2a5937..c4ef437 100644 --- a/weblayer/browser/background_fetch/background_fetch_download.cc +++ b/weblayer/browser/background_fetch/background_fetch_download.cc
@@ -6,6 +6,7 @@ #include "base/strings/utf_string_conversions.h" #include "content/public/browser/background_fetch_description.h" +#include "url/origin.h" #include "weblayer/browser/background_fetch/background_fetch_delegate_impl.h" #include "weblayer/browser/background_fetch/job_details.h" @@ -92,4 +93,12 @@ return true; } +GURL BackgroundFetchDownload::GetSourceUrl() { + return job_->fetch_description->origin.GetURL(); +} + +const SkBitmap* BackgroundFetchDownload::GetLargeIcon() { + return &job_->fetch_description->icon; +} + } // namespace weblayer
diff --git a/weblayer/browser/background_fetch/background_fetch_download.h b/weblayer/browser/background_fetch/background_fetch_download.h index 69c69d7..6fc7506 100644 --- a/weblayer/browser/background_fetch/background_fetch_download.h +++ b/weblayer/browser/background_fetch/background_fetch_download.h
@@ -40,6 +40,8 @@ // DownloadImpl: int GetNotificationId() override; bool IsTransient() override; + GURL GetSourceUrl() override; + const SkBitmap* GetLargeIcon() override; private: BackgroundFetchDelegateImpl* controller_;
diff --git a/weblayer/browser/download_callback_proxy.cc b/weblayer/browser/download_callback_proxy.cc index 6574412..0b9effd 100644 --- a/weblayer/browser/download_callback_proxy.cc +++ b/weblayer/browser/download_callback_proxy.cc
@@ -5,6 +5,7 @@ #include "weblayer/browser/download_callback_proxy.h" #include "base/android/jni_string.h" +#include "url/android/gurl_android.h" #include "url/gurl.h" #include "weblayer/browser/download_impl.h" #include "weblayer/browser/java/jni/DownloadCallbackProxy_jni.h" @@ -78,7 +79,8 @@ JNIEnv* env = AttachCurrentThread(); Java_DownloadCallbackProxy_createDownload( env, java_delegate_, reinterpret_cast<jlong>(download_impl), - download_impl->GetNotificationId()); + download_impl->GetNotificationId(), download_impl->IsTransient(), + url::GURLAndroid::FromNativeGURL(env, download_impl->GetSourceUrl())); Java_DownloadCallbackProxy_downloadStarted(env, java_delegate_, download_impl->java_download()); }
diff --git a/weblayer/browser/download_impl.cc b/weblayer/browser/download_impl.cc index f30720816..c785111 100644 --- a/weblayer/browser/download_impl.cc +++ b/weblayer/browser/download_impl.cc
@@ -12,6 +12,7 @@ #if defined(OS_ANDROID) #include "base/android/jni_string.h" +#include "ui/gfx/android/java_bitmap.h" #include "weblayer/browser/java/jni/DownloadImpl_jni.h" #endif @@ -51,6 +52,17 @@ return base::android::ScopedJavaLocalRef<jstring>( base::android::ConvertUTF8ToJavaString(env, GetMimeType())); } + +base::android::ScopedJavaLocalRef<jobject> DownloadImpl::GetLargeIconImpl( + JNIEnv* env) { + base::android::ScopedJavaLocalRef<jobject> j_icon; + const SkBitmap* icon = GetLargeIcon(); + + if (icon && !icon->drawsNothing()) + j_icon = gfx::ConvertToJavaBitmap(*icon); + + return j_icon; +} #endif DownloadImpl::DownloadImpl() = default;
diff --git a/weblayer/browser/download_impl.h b/weblayer/browser/download_impl.h index 7df2af2..ca92f08 100644 --- a/weblayer/browser/download_impl.h +++ b/weblayer/browser/download_impl.h
@@ -9,12 +9,15 @@ #include "base/memory/weak_ptr.h" #include "base/supports_user_data.h" #include "build/build_config.h" +#include "url/gurl.h" #include "weblayer/public/download.h" #if defined(OS_ANDROID) #include "base/android/scoped_java_ref.h" #endif +class SkBitmap; + namespace weblayer { // Base class for downloads that should be represented in the UI. @@ -39,7 +42,7 @@ JNIEnv* env); base::android::ScopedJavaLocalRef<jstring> GetMimeTypeImpl(JNIEnv* env); int GetErrorImpl(JNIEnv* env) { return static_cast<int>(GetError()); } - bool IsTransientImpl(JNIEnv* env) { return IsTransient(); } + base::android::ScopedJavaLocalRef<jobject> GetLargeIconImpl(JNIEnv* env); base::android::ScopedJavaGlobalRef<jobject> java_download() { return java_download_; @@ -50,10 +53,17 @@ // unique across all DownloadImpls. virtual int GetNotificationId() = 0; - // A transient download is not persisted to disk, which will affect its UI + // A transient download is not persisted to disk, which affects its UI // treatment. virtual bool IsTransient() = 0; + // Returns the originating URL for this download. + virtual GURL GetSourceUrl() = 0; + + // Gets the icon to display. If the return value is null or draws nothing, no + // icon will be displayed. + virtual const SkBitmap* GetLargeIcon() = 0; + // Returns whether this download has been added to the UI via // DownloadDelegate::OnDownloadStarted. bool HasBeenAddedToUi();
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/DownloadCallbackProxy.java b/weblayer/browser/java/org/chromium/weblayer_private/DownloadCallbackProxy.java index 347a551..9235cc26 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/DownloadCallbackProxy.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/DownloadCallbackProxy.java
@@ -14,6 +14,7 @@ import org.chromium.base.annotations.JNINamespace; import org.chromium.base.annotations.NativeMethods; import org.chromium.ui.base.WindowAndroid; +import org.chromium.url.GURL; import org.chromium.weblayer_private.interfaces.IDownloadCallbackClient; import org.chromium.weblayer_private.interfaces.ObjectWrapper; @@ -99,9 +100,10 @@ } @CalledByNative - private DownloadImpl createDownload(long nativeDownloadImpl, int id) { - return new DownloadImpl( - mProfile.getName(), mProfile.isIncognito(), mClient, nativeDownloadImpl, id); + private DownloadImpl createDownload( + long nativeDownloadImpl, int id, boolean isTransient, GURL sourceUrl) { + return new DownloadImpl(mProfile.getName(), mProfile.isIncognito(), mClient, + nativeDownloadImpl, id, isTransient, sourceUrl); } @CalledByNative
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/DownloadImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/DownloadImpl.java index 490cf760..7bcb103 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/DownloadImpl.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/DownloadImpl.java
@@ -8,7 +8,9 @@ import android.content.Context; import android.content.Intent; import android.content.res.Resources; +import android.graphics.Bitmap; import android.net.Uri; +import android.os.Build; import android.os.RemoteException; import android.text.TextUtils; @@ -25,6 +27,7 @@ import org.chromium.components.browser_ui.notifications.NotificationMetadata; import org.chromium.components.browser_ui.notifications.PendingIntentProvider; import org.chromium.components.browser_ui.util.DownloadUtils; +import org.chromium.url.GURL; import org.chromium.weblayer_private.interfaces.APICallException; import org.chromium.weblayer_private.interfaces.DownloadError; import org.chromium.weblayer_private.interfaces.DownloadState; @@ -73,6 +76,18 @@ private long mNativeDownloadImpl; private boolean mDisableNotification; + // The time this download started, in milliseconds. + private final long mStartTime; + + // A transient download is not persisted to disk, which affects its UI treatment. + private final boolean mIsTransient; + + // The originating URL for this download. + private final GURL mSourceUrl; + + // The large icon to show. Once this is successfully fetched from native, it won't be updated. + private Bitmap mLargeIcon; + private final int mNotificationId; private static final HashMap<Integer, DownloadImpl> sMap = new HashMap<Integer, DownloadImpl>(); @@ -149,12 +164,16 @@ } public DownloadImpl(String profileName, boolean isIncognito, IDownloadCallbackClient client, - long nativeDownloadImpl, int id) { + long nativeDownloadImpl, int id, boolean isTransient, GURL sourceUrl) { mProfileName = profileName; mIsIncognito = isIncognito; - mClient = DownloadImplJni.get().isTransientImpl(nativeDownloadImpl) ? null : client; + mClient = isTransient ? null : client; mNativeDownloadImpl = nativeDownloadImpl; mNotificationId = id; + mStartTime = System.currentTimeMillis(); + mIsTransient = isTransient; + mSourceUrl = sourceUrl; + if (mClient == null) { mClientDownload = null; } else { @@ -350,6 +369,12 @@ @DownloadState int state = getState(); + if (state == DownloadState.CANCELLED) { + notificationManager.cancel(NOTIFICATION_TAG, mNotificationId); + mDisableNotification = true; + return; + } + String channelId = state == DownloadState.COMPLETE ? WebLayerNotificationChannels.ChannelId.COMPLETED_DOWNLOADS : WebLayerNotificationChannels.ChannelId.ACTIVE_DOWNLOADS; @@ -357,6 +382,8 @@ WebLayerNotificationWrapperBuilder builder = WebLayerNotificationWrapperBuilder.create( channelId, new NotificationMetadata(0, NOTIFICATION_TAG, mNotificationId)); builder.setOngoing(true) + .setWhen(mStartTime) + .setShowWhen(true) .setDeleteIntent(deletePendingIntent) .setPriorityBeforeO(NotificationCompat.PRIORITY_DEFAULT); @@ -366,27 +393,40 @@ builder.setContentTitle(name); } - if (state == DownloadState.CANCELLED) { - notificationManager.cancel(NOTIFICATION_TAG, mNotificationId); - mDisableNotification = true; - return; + // Set the large icon/thumbnail, except when incognito. + if (!mIsIncognito && mLargeIcon == null) { + mLargeIcon = DownloadImplJni.get().getLargeIconImpl(mNativeDownloadImpl); } + if (mLargeIcon != null) { + builder.setLargeIcon(mLargeIcon); + } + + // As with Chrome, transient downloads "promote" the source URL. + if (!mIsIncognito && mIsTransient) { + String formattedUrl = DownloadUtils.formatUrlForDisplayInNotification(mSourceUrl); + if (formattedUrl != null) setSubText(builder, formattedUrl); + } + // TODO(estade): In incognito, Chrome uses a subtext of "Incognito tab". Should WL display + // something similar? Resources resources = context.getResources(); if (state == DownloadState.COMPLETE) { - String contextText = - resources.getString(R.string.download_notification_completed_with_size, - DownloadUtils.getStringForBytes(context, getTotalBytes())); - builder.setContentText(contextText) - .setOngoing(false) + builder.setOngoing(false) .setSmallIcon(android.R.drawable.stat_sys_download_done) .setAutoCancel(true) .setProgress(0, 0, false); - // TODO(estade): for transient downloads, create an intent that delegates back to native - // code. - if (!DownloadImplJni.get().isTransientImpl(mNativeDownloadImpl)) { + if (mIsTransient) { + builder.setContentText( + resources.getString(R.string.download_notification_completed)); + // TODO(estade): for transient downloads, create an intent that delegates back to + // native code. + } else { + builder.setContentText( + resources.getString(R.string.download_notification_completed_with_size, + DownloadUtils.getStringForBytes(context, getTotalBytes()))); + Intent openIntent = createIntent(OPEN_INTENT); openIntent.putExtra(EXTRA_NOTIFICATION_LOCATION, getLocation()); openIntent.putExtra(EXTRA_NOTIFICATION_MIME_TYPE, getMimeType()); @@ -454,6 +494,19 @@ } /** + * Helper method to set the sub text on different versions of Android. + * @param builder The builder to build notification. + * @param subText A string shown as sub text on the notification. + */ + private static void setSubText(WebLayerNotificationWrapperBuilder builder, String subText) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + builder.setSubText(subText); + } else { + builder.setContentInfo(subText); + } + } + + /** * Returns the notification manager. */ private static NotificationManagerProxy getNotificationManager() { @@ -485,6 +538,6 @@ String getFileNameToReportToUserImpl(long nativeDownloadImpl); String getMimeTypeImpl(long nativeDownloadImpl); int getErrorImpl(long nativeDownloadImpl); - boolean isTransientImpl(long nativeDownloadImpl); + Bitmap getLargeIconImpl(long nativeDownloadImpl); } }
diff --git a/weblayer/browser/persistent_download.cc b/weblayer/browser/persistent_download.cc index bd27ca2531..316e2ecb 100644 --- a/weblayer/browser/persistent_download.cc +++ b/weblayer/browser/persistent_download.cc
@@ -140,6 +140,14 @@ return false; } +GURL PersistentDownload::GetSourceUrl() { + return {}; +} + +const SkBitmap* PersistentDownload::GetLargeIcon() { + return nullptr; +} + void PersistentDownload::ResumeInternal() { if (resume_pending_) { resume_pending_ = false;
diff --git a/weblayer/browser/persistent_download.h b/weblayer/browser/persistent_download.h index 8d45e380..4a6f961a 100644 --- a/weblayer/browser/persistent_download.h +++ b/weblayer/browser/persistent_download.h
@@ -40,6 +40,8 @@ // DownloadImpl: int GetNotificationId() override; bool IsTransient() override; + GURL GetSourceUrl() override; + const SkBitmap* GetLargeIcon() override; private: explicit PersistentDownload(download::DownloadItem* item);
diff --git a/weblayer/grit_strings_allowlist.txt b/weblayer/grit_strings_allowlist.txt index 4a32bebae0..f8f75765 100644 --- a/weblayer/grit_strings_allowlist.txt +++ b/weblayer/grit_strings_allowlist.txt
@@ -81,6 +81,7 @@ IDS_CLOCK_ERROR_UPDATE_DATE_AND_TIME IDS_DEFAULT_ENCODING IDS_DOWNLOAD_NOTIFICATION_CANCEL_BUTTON +IDS_DOWNLOAD_NOTIFICATION_COMPLETED IDS_DOWNLOAD_NOTIFICATION_COMPLETED_WITH_SIZE IDS_DOWNLOAD_NOTIFICATION_FAILED IDS_DOWNLOAD_NOTIFICATION_PAUSED