diff --git a/.gn b/.gn index e3ff7d4b..22e155c1 100644 --- a/.gn +++ b/.gn
@@ -250,10 +250,8 @@ "//third_party/blink/renderer/core/workers:*", # 289 errors "//third_party/blink/renderer/core/xmlhttprequest:*", # 49 errors "//third_party/blink/renderer/core:*", # 823 errors - "//third_party/blink/renderer/modules/canvas:*", # 1 error "//third_party/blink/renderer/modules/font_access:*", # 3 errors "//third_party/blink/renderer/modules/peerconnection:*", # 43 errors - "//third_party/blink/renderer/platform:*", # 10 errors "//third_party/breakpad:*", # 34 errors "//third_party/ced/*",
diff --git a/DEPS b/DEPS index 85d11de..e88c938 100644 --- a/DEPS +++ b/DEPS
@@ -171,7 +171,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:18502e6a01811b0c2dd2a0250e81bd82e47d2c2d', + 'luci_go': 'git_revision:b022173f8069cf8001d4cf2a87ce7c5f0eae220f', # This can be overridden, e.g. with custom_vars, to build clang from HEAD # instead of downloading the prebuilt pinned revision. @@ -195,7 +195,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '081bc32703b7eb62728e6b5478e24e55c8f84463', + 'skia_revision': '2bc4077c9e4216fba03607d61d4f1bda43a60eb8', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -203,11 +203,11 @@ # 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. - 'swarming_revision': '4c095d04179dc725a300085ae21fe3b79900d072', + 'swarming_revision': '44c13d73156581ea09b9389001e58c23a4b8d70a', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '75d257686e00d26633d0ae4648b1c9939fffda22', + 'angle_revision': '2296e7afd74851bd287f46f06864b904365b05ce', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -266,7 +266,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling devtools-frontend # and whatever else without interference from each other. - 'devtools_frontend_revision': '02fad13e19503b82c73778c2cf54bc25cb2dd652', + 'devtools_frontend_revision': 'd1b7c5ca690cf6874aa2f69713048a688ed1f1b0', # 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. @@ -322,7 +322,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': '5c52ad843f8a33546cc17f4e7f05e6ab0df92c43', + 'quiche_revision': '093f8e4f0014522e32896cfa4d1d8e5510b41788', # 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. @@ -545,7 +545,7 @@ }, 'src/ios/third_party/material_components_ios/src': { - 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '6543af21be74965abb609e792d744f8f76fe4c63', + 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'dc8add9b14b393940bd3430c5dffa51f016424e5', 'condition': 'checkout_ios', }, @@ -896,7 +896,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'a1e15498cd2dd4b2cc8826e65dbee2c2b0b63aa9', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '0547fb291708a09df5e9873561aee0eed6889133', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), @@ -947,7 +947,7 @@ Var('chromium_git') + '/codecs/libgav1.git' + '@' + 'a9449e612bc251b4271bbe1e3a0d12e9809bf74c', 'src/third_party/glslang/src': - Var('chromium_git') + '/external/github.com/KhronosGroup/glslang.git' + '@' + 'f8a5602c55606f8e97f5576c85cbc2a58026a999', + Var('chromium_git') + '/external/github.com/KhronosGroup/glslang.git' + '@' + 'ac2f01f4bd89762c084003003a15c2be0939877d', 'src/third_party/google_toolbox_for_mac/src': { 'url': Var('chromium_git') + '/external/github.com/google/google-toolbox-for-mac.git' + '@' + Var('google_toolbox_for_mac_revision'), @@ -1249,7 +1249,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + 'bef393a5a340a4d6303b263cba7adee98372ab7f', + Var('android_git') + '/platform/external/perfetto.git' + '@' + 'cfda0b2aaf01f3fc41a9885114baeab0c368477e', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1428,7 +1428,7 @@ }, 'src/third_party/usrsctp/usrsctplib': - Var('chromium_git') + '/external/github.com/sctplab/usrsctp' + '@' + 'a8c51df76caae94254b1e59999405f739467490e', + Var('chromium_git') + '/external/github.com/sctplab/usrsctp' + '@' + '995c0b84414466d77d52011e5b572cbe213b770a', 'src/third_party/vulkan_memory_allocator': Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + '6c656df63da5995a932aafd45b32af1974e497d9', @@ -1471,7 +1471,7 @@ }, 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '8452ea86c5cbc8f3626c00ddd38ac43db57f1c4d', + Var('webrtc_git') + '/src.git' + '@' + '7703f23b60c493744aba84977aec459cbc33f016', 'src/third_party/libgifcodec': Var('skia_git') + '/libgifcodec' + '@'+ Var('libgifcodec_revision'), @@ -1543,7 +1543,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@44c9ca6a2c0e352909ae9cf9206b6155380446f3', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@a0ee89a93f645c9eb91e107360503fc96cb6c61e', 'condition': 'checkout_src_internal', }, @@ -1551,7 +1551,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/help_app/app', - 'version': '_QUWBlAB3zSpGuENS-ygkl0rPTkolBKtlvjdPANqPVEC', + 'version': 'Efy7gVoSk1mOpec4spFNgvpGxdfwB3frPpVKkwksne8C', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -1562,7 +1562,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/media_app/app', - 'version': 'MEjLKGkVlDNdHj0W1rgJY5UBkUoBb16icAog6f-mvaEC', + 'version': 'tbdCdSmxCSExSm3_J4ZD3I0NKirjX4F7MA1Lr38MjDcC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -1972,17 +1972,6 @@ 'dep_type': 'cipd', }, - 'src/third_party/android_deps/libs/androidx_legacy_legacy_support_v13': { - 'packages': [ - { - 'package': 'chromium/third_party/android_deps/libs/androidx_legacy_legacy_support_v13', - 'version': 'version:1.0.0-cr0', - }, - ], - 'condition': 'checkout_android', - 'dep_type': 'cipd', - }, - 'src/third_party/android_deps/libs/androidx_legacy_legacy_support_v4': { 'packages': [ {
diff --git a/PRESUBMIT.py b/PRESUBMIT.py index fbbf6fd..543843a 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py
@@ -1200,7 +1200,7 @@ ( 'mojo::MakeRequest is deprecated.', 'Use mojo::AssociatedRemote::' - 'BindNewEndpointAndPassDedicatedReceiverForTesting() instead.', + 'BindNewEndpointAndPassDedicatedReceiver() instead.', ), ), (
diff --git a/android_webview/browser/aw_browser_policy_connector.cc b/android_webview/browser/aw_browser_policy_connector.cc index 881a34e..369724c 100644 --- a/android_webview/browser/aw_browser_policy_connector.cc +++ b/android_webview/browser/aw_browser_policy_connector.cc
@@ -8,9 +8,9 @@ #include "android_webview/browser/aw_browser_process.h" #include "base/bind.h" -#include "components/policy/core/browser/android/android_combined_policy_provider.h" #include "components/policy/core/browser/configuration_policy_handler_list.h" #include "components/policy/core/browser/url_blocklist_policy_handler.h" +#include "components/policy/core/common/android/android_combined_policy_provider.h" #include "components/policy/core/common/policy_details.h" #include "components/policy/core/common/policy_pref_names.h" #include "components/policy/policy_constants.h"
diff --git a/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java b/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java index 72d1fcd..4d9db1d1 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java +++ b/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java
@@ -45,10 +45,10 @@ import org.chromium.base.task.TaskRunner; import org.chromium.base.task.TaskTraits; import org.chromium.components.minidump_uploader.CrashFileManager; +import org.chromium.components.policy.CombinedPolicyProvider; import org.chromium.content_public.browser.BrowserStartupController; import org.chromium.content_public.browser.ChildProcessCreationParams; import org.chromium.content_public.browser.ChildProcessLauncherHelper; -import org.chromium.policy.CombinedPolicyProvider; import java.io.File; import java.io.FileNotFoundException;
diff --git a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java index 03a5140..c27c16ec 100644 --- a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java +++ b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
@@ -61,6 +61,9 @@ + "crash reporting is typically compiled but disabled."), Flag.commandLine(GpuSwitches.DISABLE_GPU_RASTERIZATION, "Disables GPU rasterization, i.e. rasterizes on the CPU only."), + Flag.commandLine(GpuSwitches.IGNORE_GPU_BLOCKLIST, + "Overrides the built-in software rendering list and enables " + + "GPU acceleration on unsupported device configurations."), Flag.baseFeature("OutOfBlinkCors", "Moves CORS logic into the Network Service (rather than inside the blink " + "rendering engine)."),
diff --git a/android_webview/java/src/org/chromium/android_webview/common/crash/CrashUploadUtil.java b/android_webview/java/src/org/chromium/android_webview/common/crash/CrashUploadUtil.java index 7c45cef..312826c 100644 --- a/android_webview/java/src/org/chromium/android_webview/common/crash/CrashUploadUtil.java +++ b/android_webview/java/src/org/chromium/android_webview/common/crash/CrashUploadUtil.java
@@ -11,6 +11,7 @@ import androidx.annotation.NonNull; import androidx.annotation.UiThread; +import androidx.annotation.VisibleForTesting; import org.chromium.android_webview.common.services.ServiceNames; import org.chromium.base.Log; @@ -28,12 +29,43 @@ private static final String TAG = "CrashUploadUtil"; /** + * Delegate interface to mock network status check and scheduling upload jobs for testing. + */ + @VisibleForTesting + public static interface CrashUploadDelegate { + /** + * Schedule a MinidumpUploadJobService to attempt uploading all ready crash minidumps. + */ + void scheduleNewJob(@NonNull Context context); + + /** + * Check if network is unmetered or not. + */ + boolean isNetworkUnmetered(@NonNull Context context); + } + + private static CrashUploadDelegate sDelegate = new CrashUploadDelegate() { + @Override + public void scheduleNewJob(@NonNull Context context) { + JobInfo.Builder builder = new JobInfo.Builder(TaskIds.WEBVIEW_MINIDUMP_UPLOADING_JOB_ID, + new ComponentName(context, ServiceNames.AW_MINIDUMP_UPLOAD_JOB_SERVICE)); + MinidumpUploadJobService.scheduleUpload(builder); + } + + @Override + public boolean isNetworkUnmetered(@NonNull Context context) { + ConnectivityManager connectivityManager = + (ConnectivityManager) context.getApplicationContext().getSystemService( + Context.CONNECTIVITY_SERVICE); + return NetworkPermissionUtil.isNetworkUnmetered(connectivityManager); + } + }; + + /** * Schedule a MinidumpUploadJobService to attempt uploading all ready crash minidumps. */ public static void scheduleNewJob(@NonNull Context context) { - JobInfo.Builder builder = new JobInfo.Builder(TaskIds.WEBVIEW_MINIDUMP_UPLOADING_JOB_ID, - new ComponentName(context, ServiceNames.AW_MINIDUMP_UPLOAD_JOB_SERVICE)); - MinidumpUploadJobService.scheduleUpload(builder); + sDelegate.scheduleNewJob(context); } /** @@ -66,10 +98,12 @@ } public static boolean isNetworkUnmetered(@NonNull Context context) { - ConnectivityManager connectivityManager = - (ConnectivityManager) context.getApplicationContext().getSystemService( - Context.CONNECTIVITY_SERVICE); - return NetworkPermissionUtil.isNetworkUnmetered(connectivityManager); + return sDelegate.isNetworkUnmetered(context); + } + + @VisibleForTesting + public static void setCrashUploadDelegateForTesting(CrashUploadDelegate delegate) { + sDelegate = delegate; } // Do not instantiate this class.
diff --git a/android_webview/java/src/org/chromium/android_webview/policy/AwPolicyProvider.java b/android_webview/java/src/org/chromium/android_webview/policy/AwPolicyProvider.java index 12250fb..68020092 100644 --- a/android_webview/java/src/org/chromium/android_webview/policy/AwPolicyProvider.java +++ b/android_webview/java/src/org/chromium/android_webview/policy/AwPolicyProvider.java
@@ -9,7 +9,7 @@ import androidx.annotation.VisibleForTesting; -import org.chromium.policy.AppRestrictionsProvider; +import org.chromium.components.policy.AppRestrictionsProvider; /** * Does the plumbing between the policies collected via Android's App Restriction system and the
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AndroidScrollIntegrationTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AndroidScrollIntegrationTest.java index 7eb07265..c4426e3 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AndroidScrollIntegrationTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AndroidScrollIntegrationTest.java
@@ -449,13 +449,8 @@ } @Test - /** - * @SmallTest - * @Feature({"AndroidWebView"}) - * BUG=813837 - */ - // Originally flaked only in multi-process mode (http://crbug.com/616505) - @DisabledTest + @SmallTest + @Feature({"AndroidWebView"}) public void testTouchScrollCanBeAlteredByUi() throws Throwable { final TestAwContentsClient contentsClient = new TestAwContentsClient(); final ScrollTestContainerView testContainerView =
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/PolicyUrlFilteringTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/PolicyUrlFilteringTest.java index 9a286448..08e1ece 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/PolicyUrlFilteringTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/PolicyUrlFilteringTest.java
@@ -23,13 +23,13 @@ import org.chromium.android_webview.WebviewErrorCode; import org.chromium.android_webview.policy.AwPolicyProvider; import org.chromium.base.test.util.Feature; +import org.chromium.components.policy.AbstractAppRestrictionsProvider; +import org.chromium.components.policy.CombinedPolicyProvider; +import org.chromium.components.policy.test.PolicyData; +import org.chromium.components.policy.test.annotations.Policies; import org.chromium.content_public.browser.test.util.TestCallbackHelperContainer; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.net.test.util.TestWebServer; -import org.chromium.policy.AbstractAppRestrictionsProvider; -import org.chromium.policy.CombinedPolicyProvider; -import org.chromium.policy.test.PolicyData; -import org.chromium.policy.test.annotations.Policies; import java.util.ArrayList; import java.util.Arrays;
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/devui/CrashesListFragmentTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/devui/CrashesListFragmentTest.java index 0b9e4cc2..deee8e9 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/devui/CrashesListFragmentTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/devui/CrashesListFragmentTest.java
@@ -7,19 +7,30 @@ import static androidx.test.espresso.Espresso.onData; import static androidx.test.espresso.Espresso.onView; import static androidx.test.espresso.action.ViewActions.click; +import static androidx.test.espresso.action.ViewActions.longClick; +import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist; import static androidx.test.espresso.assertion.ViewAssertions.matches; +import static androidx.test.espresso.intent.Intents.assertNoUnverifiedIntents; +import static androidx.test.espresso.intent.Intents.intended; +import static androidx.test.espresso.intent.Intents.intending; import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; import static androidx.test.espresso.matcher.ViewMatchers.isEnabled; import static androidx.test.espresso.matcher.ViewMatchers.withId; import static androidx.test.espresso.matcher.ViewMatchers.withText; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.anything; +import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; import static org.chromium.android_webview.test.common.crash.CrashInfoTest.createCrashInfo; +import static org.chromium.android_webview.test.devui.DeveloperUiTestUtils.getClipBoardTextOnUiThread; +import static org.chromium.android_webview.test.devui.DeveloperUiTestUtils.setClipBoardTextOnUiThread; import static org.chromium.android_webview.test.devui.DeveloperUiTestUtils.withCount; +import android.app.Activity; +import android.app.Instrumentation.ActivityResult; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; @@ -29,12 +40,14 @@ import android.graphics.Canvas; import android.graphics.drawable.Drawable; import android.support.test.InstrumentationRegistry; -import android.support.test.rule.ActivityTestRule; import android.view.View; import android.widget.ImageView; import androidx.annotation.IdRes; import androidx.test.espresso.DataInteraction; +import androidx.test.espresso.intent.Intents; +import androidx.test.espresso.intent.matcher.IntentMatchers; +import androidx.test.espresso.intent.rule.IntentsTestRule; import androidx.test.filters.LargeTest; import org.hamcrest.Description; @@ -48,10 +61,13 @@ import org.chromium.android_webview.common.crash.CrashInfo; import org.chromium.android_webview.common.crash.CrashInfo.UploadState; +import org.chromium.android_webview.common.crash.CrashUploadUtil; +import org.chromium.android_webview.common.crash.CrashUploadUtil.CrashUploadDelegate; import org.chromium.android_webview.common.crash.SystemWideCrashDirectories; import org.chromium.android_webview.devui.CrashesListFragment; import org.chromium.android_webview.devui.MainActivity; import org.chromium.android_webview.devui.R; +import org.chromium.android_webview.devui.util.CrashBugUrlFactory; import org.chromium.android_webview.test.AwJUnit4ClassRunner; import org.chromium.base.FileUtils; import org.chromium.base.test.util.CallbackHelper; @@ -77,13 +93,15 @@ private static final String CRASH_UPLOAD_BUTTON_TEXT = "Upload this crash report"; @Rule - public ActivityTestRule mRule = - new ActivityTestRule<MainActivity>(MainActivity.class, false, false); + public IntentsTestRule mRule = + new IntentsTestRule<MainActivity>(MainActivity.class, false, false); @After public void tearDown() { FileUtils.recursivelyDeleteFile(SystemWideCrashDirectories.getWebViewCrashDir(), null); FileUtils.recursivelyDeleteFile(SystemWideCrashDirectories.getWebViewCrashLogDir(), null); + // Tests are responsible for verifying every Intent they trigger. + assertNoUnverifiedIntents(); } private void launchCrashesFragment() { @@ -91,6 +109,11 @@ intent.putExtra(MainActivity.FRAGMENT_ID_INTENT_EXTRA, MainActivity.FRAGMENT_ID_CRASHES); mRule.launchActivity(intent); onView(withId(R.id.fragment_crashes_list)).check(matches(isDisplayed())); + + // Stub all external intents, to avoid launching other apps (ex. system browser), has to be + // done after launching the activity. + intending(not(IntentMatchers.isInternal())) + .respondWith(new ActivityResult(Activity.RESULT_OK, null)); } private static File createMinidumpFile(CrashInfo crashInfo) throws IOException { @@ -309,6 +332,55 @@ @Test @Feature({"AndroidWebView"}) + public void testOpenBugReportCrash() throws Throwable { + final long systemTime = System.currentTimeMillis(); + CrashInfo crashInfo = createCrashInfo("123456", systemTime, "0abcde123456", + systemTime + 1000, FAKE_APP_PACKAGE_NAME, UploadState.UPLOADED); + + assertThat("temp json log file should exist", writeJsonLogFile(crashInfo).exists()); + assertThat("upload log file should exist", appendUploadedEntryToLog(crashInfo).exists()); + + CallbackHelper helper = getCrashListLoadedListener(); + int crashListLoadInitCount = helper.getCallCount(); + launchCrashesFragment(); + helper.waitForCallback(crashListLoadInitCount, 1); + + onView(withId(R.id.crashes_list)).check(matches(withCount(1))); + // Click the header to expand the list item. + onData(anything()).atPosition(0).perform(click()); + // The body is considered item#2 in the list view after expansion. + onView(withId(R.id.crashes_list)).check(matches(withCount(2))); + onData(anything()) + .atPosition(1) + .onChildView(withId(R.id.crash_report_button)) + .perform(click()); + onView(withText(CrashesListFragment.CRASH_BUG_DIALOG_MESSAGE)) + .check(matches(isDisplayed())); + // button2 is the AlertDialog negative button id. + onView(withId(android.R.id.button2)).check(matches(withText("Dismiss"))).perform(click()); + onView(withText(CrashesListFragment.CRASH_BUG_DIALOG_MESSAGE)).check(doesNotExist()); + // Verify that no intents are sent out. + Intents.times(0); + + onData(anything()) + .atPosition(1) + .onChildView(withId(R.id.crash_report_button)) + .perform(click()); + // button1 is the AlertDialog positive button id. + onView(withId(android.R.id.button1)) + .check(matches(withText("Provide more info"))) + .perform(click()); + onView(withText(CrashesListFragment.CRASH_BUG_DIALOG_MESSAGE)).check(doesNotExist()); + Intent expectedIntent = new CrashBugUrlFactory(crashInfo).getReportIntent(); + // TODO(hazems): use IntentMatchers.filterEquals() after pulling the new version of + // espresso-intents + intended(allOf(IntentMatchers.hasAction(expectedIntent.getAction()), + IntentMatchers.hasData(expectedIntent.getData()))); + } + + @Test + @LargeTest + @Feature({"AndroidWebView"}) public void testShowingSingleCrashReport_pending() throws Throwable { final long systemTime = System.currentTimeMillis(); CrashInfo crashInfo = createCrashInfo( @@ -425,6 +497,124 @@ @Test @Feature({"AndroidWebView"}) + public void testForceUploadSkippedCrashReport_noWifi() throws Throwable { + final long systemTime = System.currentTimeMillis(); + CrashInfo crashInfo = createCrashInfo( + "123456", systemTime, null, -1, FAKE_APP_PACKAGE_NAME, UploadState.SKIPPED); + + File minidumpFile = createMinidumpFile(crashInfo); + assertThat("temp minidump file should exist", minidumpFile.exists()); + assertThat("temp json log file should exist", writeJsonLogFile(crashInfo).exists()); + + CrashUploadUtil.setCrashUploadDelegateForTesting(new CrashUploadDelegate() { + @Override + public void scheduleNewJob(Context context) {} + + @Override + public boolean isNetworkUnmetered(Context context) { + return false; + } + }); + + CallbackHelper helper = getCrashListLoadedListener(); + int crashListLoadInitCount = helper.getCallCount(); + launchCrashesFragment(); + helper.waitForCallback(crashListLoadInitCount, 1); + + onView(withId(R.id.crashes_list)).check(matches(withCount(1))); + + // click on the crash item header to expand + onData(anything()).atPosition(0).perform(click()); + // The body is considered item#2 in the list view after expansion + onView(withId(R.id.crashes_list)).check(matches(withCount(2))); + DataInteraction bodyDataInteraction = onData(anything()).atPosition(1); + checkCrashItemUploadStatus(bodyDataInteraction, crashInfo); + + // Firstly test clicking the upload button, and dismissing the dialog + bodyDataInteraction.onChildView(withId(R.id.crash_upload_button)).perform(click()); + onView(withText(CrashesListFragment.NO_WIFI_DIALOG_MESSAGE)).check(matches(isDisplayed())); + // button2 is the AlertDialog negative button id. + onView(withId(android.R.id.button2)).check(matches(withText("Cancel"))).perform(click()); + // Check no changes in the view after dismissing the dialog + checkCrashItemUploadStatus(bodyDataInteraction, crashInfo); + bodyDataInteraction.onChildView(withId(R.id.crash_upload_button)) + .check(matches(isDisplayed())); + + // Secondly test clicking the upload button, and proceeding with upload. + crashListLoadInitCount = helper.getCallCount(); + bodyDataInteraction.onChildView(withId(R.id.crash_upload_button)).perform(click()); + onView(withText(CrashesListFragment.NO_WIFI_DIALOG_MESSAGE)).check(matches(isDisplayed())); + // button1 is the AlertDialog positive button id. + onView(withId(android.R.id.button1)).check(matches(withText("Upload"))).perform(click()); + helper.waitForCallback(crashListLoadInitCount, 1); + // upload button is now hidden + bodyDataInteraction.onChildView(withId(R.id.crash_upload_button)) + .check(matches(not(isDisplayed()))); + crashInfo.uploadState = UploadState.PENDING_USER_REQUESTED; + checkCrashItemUploadStatus(bodyDataInteraction, crashInfo); + + // Check that minidump file suffix is changed to ".forced" + File renamedMinidumpFile = + new File(minidumpFile.getAbsolutePath().replace("skipped", "forced")); + assertThat("skipped minidump file shouldn't exist", not(minidumpFile.exists())); + assertThat("renamed forced minidump file should exist", renamedMinidumpFile.exists()); + } + + @Test + @LargeTest + @Feature({"AndroidWebView"}) + public void testForceUploadSkippedCrashReport_withWifi() throws Throwable { + final long systemTime = System.currentTimeMillis(); + CrashInfo crashInfo = createCrashInfo( + "123456", systemTime, null, -1, FAKE_APP_PACKAGE_NAME, UploadState.SKIPPED); + + File minidumpFile = createMinidumpFile(crashInfo); + assertThat("temp minidump file should exist", minidumpFile.exists()); + assertThat("temp json log file should exist", writeJsonLogFile(crashInfo).exists()); + + CrashUploadUtil.setCrashUploadDelegateForTesting(new CrashUploadDelegate() { + @Override + public void scheduleNewJob(Context context) {} + + @Override + public boolean isNetworkUnmetered(Context context) { + return true; + } + }); + + CallbackHelper helper = getCrashListLoadedListener(); + int crashListLoadInitCount = helper.getCallCount(); + launchCrashesFragment(); + helper.waitForCallback(crashListLoadInitCount, 1); + + onView(withId(R.id.crashes_list)).check(matches(withCount(1))); + + // click on the crash item header to expand + onData(anything()).atPosition(0).perform(click()); + // The body is considered item#2 in the list view after expansion + onView(withId(R.id.crashes_list)).check(matches(withCount(2))); + DataInteraction bodyDataInteraction = onData(anything()).atPosition(1); + checkCrashItemUploadStatus(bodyDataInteraction, crashInfo); + + crashListLoadInitCount = helper.getCallCount(); + bodyDataInteraction.onChildView(withId(R.id.crash_upload_button)).perform(click()); + helper.waitForCallback(crashListLoadInitCount, 1); + // upload button is now hidden + bodyDataInteraction.onChildView(withId(R.id.crash_upload_button)) + .check(matches(not(isDisplayed()))); + crashInfo.uploadState = UploadState.PENDING_USER_REQUESTED; + checkCrashItemUploadStatus(bodyDataInteraction, crashInfo); + + // Check that minidump file suffix is changed to ".forced" + File renamedMinidumpFile = + new File(minidumpFile.getAbsolutePath().replace("skipped", "forced")); + assertThat("skipped minidump file shouldn't exist", not(minidumpFile.exists())); + assertThat("renamed forced minidump file should exist", renamedMinidumpFile.exists()); + } + + @Test + @LargeTest + @Feature({"AndroidWebView"}) // Test when a crash has a known package name that can be found using PackageManager public void testInstalledPackageInfo() throws Throwable { Context context = InstrumentationRegistry.getTargetContext(); @@ -593,4 +783,80 @@ onView(withId(R.id.crashes_list)).check(matches(withCount(0))); } + + @Test + @LargeTest + @Feature({"AndroidWebView"}) + public void testRefreshMenuOption() throws Throwable { + CallbackHelper helper = getCrashListLoadedListener(); + int crashListLoadInitCount = helper.getCallCount(); + launchCrashesFragment(); + helper.waitForCallback(crashListLoadInitCount, 1); + + onView(withId(R.id.crashes_list)).check(matches(withCount(0))); + + final long systemTime = System.currentTimeMillis(); + CrashInfo crashInfo = createCrashInfo( + "123456", systemTime, null, -1, FAKE_APP_PACKAGE_NAME, UploadState.PENDING); + + assertThat("temp minidump file should exist", createMinidumpFile(crashInfo).exists()); + assertThat("temp json log file should exist", writeJsonLogFile(crashInfo).exists()); + + crashListLoadInitCount = helper.getCallCount(); + onView(withText("Refresh")).check(matches(isDisplayed())); + onView(withText("Refresh")).perform(click()); + helper.waitForCallback(crashListLoadInitCount, 1); + + onView(withId(R.id.crashes_list)).check(matches(withCount(1))); + checkUnknownPackageCrashItemHeader(onData(anything()).atPosition(0), crashInfo); + } + + @Test + @LargeTest + @Feature({"AndroidWebView"}) + public void testLongPressCopy() throws Throwable { + Context context = InstrumentationRegistry.getTargetContext(); + final long systemTime = System.currentTimeMillis(); + CrashInfo uploadedCrashInfo = createCrashInfo("123456", systemTime - 1000, "0abcde123456", + systemTime, FAKE_APP_PACKAGE_NAME, UploadState.UPLOADED); + CrashInfo pendingCrashInfo = createCrashInfo( + "78910", systemTime - 2000, null, -1, FAKE_APP_PACKAGE_NAME, UploadState.PENDING); + + assertThat("temp json log file for uploaded crash should exist", + writeJsonLogFile(uploadedCrashInfo).exists()); + assertThat("upload log file should exist", + appendUploadedEntryToLog(uploadedCrashInfo).exists()); + + assertThat("temp minidump file for pending crash should exist", + createMinidumpFile(pendingCrashInfo).exists()); + assertThat("temp json log file for pending crash should exist", + writeJsonLogFile(pendingCrashInfo).exists()); + + CallbackHelper helper = getCrashListLoadedListener(); + int crashListLoadInitCount = helper.getCallCount(); + launchCrashesFragment(); + helper.waitForCallback(crashListLoadInitCount, 1); + + onView(withId(R.id.crashes_list)).check(matches(withCount(2))); + + // click on the first crash item header to expand + onData(anything()).atPosition(0).perform(click()); + // long click on the crash item body to copy + onData(anything()).atPosition(1).perform(longClick()); + String expectedUploadInfo = new Date(uploadedCrashInfo.uploadTime).toString() + + "\nID: " + uploadedCrashInfo.uploadId; + assertThat(getClipBoardTextOnUiThread(context), is(expectedUploadInfo)); + + // click on the first crash item header to collapse + onData(anything()).atPosition(0).perform(click()); + // click on the second crash item header to expand + onData(anything()).atPosition(1).perform(click()); + // Clear clipboard content + setClipBoardTextOnUiThread(context, "", ""); + // Crash body is now the second item in the list view, long click on the crash item body to + // copy. + onData(anything()).atPosition(2).perform(longClick()); + // This a pending upload, nothing should be copied + assertThat(getClipBoardTextOnUiThread(context), is("")); + } }
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/devui/DeveloperUiTestUtils.java b/android_webview/javatests/src/org/chromium/android_webview/test/devui/DeveloperUiTestUtils.java index 613747848..411aaab 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/devui/DeveloperUiTestUtils.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/devui/DeveloperUiTestUtils.java
@@ -6,6 +6,7 @@ import static org.hamcrest.Matchers.is; +import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; import android.view.View; @@ -63,6 +64,17 @@ }); } + public static void setClipBoardTextOnUiThread(Context context, String key, String value) + throws ExecutionException { + // ClipManager service has to be called on the UI main thread. + TestThreadUtils.runOnUiThreadBlocking(() -> { + ClipboardManager clipboardManager = + (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); + ClipData clip = ClipData.newPlainText(key, value); + clipboardManager.setPrimaryClip(clip); + }); + } + // Don't instantiate this class. private DeveloperUiTestUtils() {} }
diff --git a/android_webview/nonembedded/java/src/org/chromium/android_webview/devui/CrashesListFragment.java b/android_webview/nonembedded/java/src/org/chromium/android_webview/devui/CrashesListFragment.java index da2409f..06a2c5d 100644 --- a/android_webview/nonembedded/java/src/org/chromium/android_webview/devui/CrashesListFragment.java +++ b/android_webview/nonembedded/java/src/org/chromium/android_webview/devui/CrashesListFragment.java
@@ -62,6 +62,13 @@ public class CrashesListFragment extends DevUiBaseFragment { private static final String TAG = "WebViewDevTools"; + public static final String CRASH_BUG_DIALOG_MESSAGE = + "This crash has already been reported to our crash system. " + + "Do you want to share more information, such as steps to reproduce the crash?"; + public static final String NO_WIFI_DIALOG_MESSAGE = + "You are connected to a metered network or cellular data." + + " Do you want to proceed?"; + // Max number of crashes to show in the crashes list. public static final int MAX_CRASHES_NUMBER = 20; @@ -273,9 +280,7 @@ if (!CrashUploadUtil.isNetworkUnmetered(mContext)) { new AlertDialog.Builder(mContext) .setTitle("Network Warning") - .setMessage( - "You are connected to a metered network or cellular data." - + " Do you want to proceed?") + .setMessage(NO_WIFI_DIALOG_MESSAGE) .setPositiveButton("Upload", (dialog, id) -> { logCrashInteraction( @@ -503,9 +508,7 @@ private AlertDialog buildCrashBugDialog(CrashInfo crashInfo) { AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(mContext); - dialogBuilder.setMessage( - "This crash has already been reported to our crash system. Do you want to share " - + "more information, such as steps to reproduce the crash?"); + dialogBuilder.setMessage(CRASH_BUG_DIALOG_MESSAGE); dialogBuilder.setPositiveButton("Provide more info", (dialog, id) -> { logCrashInteraction(CrashInteraction.FILE_BUG_REPORT_DIALOG_PROCEED); startActivity(new CrashBugUrlFactory(crashInfo).getReportIntent());
diff --git a/android_webview/system_webview_apk_tmpl.gni b/android_webview/system_webview_apk_tmpl.gni index e9f4a27..dad91d6a 100644 --- a/android_webview/system_webview_apk_tmpl.gni +++ b/android_webview/system_webview_apk_tmpl.gni
@@ -53,6 +53,9 @@ } else { if (_is_bundle_module && weblayer_in_split) { deps += [ + # TODO(crbug.com/1105096): WebLayer resources are added to the base + # module for now because of bugs with shared resources in splits. + ":${target_name}__all_weblayer_resources", "//android_webview:android_webview_no_weblayer_java", "//weblayer/browser/java:base_module_java", ]
diff --git a/android_webview/system_webview_bundle.gni b/android_webview/system_webview_bundle.gni index 284ad06..3a852ae 100644 --- a/android_webview/system_webview_bundle.gni +++ b/android_webview/system_webview_bundle.gni
@@ -27,6 +27,18 @@ name = "weblayer" module_target = ":${_weblayer_module_target}" } + + # TODO(crbug.com/1105096): This target is needed to add all WebLayer + # resources to the base module because of bugs with shared resources in + # splits. + android_resources("${_base_target_name}__all_weblayer_resources") { + recursive_resource_deps = true + deps = [ "//weblayer/browser/java" ] + if (defined(invoker.weblayer_deps)) { + deps += invoker.weblayer_deps + } + } + android_app_bundle_module(_weblayer_module_target) { forward_variables_from(invoker, [
diff --git a/android_webview/test/shell/src/org/chromium/android_webview/test/AwJUnit4ClassRunner.java b/android_webview/test/shell/src/org/chromium/android_webview/test/AwJUnit4ClassRunner.java index 1c8d1a0d7..4840a38 100644 --- a/android_webview/test/shell/src/org/chromium/android_webview/test/AwJUnit4ClassRunner.java +++ b/android_webview/test/shell/src/org/chromium/android_webview/test/AwJUnit4ClassRunner.java
@@ -13,7 +13,7 @@ import org.chromium.android_webview.test.OnlyRunIn.ProcessMode; import org.chromium.base.CommandLine; import org.chromium.base.test.BaseJUnit4ClassRunner; -import org.chromium.policy.test.annotations.Policies; +import org.chromium.components.policy.test.annotations.Policies; import java.util.ArrayList; import java.util.List;
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index ee1ec24..eb0f710e 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -925,8 +925,12 @@ "system/holding_space/holding_space_item_chip_view.h", "system/holding_space/holding_space_item_chips_container.cc", "system/holding_space/holding_space_item_chips_container.h", - "system/holding_space/holding_space_screenshot_view.cc", - "system/holding_space/holding_space_screenshot_view.h", + "system/holding_space/holding_space_item_context_menu.cc", + "system/holding_space/holding_space_item_context_menu.h", + "system/holding_space/holding_space_item_screenshot_view.cc", + "system/holding_space/holding_space_item_screenshot_view.h", + "system/holding_space/holding_space_item_view.cc", + "system/holding_space/holding_space_item_view.h", "system/holding_space/holding_space_tray.cc", "system/holding_space/holding_space_tray.h", "system/holding_space/pinned_files_container.cc",
diff --git a/ash/ambient/ambient_controller.cc b/ash/ambient/ambient_controller.cc index 8f1d2df..12d0453 100644 --- a/ash/ambient/ambient_controller.cc +++ b/ash/ambient/ambient_controller.cc
@@ -44,6 +44,7 @@ #include "ui/base/ui_base_types.h" #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_delegate.h" +#include "ui/wm/core/cursor_manager.h" #include "ui/wm/core/visibility_controller.h" #include "ui/wm/core/window_animations.h" @@ -549,6 +550,9 @@ widget->Show(); + // Hide cursor. + Shell::Get()->cursor_manager()->HideCursor(); + // Requests keyboard focus for |container_view_| to receive keyboard events. container_view_->RequestFocus(); }
diff --git a/ash/ambient/ambient_controller_unittest.cc b/ash/ambient/ambient_controller_unittest.cc index f10b0ab..bedd5fc2 100644 --- a/ash/ambient/ambient_controller_unittest.cc +++ b/ash/ambient/ambient_controller_unittest.cc
@@ -11,6 +11,7 @@ #include "ash/ambient/test/ambient_ash_test_base.h" #include "ash/ambient/ui/ambient_container_view.h" #include "ash/public/cpp/ambient/ambient_ui_model.h" +#include "ash/shell.h" #include "ash/system/power/power_status.h" #include "base/run_loop.h" #include "base/test/bind_test_util.h" @@ -474,4 +475,25 @@ EXPECT_TRUE(ambient_controller()->IsShown()); } +TEST_F(AmbientControllerTest, HideCursor) { + auto* cursor_manager = Shell::Get()->cursor_manager(); + LockScreen(); + + cursor_manager->ShowCursor(); + EXPECT_TRUE(cursor_manager->IsCursorVisible()); + + FastForwardToInactivity(); + FastForwardToNextImage(); + + EXPECT_TRUE(container_view()); + EXPECT_EQ(AmbientUiModel::Get()->ui_visibility(), + AmbientUiVisibility::kShown); + EXPECT_TRUE(ambient_controller()->IsShown()); + EXPECT_FALSE(cursor_manager->IsCursorVisible()); + + // Clean up. + UnlockScreen(); + EXPECT_FALSE(ambient_controller()->IsShown()); +} + } // namespace ash
diff --git a/ash/ambient/ui/ambient_background_image_view.cc b/ash/ambient/ui/ambient_background_image_view.cc index 4f3aadf..b4d28189 100644 --- a/ash/ambient/ui/ambient_background_image_view.cc +++ b/ash/ambient/ui/ambient_background_image_view.cc
@@ -6,8 +6,10 @@ #include <memory> +#include "ash/ambient/ui/glanceable_info_view.h" #include "ash/ambient/util/ambient_util.h" #include "ash/assistant/ui/assistant_view_ids.h" +#include "base/rand_util.h" #include "ui/events/event.h" #include "ui/gfx/geometry/insets.h" #include "ui/views/controls/image_view.h" @@ -21,14 +23,22 @@ namespace { // Appearance. -constexpr int kHorizontalMarginDip = 16; -constexpr int kVerticalMarginDip = 43; +constexpr int kMarginDip = 16; +constexpr int kSpacingDip = 8; // Typography. constexpr SkColor kTextColor = SK_ColorWHITE; constexpr int kDefaultFontSizeDip = 64; constexpr int kDetailsFontSizeDip = 13; +// The dicretion to translate glanceable info views in the x/y coordinates. `1` +// means positive translate, `-1` negative. +int translate_x_direction = 1; +int translate_y_direction = -1; +// The current x/y translation of glanceable info views in Dip. +int current_x_translation = 0; +int current_y_translation = 0; + } // namespace AmbientBackgroundImageView::AmbientBackgroundImageView( @@ -57,6 +67,8 @@ void AmbientBackgroundImageView::UpdateImage(const gfx::ImageSkia& img) { image_view_->SetImage(img); + + UpdateGlanceableInfoPosition(); } void AmbientBackgroundImageView::UpdateImageDetails( @@ -78,16 +90,29 @@ // Inits the image view. This view should have the same size of the screen. image_view_ = AddChildView(std::make_unique<views::ImageView>()); + gfx::Insets shadow_insets = + gfx::ShadowValue::GetMargin(ambient::util::GetTextShadowValues()); + // Inits the attribution view. It also has a full-screen size and is // responsible for layout the details label at its bottom left corner. views::View* attribution_view = AddChildView(std::make_unique<views::View>()); views::BoxLayout* attribution_layout = attribution_view->SetLayoutManager(std::make_unique<views::BoxLayout>( - views::BoxLayout::Orientation::kHorizontal)); + views::BoxLayout::Orientation::kVertical)); attribution_layout->set_main_axis_alignment( - views::BoxLayout::MainAxisAlignment::kStart); + views::BoxLayout::MainAxisAlignment::kEnd); + attribution_layout->set_cross_axis_alignment( + views::BoxLayout::CrossAxisAlignment::kStart); attribution_layout->set_inside_border_insets( - gfx::Insets(0, kHorizontalMarginDip, kVerticalMarginDip, 0)); + gfx::Insets(0, kMarginDip + shadow_insets.left(), + kMarginDip + shadow_insets.bottom(), 0)); + + attribution_layout->set_between_child_spacing( + kSpacingDip + shadow_insets.top() + shadow_insets.bottom()); + + glanceable_info_view_ = attribution_view->AddChildView( + std::make_unique<GlanceableInfoView>(delegate_)); + glanceable_info_view_->SetPaintToLayer(); // Inits the details label. details_label_ = @@ -98,11 +123,45 @@ ambient::util::GetDefaultFontlist().DeriveWithSizeDelta( kDetailsFontSizeDip - kDefaultFontSizeDip)); details_label_->SetShadows(ambient::util::GetTextShadowValues()); - details_label_->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT); - details_label_->SetVerticalAlignment(gfx::VerticalAlignment::ALIGN_BOTTOM); + details_label_->SetPaintToLayer(); + details_label_->layer()->SetFillsBoundsOpaquely(false); } -BEGIN_METADATA(AmbientBackgroundImageView, views::ImageView) +void AmbientBackgroundImageView::UpdateGlanceableInfoPosition() { + constexpr int kStepDP = 5; + constexpr int kMaxTranslationDip = 20; + + // Move the translation point randomly one step on each x/y direction. + int x_increment = kStepDP * base::RandInt(0, 1); + int y_increment = x_increment == 0 ? kStepDP : kStepDP * base::RandInt(0, 1); + current_x_translation += translate_x_direction * x_increment; + current_y_translation += translate_y_direction * y_increment; + + // If the translation point is out of bounds, reset it within bounds and + // reverse the direction. + if (current_x_translation < 0) { + translate_x_direction = 1; + current_x_translation = 0; + } else if (current_x_translation > kMaxTranslationDip) { + translate_x_direction = -1; + current_x_translation = kMaxTranslationDip; + } + + if (current_y_translation > 0) { + translate_y_direction = -1; + current_y_translation = 0; + } else if (current_y_translation < -kMaxTranslationDip) { + translate_y_direction = 1; + current_y_translation = -kMaxTranslationDip; + } + + gfx::Transform transform; + transform.Translate(current_x_translation, current_y_translation); + glanceable_info_view_->layer()->SetTransform(transform); + details_label_->layer()->SetTransform(transform); +} + +BEGIN_METADATA(AmbientBackgroundImageView, views::View) END_METADATA } // namespace ash
diff --git a/ash/ambient/ui/ambient_background_image_view.h b/ash/ambient/ui/ambient_background_image_view.h index 7607694..fbbb046e 100644 --- a/ash/ambient/ui/ambient_background_image_view.h +++ b/ash/ambient/ui/ambient_background_image_view.h
@@ -19,6 +19,8 @@ namespace ash { +class GlanceableInfoView; + // AmbientBackgroundImageView-------------------------------------------------- // A custom ImageView to display photo image and details information on ambient. // It also handles specific mouse/gesture events to dismiss ambient when user @@ -49,12 +51,16 @@ private: void InitLayout(); + void UpdateGlanceableInfoPosition(); + // Owned by |AmbientController| and should always outlive |this|. AmbientViewDelegate* delegate_ = nullptr; // View to display the current image on ambient. Owned by the view hierarchy. views::ImageView* image_view_ = nullptr; + GlanceableInfoView* glanceable_info_view_ = nullptr; + // Label to show details text, i.e. attribution, to be displayed for the // current image. Owned by the view hierarchy. views::Label* details_label_ = nullptr;
diff --git a/ash/ambient/ui/ambient_container_view.cc b/ash/ambient/ui/ambient_container_view.cc index 24803e8..4f7d01d 100644 --- a/ash/ambient/ui/ambient_container_view.cc +++ b/ash/ambient/ui/ambient_container_view.cc
@@ -9,7 +9,6 @@ #include "ash/ambient/ui/ambient_assistant_container_view.h" #include "ash/ambient/ui/ambient_view_delegate.h" -#include "ash/ambient/ui/glanceable_info_view.h" #include "ash/ambient/ui/media_string_view.h" #include "ash/ambient/ui/photo_view.h" #include "ash/ambient/util/ambient_util.h" @@ -39,7 +38,6 @@ // Appearance. constexpr int kHorizontalMarginDip = 16; -constexpr int kVerticalMarginDip = 64; constexpr int kAssistantPreferredHeightDip = 128; constexpr int kMediaStringTopMarginDip = 25; @@ -60,7 +58,8 @@ DCHECK(container_); event_monitor_ = views::EventMonitor::CreateWindowMonitor( this, container_->GetWidget()->GetNativeWindow()->GetRootWindow(), - {ui::ET_KEY_PRESSED, ui::ET_MOUSE_ENTERED, ui::ET_MOUSE_MOVED}); + {ui::ET_KEY_PRESSED, ui::ET_MOUSE_ENTERED, ui::ET_MOUSE_MOVED, + ui::ET_TOUCH_PRESSED, ui::ET_TOUCH_MOVED}); } ~HostWidgetEventObserver() override = default; @@ -75,6 +74,10 @@ DCHECK(event.IsKeyEvent()); container_->HandleEvent(); break; + case ui::ET_TOUCH_PRESSED: + case ui::ET_TOUCH_MOVED: + container_->HandleEvent(); + break; case ui::ET_MOUSE_ENTERED: DCHECK(event.IsMouseEvent()); // Updates the mouse enter location. @@ -133,7 +136,6 @@ void AmbientContainerView::Layout() { // Layout child views first to have proper bounds set for children. LayoutPhotoView(); - LayoutGlanceableInfoView(); LayoutMediaStringView(); // The assistant view may not exist if |kAmbientAssistant| feature is // disabled. @@ -155,9 +157,6 @@ photo_view_ = AddChildView(std::make_unique<PhotoView>(delegate_)); - glanceable_info_view_ = - AddChildView(std::make_unique<GlanceableInfoView>(delegate_)); - media_string_view_ = AddChildView(std::make_unique<MediaStringView>()); media_string_view_->SetVisible(false); @@ -173,19 +172,6 @@ photo_view_->SetBoundsRect(GetLocalBounds()); } -void AmbientContainerView::LayoutGlanceableInfoView() { - const gfx::Size container_size = GetLocalBounds().size(); - const gfx::Size preferred_size = glanceable_info_view_->GetPreferredSize(); - - // The clock and weather view is positioned on the left-bottom corner of the - // container. - int x = kHorizontalMarginDip; - int y = - container_size.height() - kVerticalMarginDip - preferred_size.height(); - glanceable_info_view_->SetBoundsRect( - gfx::Rect(x, y, preferred_size.width(), preferred_size.height())); -} - void AmbientContainerView::LayoutAssistantView() { int preferred_width = GetPreferredSize().width(); int preferred_height = kAssistantPreferredHeightDip;
diff --git a/ash/ambient/ui/ambient_container_view.h b/ash/ambient/ui/ambient_container_view.h index 6e5dbce..2cd56ea6 100644 --- a/ash/ambient/ui/ambient_container_view.h +++ b/ash/ambient/ui/ambient_container_view.h
@@ -15,7 +15,6 @@ class AmbientAssistantContainerView; class AmbientViewDelegate; -class GlanceableInfoView; class PhotoView; class MediaStringView; @@ -42,7 +41,6 @@ // TODO(meilinw): Use LayoutManagers to lay out children instead of overriding // Layout(). See b/163170162. void LayoutPhotoView(); - void LayoutGlanceableInfoView(); void LayoutAssistantView(); void LayoutMediaStringView(); @@ -54,7 +52,6 @@ // Owned by view hierarchy. PhotoView* photo_view_ = nullptr; AmbientAssistantContainerView* ambient_assistant_container_view_ = nullptr; - GlanceableInfoView* glanceable_info_view_ = nullptr; MediaStringView* media_string_view_ = nullptr; // Observes events from its host widget.
diff --git a/ash/ambient/ui/glanceable_info_view.cc b/ash/ambient/ui/glanceable_info_view.cc index df51bbf6..948db49 100644 --- a/ash/ambient/ui/glanceable_info_view.cc +++ b/ash/ambient/ui/glanceable_info_view.cc
@@ -16,6 +16,7 @@ #include "ash/system/model/clock_model.h" #include "ash/system/model/system_tray_model.h" #include "ash/system/time/time_view.h" +#include "ash/system/tray/tray_constants.h" #include "base/i18n/number_formatting.h" #include "base/strings/utf_string_conversions.h" #include "third_party/skia/include/core/SkColor.h" @@ -57,15 +58,13 @@ temperature_font_size_delta); } -// Returns the border insets for |weather_info_| to be aligned to the time text -// baseline. -gfx::Insets GetWeatherInfoInsets() { - int time_font_descent = - GetTimeFontList().GetHeight() - GetTimeFontList().GetBaseline(); - int temperature_font_descent = GetWeatherTemperatureFontList().GetHeight() - - GetWeatherTemperatureFontList().GetBaseline(); - return gfx::Insets( - 0, 0, /*bottom=*/time_font_descent - temperature_font_descent, 0); +int GetTimeFontDescent() { + return GetTimeFontList().GetHeight() - GetTimeFontList().GetBaseline(); +} + +int GetTemperatureFontDescent() { + return GetWeatherTemperatureFontList().GetHeight() - + GetWeatherTemperatureFontList().GetBaseline(); } } // namespace @@ -128,9 +127,11 @@ views::BoxLayout* layout = SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::Orientation::kHorizontal)); - layout->set_main_axis_alignment(views::BoxLayout::MainAxisAlignment::kCenter); + layout->set_main_axis_alignment(views::BoxLayout::MainAxisAlignment::kStart); layout->set_cross_axis_alignment(views::BoxLayout::CrossAxisAlignment::kEnd); - layout->set_between_child_spacing(kSpacingBetweenTimeAndWeatherDip); + + gfx::ShadowValues text_shadow_values = ambient::util::GetTextShadowValues(); + gfx::Insets shadow_insets = gfx::ShadowValue::GetMargin(text_shadow_values); // Inits the time view. time_view_ = AddChildView(std::make_unique<tray::TimeView>( @@ -139,35 +140,31 @@ time_view_->SetTextFont(GetTimeFontList()); time_view_->SetTextColor(kTextColor, /*auto_color_readability_enabled=*/false); - time_view_->SetTextShadowValues(ambient::util::GetTextShadowValues()); - - // Inits and layouts the weather info. - weather_info_ = AddChildView(std::make_unique<views::View>()); - views::BoxLayout* weather_info_layout = - weather_info_->SetLayoutManager(std::make_unique<views::BoxLayout>( - views::BoxLayout::Orientation::kHorizontal)); - // Aligns its child views to the center point. - weather_info_layout->set_cross_axis_alignment( - views::BoxLayout::CrossAxisAlignment::kCenter); - weather_info_layout->set_between_child_spacing( - kSpacingBetweenWeatherIconAndTempDip); - - // This view should be baseline-aligned to the time view. - weather_info_layout->set_inside_border_insets(GetWeatherInfoInsets()); + time_view_->SetTextShadowValues(text_shadow_values); + // Remove the internal spacing in `time_view_` and adjust spacing for shadows. + time_view_->SetBorder(views::CreateEmptyBorder( + -kUnifiedTrayTextTopPadding, -kUnifiedTrayTimeLeftPadding, 0, + kSpacingBetweenTimeAndWeatherDip + shadow_insets.right())); // Inits the icon view. - weather_condition_icon_ = - weather_info_->AddChildView(std::make_unique<views::ImageView>()); + weather_condition_icon_ = AddChildView(std::make_unique<views::ImageView>()); const gfx::Size size = gfx::Size(kWeatherIconSizeDip, kWeatherIconSizeDip); weather_condition_icon_->SetSize(size); weather_condition_icon_->SetImageSize(size); + constexpr int kIconInternalPaddingDip = 4; + weather_condition_icon_->SetBorder(views::CreateEmptyBorder( + 0, 0, + GetTimeFontDescent() - shadow_insets.bottom() - kIconInternalPaddingDip, + kSpacingBetweenWeatherIconAndTempDip + shadow_insets.left())); // Inits the temp view. - temperature_ = weather_info_->AddChildView(std::make_unique<views::Label>()); + temperature_ = AddChildView(std::make_unique<views::Label>()); temperature_->SetAutoColorReadabilityEnabled(false); temperature_->SetEnabledColor(kTextColor); temperature_->SetFontList(GetWeatherTemperatureFontList()); - temperature_->SetShadows(ambient::util::GetTextShadowValues()); + temperature_->SetShadows(text_shadow_values); + temperature_->SetBorder(views::CreateEmptyBorder( + 0, 0, GetTimeFontDescent() - GetTemperatureFontDescent(), 0)); } } // namespace ash
diff --git a/ash/ambient/ui/glanceable_info_view.h b/ash/ambient/ui/glanceable_info_view.h index d0d4593..31c0bf1 100644 --- a/ash/ambient/ui/glanceable_info_view.h +++ b/ash/ambient/ui/glanceable_info_view.h
@@ -47,11 +47,7 @@ // View for the time info. Owned by the view hierarchy. ash::tray::TimeView* time_view_ = nullptr; - // Container holding weather-related views. Owned by the view hierarchy. - views::View* weather_info_ = nullptr; - // Views for weather icon and temperature. - // Child views of |weather_info_| and owned by the view hierarchy. views::ImageView* weather_condition_icon_ = nullptr; views::Label* temperature_ = nullptr;
diff --git a/ash/app_list/views/search_result_suggestion_chip_view.cc b/ash/app_list/views/search_result_suggestion_chip_view.cc index 0337908..d0780d9 100644 --- a/ash/app_list/views/search_result_suggestion_chip_view.cc +++ b/ash/app_list/views/search_result_suggestion_chip_view.cc
@@ -4,6 +4,7 @@ #include "ash/app_list/views/search_result_suggestion_chip_view.h" +#include <algorithm> #include <utility> #include "ash/app_list/app_list_metrics.h"
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd index f14a3f7..a816c15 100644 --- a/ash/ash_strings.grd +++ b/ash/ash_strings.grd
@@ -330,7 +330,7 @@ <message name="IDS_ASH_STATUS_TRAY_CAST_CAST_DESKTOP" desc="The label used in the tray popup to tell the user we are casting the desktop."> Casting screen to <ph name="RECEIVER_NAME">$1<ex>Living Room</ex></ph> </message> - <message name="IDS_ASH_STATUS_TRAY_DARK_THEME" desc="The label used as the header in the dark theme popup. [CHAR_LIMIT=14]"> + <message name="IDS_ASH_STATUS_TRAY_DARK_THEME" desc="The label used as the header in the dark theme popup. [CHAR_LIMIT=17"> Dark theme </message> <message name="IDS_ASH_STATUS_TRAY_DARK_THEME_TOGGLE_TOOLTIP" desc="The tooltip text used for the button in the status tray to toggle the Dark theme feature on or off."> @@ -943,6 +943,15 @@ <message name="IDS_ASH_HOLDING_SPACE_SCREENSHOTS_TITLE" desc="Title of the screenshots area in the holding space bubble."> Screenshots </message> + <message name="IDS_ASH_HOLDING_SPACE_CONTEXT_MENU_COPY_TO_CLIPBOARD" desc="Title of the option to copy items to clipboard."> + Copy to clipboard + </message> + <message name="IDS_ASH_HOLDING_SPACE_CONTEXT_MENU_PIN" desc="Title of the pin option in the holding space item context menu."> + Pin + </message> + <message name="IDS_ASH_HOLDING_SPACE_CONTEXT_MENU_SHOW_IN_FOLDER" desc="Title of the option to show item in its folder in the holding space item context menu."> + Show in folder + </message> <!-- Phone Hub tray--> <message name="IDS_ASH_PHONE_HUB_TRAY_ACCESSIBLE_NAME" desc="The accessible name of the Phone Hub tray bubble for screen readers.">
diff --git a/ash/ash_strings_grd/IDS_ASH_HOLDING_SPACE_CONTEXT_MENU_COPY_TO_CLIPBOARD.png.sha1 b/ash/ash_strings_grd/IDS_ASH_HOLDING_SPACE_CONTEXT_MENU_COPY_TO_CLIPBOARD.png.sha1 new file mode 100644 index 0000000..8813b9e1 --- /dev/null +++ b/ash/ash_strings_grd/IDS_ASH_HOLDING_SPACE_CONTEXT_MENU_COPY_TO_CLIPBOARD.png.sha1
@@ -0,0 +1 @@ +b1012145df7abf2c183a8b9f8fc6f3fdf8efd6f8 \ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_HOLDING_SPACE_CONTEXT_MENU_PIN.png.sha1 b/ash/ash_strings_grd/IDS_ASH_HOLDING_SPACE_CONTEXT_MENU_PIN.png.sha1 new file mode 100644 index 0000000..8813b9e1 --- /dev/null +++ b/ash/ash_strings_grd/IDS_ASH_HOLDING_SPACE_CONTEXT_MENU_PIN.png.sha1
@@ -0,0 +1 @@ +b1012145df7abf2c183a8b9f8fc6f3fdf8efd6f8 \ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_HOLDING_SPACE_CONTEXT_MENU_SHOW_IN_FOLDER.png.sha1 b/ash/ash_strings_grd/IDS_ASH_HOLDING_SPACE_CONTEXT_MENU_SHOW_IN_FOLDER.png.sha1 new file mode 100644 index 0000000..8813b9e1 --- /dev/null +++ b/ash/ash_strings_grd/IDS_ASH_HOLDING_SPACE_CONTEXT_MENU_SHOW_IN_FOLDER.png.sha1
@@ -0,0 +1 @@ +b1012145df7abf2c183a8b9f8fc6f3fdf8efd6f8 \ No newline at end of file
diff --git a/ash/display/cros_display_config_unittest.cc b/ash/display/cros_display_config_unittest.cc index 45d185b..77a5ba4 100644 --- a/ash/display/cros_display_config_unittest.cc +++ b/ash/display/cros_display_config_unittest.cc
@@ -230,8 +230,7 @@ TestObserver observer; mojo::AssociatedRemote<mojom::CrosDisplayConfigObserver> observer_remote; mojo::AssociatedReceiver<mojom::CrosDisplayConfigObserver> receiver( - &observer, - observer_remote.BindNewEndpointAndPassDedicatedReceiverForTesting()); + &observer, observer_remote.BindNewEndpointAndPassDedicatedReceiver()); cros_display_config()->AddObserver(observer_remote.Unbind()); base::RunLoop().RunUntilIdle(); @@ -751,8 +750,7 @@ TestObserver observer; mojo::AssociatedRemote<mojom::CrosDisplayConfigObserver> observer_remote; mojo::AssociatedReceiver<mojom::CrosDisplayConfigObserver> receiver( - &observer, - observer_remote.BindNewEndpointAndPassDedicatedReceiverForTesting()); + &observer, observer_remote.BindNewEndpointAndPassDedicatedReceiver()); cros_display_config()->AddObserver(observer_remote.Unbind()); base::RunLoop().RunUntilIdle();
diff --git a/ash/public/cpp/holding_space/holding_space_constants.h b/ash/public/cpp/holding_space/holding_space_constants.h index ff2b1e2e..5bcb3873 100644 --- a/ash/public/cpp/holding_space/holding_space_constants.h +++ b/ash/public/cpp/holding_space/holding_space_constants.h
@@ -5,11 +5,20 @@ #ifndef ASH_PUBLIC_CPP_HOLDING_SPACE_HOLDING_SPACE_CONSTANTS_H_ #define ASH_PUBLIC_CPP_HOLDING_SPACE_HOLDING_SPACE_CONSTANTS_H_ +#include "ash/public/cpp/app_menu_constants.h" #include "ui/gfx/geometry/insets.h" #include "ui/gfx/geometry/size.h" namespace ash { +// Context menu commands. +enum HoldingSpaceCommandId { + kTogglePinItem, + kCopyToClipboard, + kShowInFolder, + kMaxValue = kShowInFolder +}; + // Appearance. constexpr gfx::Insets kHoldingSpaceContainerPadding(16); constexpr int kHoldingSpaceContainerSeparation = 8;
diff --git a/ash/public/cpp/shelf_config.h b/ash/public/cpp/shelf_config.h index 53deb1e..ca2779e 100644 --- a/ash/public/cpp/shelf_config.h +++ b/ash/public/cpp/shelf_config.h
@@ -179,14 +179,11 @@ bool in_tablet_mode() const { return in_tablet_mode_; } - // Ink drop color for shelf items. - SkColor GetInkDropBaseColor() const; - - // Opacity of the ink drop ripple for shelf items when the ripple is visible. - float GetInkDropVisibleOpacity() const; - bool in_overview_mode() const { return overview_mode_; } + // Ink drop RippleAttributes for shelf items. + AshColorProvider::RippleAttributes GetInkDropRippleAttributes() const; + // Gets the current color for the shelf control buttons. SkColor GetShelfControlButtonColor() const;
diff --git a/ash/scoped_animation_disabler.cc b/ash/scoped_animation_disabler.cc index b1197620..97706dc 100644 --- a/ash/scoped_animation_disabler.cc +++ b/ash/scoped_animation_disabler.cc
@@ -11,14 +11,17 @@ ScopedAnimationDisabler::ScopedAnimationDisabler(aura::Window* window) : window_(window) { + DCHECK(window_); needs_disable_ = !window_->GetProperty(aura::client::kAnimationsDisabledKey); if (needs_disable_) window_->SetProperty(aura::client::kAnimationsDisabledKey, true); } ScopedAnimationDisabler::~ScopedAnimationDisabler() { - if (needs_disable_) + if (needs_disable_) { + DCHECK_EQ(window_->GetProperty(aura::client::kAnimationsDisabledKey), true); window_->ClearProperty(aura::client::kAnimationsDisabledKey); + } } -} // namespace ash \ No newline at end of file +} // namespace ash
diff --git a/ash/scoped_animation_disabler.h b/ash/scoped_animation_disabler.h index 2c07ea3..f772251 100644 --- a/ash/scoped_animation_disabler.h +++ b/ash/scoped_animation_disabler.h
@@ -5,7 +5,7 @@ #ifndef ASH_SCOPED_ANIMATION_DISABLER_H_ #define ASH_SCOPED_ANIMATION_DISABLER_H_ -#include "base/macros.h" +#include "ash/ash_export.h" namespace aura { class Window; @@ -16,16 +16,16 @@ // Helper class to perform window state changes without animations. Used to hide // /show/minimize windows without having their animation interfere with the ones // this class is in charge of. -class ScopedAnimationDisabler { +class ASH_EXPORT ScopedAnimationDisabler { public: explicit ScopedAnimationDisabler(aura::Window* window); + ScopedAnimationDisabler(const ScopedAnimationDisabler&) = delete; + ScopedAnimationDisabler& operator=(const ScopedAnimationDisabler&) = delete; ~ScopedAnimationDisabler(); private: - aura::Window* window_; + aura::Window* const window_; bool needs_disable_ = false; - - DISALLOW_COPY_AND_ASSIGN(ScopedAnimationDisabler); }; } // namespace ash
diff --git a/ash/shelf/login_shelf_view.cc b/ash/shelf/login_shelf_view.cc index aa7e70b..d4f644b 100644 --- a/ash/shelf/login_shelf_view.cc +++ b/ash/shelf/login_shelf_view.cc
@@ -175,9 +175,10 @@ SetFocusPainter(nullptr); SetInkDropMode(InkDropMode::ON); set_has_ink_drop_action_on_click(true); - set_ink_drop_base_color(ShelfConfig::Get()->GetInkDropBaseColor()); - set_ink_drop_visible_opacity( - ShelfConfig::Get()->GetInkDropVisibleOpacity()); + AshColorProvider::RippleAttributes ripple_attributes = + ShelfConfig::Get()->GetInkDropRippleAttributes(); + set_ink_drop_base_color(ripple_attributes.base_color); + set_ink_drop_visible_opacity(ripple_attributes.inkdrop_opacity); // Layer rendering is required when the shelf background is visible, which // happens when the wallpaper is not blurred. @@ -291,9 +292,10 @@ SetFocusPainter(nullptr); SetInkDropMode(InkDropMode::ON); set_has_ink_drop_action_on_click(true); - set_ink_drop_base_color(ShelfConfig::Get()->GetInkDropBaseColor()); - set_ink_drop_visible_opacity( - ShelfConfig::Get()->GetInkDropVisibleOpacity()); + AshColorProvider::RippleAttributes ripple_attributes = + ShelfConfig::Get()->GetInkDropRippleAttributes(); + set_ink_drop_base_color(ripple_attributes.base_color); + set_ink_drop_visible_opacity(ripple_attributes.inkdrop_opacity); // Layer rendering is required when the shelf background is visible, which // happens when the wallpaper is not blurred.
diff --git a/ash/shelf/shelf_button.cc b/ash/shelf/shelf_button.cc index 0b47559..65c22cf 100644 --- a/ash/shelf/shelf_button.cc +++ b/ash/shelf/shelf_button.cc
@@ -21,8 +21,10 @@ shelf_button_delegate_(shelf_button_delegate) { DCHECK(shelf_button_delegate_); set_hide_ink_drop_when_showing_context_menu(false); - set_ink_drop_base_color(ShelfConfig::Get()->GetInkDropBaseColor()); - set_ink_drop_visible_opacity(ShelfConfig::Get()->GetInkDropVisibleOpacity()); + AshColorProvider::RippleAttributes ripple_attributes = + ShelfConfig::Get()->GetInkDropRippleAttributes(); + set_ink_drop_base_color(ripple_attributes.base_color); + set_ink_drop_visible_opacity(ripple_attributes.inkdrop_opacity); SetFocusBehavior(FocusBehavior::ALWAYS); SetInkDropMode(InkDropMode::ON_NO_GESTURE_HANDLER); SetFocusPainter(views::Painter::CreateSolidFocusPainter(
diff --git a/ash/shelf/shelf_config.cc b/ash/shelf/shelf_config.cc index b76428d..f46efb4 100644 --- a/ash/shelf/shelf_config.cc +++ b/ash/shelf/shelf_config.cc
@@ -444,13 +444,9 @@ return is_dense_ ? 48 : 56; } -SkColor ShelfConfig::GetInkDropBaseColor() const { - return AshColorProvider::Get()->GetInkDropBaseColor( - AshColorProvider::AshColorMode::kDark); -} - -float ShelfConfig::GetInkDropVisibleOpacity() const { - return AshColorProvider::Get()->GetInkDropVisibleOpacity(); +AshColorProvider::RippleAttributes ShelfConfig::GetInkDropRippleAttributes() + const { + return AshColorProvider::Get()->GetRippleAttributes(GetDefaultShelfColor()); } SkColor ShelfConfig::GetShelfControlButtonColor() const {
diff --git a/ash/style/ash_color_provider.cc b/ash/style/ash_color_provider.cc index 677d11a..f018db1 100644 --- a/ash/style/ash_color_provider.cc +++ b/ash/style/ash_color_provider.cc
@@ -272,17 +272,6 @@ return IsThemed() ? GetBackgroundThemedColor() : GetBackgroundDefaultColor(); } -SkColor AshColorProvider::GetInkDropBaseColor( - AshColorMode given_color_mode) const { - AshColorMode color_mode = - color_mode_ != AshColorMode::kDefault ? color_mode_ : given_color_mode; - return color_mode == AshColorMode::kLight ? SK_ColorBLACK : SK_ColorWHITE; -} - -float AshColorProvider::GetInkDropVisibleOpacity() const { - return 0.2f; -} - void AshColorProvider::DecoratePillButton(views::LabelButton* button, ButtonType type, const gfx::VectorIcon& icon) {
diff --git a/ash/style/ash_color_provider.h b/ash/style/ash_color_provider.h index d7b1274..3eafb48c 100644 --- a/ash/style/ash_color_provider.h +++ b/ash/style/ash_color_provider.h
@@ -205,12 +205,6 @@ // |is_themed_|). SkColor GetBackgroundColor() const; - // Ink drop color for shelf items. - SkColor GetInkDropBaseColor(AshColorMode given_color_mode) const; - - // Opacity of the ink drop ripple for shelf items when the ripple is visible. - float GetInkDropVisibleOpacity() const; - // Helpers to style buttons based on the desired |type| and theme. Depending // on the type may style text, icon and background colors for both enabled and // disabled states. May overwrite an prior styles on |button|.
diff --git a/ash/system/holding_space/holding_space_item_chip_view.cc b/ash/system/holding_space/holding_space_item_chip_view.cc index dc38334..e8784de6 100644 --- a/ash/system/holding_space/holding_space_item_chip_view.cc +++ b/ash/system/holding_space/holding_space_item_chip_view.cc
@@ -8,6 +8,7 @@ #include "ash/public/cpp/holding_space/holding_space_item.h" #include "ash/public/cpp/shelf_config.h" #include "ash/style/ash_color_provider.h" +#include "ash/system/holding_space/holding_space_item_view.h" #include "ash/system/tray/tray_constants.h" #include "ash/system/tray/tray_popup_item_style.h" #include "ash/system/tray/tray_popup_utils.h" @@ -15,8 +16,6 @@ #include "ash/system/user/rounded_image_view.h" #include "ui/base/dragdrop/drag_drop_types.h" #include "ui/gfx/paint_vector_icon.h" -#include "ui/gfx/text_constants.h" -#include "ui/views/accessibility/view_accessibility.h" #include "ui/views/animation/flood_fill_ink_drop_ripple.h" #include "ui/views/animation/ink_drop_impl.h" #include "ui/views/background.h" @@ -30,7 +29,7 @@ namespace ash { HoldingSpaceItemChipView::HoldingSpaceItemChipView(const HoldingSpaceItem* item) - : item_(item) { + : HoldingSpaceItemView(item) { auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::Orientation::kHorizontal, gfx::Insets(kHoldingSpaceChipPadding), kHoldingSpaceChipChildSpacing)); @@ -38,7 +37,7 @@ image_ = AddChildView(std::make_unique<tray::RoundedImageView>(kTrayItemSize / 2)); - label_ = AddChildView(std::make_unique<views::Label>(item_->text())); + label_ = AddChildView(std::make_unique<views::Label>(item->text())); label_->SetElideBehavior(gfx::ELIDE_MIDDLE); layout->SetFlexForView(label_, 1); @@ -47,18 +46,14 @@ AddPinButton(); - SetPaintToLayer(); - layer()->SetFillsBoundsOpaquely(false); - SetBackground(views::CreateRoundedRectBackground( AshColorProvider::Get()->GetControlsLayerColor( AshColorProvider::ControlsLayerType::kControlBackgroundColorInactive), kHoldingSpaceChipCornerRadius)); - GetViewAccessibility().OverrideName(item_->text()); - SetFocusBehavior(FocusBehavior::ALWAYS); SetInkDropMode(InkDropMode::ON_NO_GESTURE_HANDLER); - set_ink_drop_visible_opacity(ShelfConfig::Get()->GetInkDropVisibleOpacity()); + set_ink_drop_visible_opacity( + ShelfConfig::Get()->GetInkDropRippleAttributes().inkdrop_opacity); SetNotifyEnterExitOnChild(true); // Ink drop layers should be clipped to match the corner radius of this view. @@ -67,7 +62,7 @@ // Subscribe to be notified of changes to `item_`'s image. image_subscription_ = - item_->image().AddImageSkiaChangedCallback(base::BindRepeating( + item->image().AddImageSkiaChangedCallback(base::BindRepeating( &HoldingSpaceItemChipView::Update, base::Unretained(this))); Update(); @@ -75,19 +70,6 @@ HoldingSpaceItemChipView::~HoldingSpaceItemChipView() = default; -SkColor HoldingSpaceItemChipView::GetInkDropBaseColor() const { - return ShelfConfig::Get()->GetInkDropBaseColor(); -} - -int HoldingSpaceItemChipView::GetDragOperations(const gfx::Point& point) { - return ui::DragDropTypes::DRAG_COPY; -} - -void HoldingSpaceItemChipView::WriteDragData(const gfx::Point& point, - ui::OSExchangeData* data) { - data->SetFilename(item_->file_path()); -} - void HoldingSpaceItemChipView::OnMouseEvent(ui::MouseEvent* event) { switch (event->type()) { case ui::ET_MOUSE_ENTERED: @@ -128,11 +110,11 @@ void HoldingSpaceItemChipView::Update() { image_->SetImage( - item_->image().image_skia(), + item()->image().image_skia(), gfx::Size(kHoldingSpaceChipIconSize, kHoldingSpaceChipIconSize)); } -BEGIN_METADATA(HoldingSpaceItemChipView, views::InkDropHostView) +BEGIN_METADATA(HoldingSpaceItemChipView, HoldingSpaceItemView) END_METADATA } // namespace ash
diff --git a/ash/system/holding_space/holding_space_item_chip_view.h b/ash/system/holding_space/holding_space_item_chip_view.h index 925b73ad..a0b1a54d 100644 --- a/ash/system/holding_space/holding_space_item_chip_view.h +++ b/ash/system/holding_space/holding_space_item_chip_view.h
@@ -9,7 +9,7 @@ #include "ash/ash_export.h" #include "ash/public/cpp/holding_space/holding_space_image.h" -#include "ui/views/animation/ink_drop_host_view.h" +#include "ash/system/holding_space/holding_space_item_view.h" #include "ui/views/controls/button/button.h" #include "ui/views/metadata/metadata_header_macros.h" @@ -28,7 +28,7 @@ // A button with an image derived from a file's thumbnail and file's name as the // label. -class ASH_EXPORT HoldingSpaceItemChipView : public views::InkDropHostView, +class ASH_EXPORT HoldingSpaceItemChipView : public HoldingSpaceItemView, public views::ButtonListener { public: METADATA_HEADER(HoldingSpaceItemChipView); @@ -38,10 +38,7 @@ HoldingSpaceItemChipView& operator=(const HoldingSpaceItemChipView&) = delete; ~HoldingSpaceItemChipView() override; - // views::InkDropHostView: - SkColor GetInkDropBaseColor() const override; - int GetDragOperations(const gfx::Point& point) override; - void WriteDragData(const gfx::Point& point, ui::OSExchangeData*) override; + // HoldingSpaceItemView: void OnMouseEvent(ui::MouseEvent* event) override; // views::ButtonListener: @@ -51,7 +48,6 @@ void AddPinButton(); void Update(); - const HoldingSpaceItem* const item_; tray::RoundedImageView* image_ = nullptr; views::Label* label_ = nullptr; views::ToggleImageButton* pin_ = nullptr;
diff --git a/ash/system/holding_space/holding_space_item_context_menu.cc b/ash/system/holding_space/holding_space_item_context_menu.cc new file mode 100644 index 0000000..0e4cecf6 --- /dev/null +++ b/ash/system/holding_space/holding_space_item_context_menu.cc
@@ -0,0 +1,69 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/system/holding_space/holding_space_item_context_menu.h" + +#include "ash/public/cpp/holding_space/holding_space_constants.h" +#include "ash/strings/grit/ash_strings.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/models/simple_menu_model.h" +#include "ui/views/controls/menu/menu_runner.h" +#include "ui/views/view.h" + +namespace ash { + +HoldingSpaceItemContextMenu::HoldingSpaceItemContextMenu() = default; + +HoldingSpaceItemContextMenu::~HoldingSpaceItemContextMenu() = default; + +ui::SimpleMenuModel* HoldingSpaceItemContextMenu::BuildMenuModel() { + context_menu_model_ = std::make_unique<ui::SimpleMenuModel>(this); + context_menu_model_->AddItem( + HoldingSpaceCommandId::kShowInFolder, + l10n_util::GetStringUTF16( + IDS_ASH_HOLDING_SPACE_CONTEXT_MENU_SHOW_IN_FOLDER)); + context_menu_model_->AddItem( + HoldingSpaceCommandId::kCopyToClipboard, + l10n_util::GetStringUTF16( + IDS_ASH_HOLDING_SPACE_CONTEXT_MENU_COPY_TO_CLIPBOARD)); + context_menu_model_->AddItem( + HoldingSpaceCommandId::kTogglePinItem, + l10n_util::GetStringUTF16(IDS_ASH_HOLDING_SPACE_CONTEXT_MENU_PIN)); + + return context_menu_model_.get(); +} + +void HoldingSpaceItemContextMenu::ShowContextMenuForViewImpl( + views::View* source, + const gfx::Point& point, + ui::MenuSourceType source_type) { + int run_types = views::MenuRunner::USE_TOUCHABLE_LAYOUT | + views::MenuRunner::CONTEXT_MENU | + views::MenuRunner::FIXED_ANCHOR; + + context_menu_runner_ = + std::make_unique<views::MenuRunner>(BuildMenuModel(), run_types); + + context_menu_runner_->RunMenuAt( + source->GetWidget(), nullptr /*button_controller*/, + source->GetBoundsInScreen(), views::MenuAnchorPosition::kBubbleRight, + source_type); +} + +void HoldingSpaceItemContextMenu::ExecuteCommand(int command_id, + int event_flags) { + switch (command_id) { + case HoldingSpaceCommandId::kCopyToClipboard: + // TODO(crbug.com/1127240): Hookup API for copy to clipboard + break; + case HoldingSpaceCommandId::kShowInFolder: + // TODO(crbug.com/1127240): Hookup API for show in folder + break; + case HoldingSpaceCommandId::kTogglePinItem: + // TODO(crbug.com/1127240): Hookup API for toggling pin + break; + } +} + +} // namespace ash
diff --git a/ash/system/holding_space/holding_space_item_context_menu.h b/ash/system/holding_space/holding_space_item_context_menu.h new file mode 100644 index 0000000..770430e1 --- /dev/null +++ b/ash/system/holding_space/holding_space_item_context_menu.h
@@ -0,0 +1,49 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_ITEM_CONTEXT_MENU_H_ +#define ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_ITEM_CONTEXT_MENU_H_ + +#include <memory> + +#include "ash/ash_export.h" +#include "ui/base/models/simple_menu_model.h" +#include "ui/views/context_menu_controller.h" + +namespace views { +class MenuRunner; +} // namespace views + +namespace ash { + +// This class handles creation of the context menu view and handling +// commands available in the menu. +class ASH_EXPORT HoldingSpaceItemContextMenu + : public views::ContextMenuController, + public ui::SimpleMenuModel::Delegate { + public: + HoldingSpaceItemContextMenu(); + HoldingSpaceItemContextMenu(const HoldingSpaceItemContextMenu&) = delete; + HoldingSpaceItemContextMenu& operator=(const HoldingSpaceItemContextMenu&) = + delete; + ~HoldingSpaceItemContextMenu() override; + + // views::ContextMenuController: + void ShowContextMenuForViewImpl(views::View* source, + const gfx::Point& point, + ui::MenuSourceType source_type) override; + + // SimpleMenuModel::Delegate: + void ExecuteCommand(int command_id, int event_flags) override; + + private: + ui::SimpleMenuModel* BuildMenuModel(); + + std::unique_ptr<ui::SimpleMenuModel> context_menu_model_; + std::unique_ptr<views::MenuRunner> context_menu_runner_; +}; + +} // namespace ash + +#endif // ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_ITEM_CONTEXT_MENU_H_
diff --git a/ash/system/holding_space/holding_space_item_screenshot_view.cc b/ash/system/holding_space/holding_space_item_screenshot_view.cc new file mode 100644 index 0000000..50d7a42 --- /dev/null +++ b/ash/system/holding_space/holding_space_item_screenshot_view.cc
@@ -0,0 +1,43 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/system/holding_space/holding_space_item_screenshot_view.h" + +#include "ash/public/cpp/holding_space/holding_space_constants.h" +#include "ash/public/cpp/holding_space/holding_space_image.h" +#include "ash/public/cpp/holding_space/holding_space_item.h" +#include "ash/system/tray/tray_constants.h" +#include "ash/system/user/rounded_image_view.h" +#include "ui/views/accessibility/view_accessibility.h" +#include "ui/views/layout/fill_layout.h" +#include "ui/views/metadata/metadata_impl_macros.h" + +namespace ash { + +HoldingSpaceItemScreenshotView::HoldingSpaceItemScreenshotView( + const HoldingSpaceItem* item) + : HoldingSpaceItemView(item) { + SetLayoutManager(std::make_unique<views::FillLayout>()); + + image_ = + AddChildView(std::make_unique<tray::RoundedImageView>(kTrayItemSize / 2)); + + // Subscribe to be notified of changes to `item_`'s image. + image_subscription_ = + item->image().AddImageSkiaChangedCallback(base::BindRepeating( + &HoldingSpaceItemScreenshotView::Update, base::Unretained(this))); + + Update(); +} + +HoldingSpaceItemScreenshotView::~HoldingSpaceItemScreenshotView() = default; + +void HoldingSpaceItemScreenshotView::Update() { + image_->SetImage(item()->image().image_skia(), kHoldingSpaceScreenshotSize); +} + +BEGIN_METADATA(HoldingSpaceItemScreenshotView, HoldingSpaceItemView) +END_METADATA + +} // namespace ash
diff --git a/ash/system/holding_space/holding_space_item_screenshot_view.h b/ash/system/holding_space/holding_space_item_screenshot_view.h new file mode 100644 index 0000000..14035bf --- /dev/null +++ b/ash/system/holding_space/holding_space_item_screenshot_view.h
@@ -0,0 +1,42 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_ITEM_SCREENSHOT_VIEW_H_ +#define ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_ITEM_SCREENSHOT_VIEW_H_ + +#include "ash/ash_export.h" +#include "ash/public/cpp/holding_space/holding_space_image.h" +#include "ash/system/holding_space/holding_space_item_view.h" +#include "ui/views/metadata/metadata_header_macros.h" + +namespace ash { + +class HoldingSpaceItem; + +namespace tray { +class RoundedImageView; +} // namespace tray + +class ASH_EXPORT HoldingSpaceItemScreenshotView : public HoldingSpaceItemView { + public: + METADATA_HEADER(HoldingSpaceItemScreenshotView); + + explicit HoldingSpaceItemScreenshotView(const HoldingSpaceItem* item); + HoldingSpaceItemScreenshotView(const HoldingSpaceItemScreenshotView&) = + delete; + HoldingSpaceItemScreenshotView& operator=( + const HoldingSpaceItemScreenshotView&) = delete; + ~HoldingSpaceItemScreenshotView() override; + + private: + void Update(); + + tray::RoundedImageView* image_ = nullptr; + + std::unique_ptr<HoldingSpaceImage::Subscription> image_subscription_; +}; + +} // namespace ash + +#endif // ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_ITEM_SCREENSHOT_VIEW_H_
diff --git a/ash/system/holding_space/holding_space_item_view.cc b/ash/system/holding_space/holding_space_item_view.cc new file mode 100644 index 0000000..c222172e --- /dev/null +++ b/ash/system/holding_space/holding_space_item_view.cc
@@ -0,0 +1,47 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/system/holding_space/holding_space_item_view.h" + +#include "ash/public/cpp/holding_space/holding_space_constants.h" +#include "ash/public/cpp/holding_space/holding_space_item.h" +#include "ash/public/cpp/shelf_config.h" +#include "ash/strings/grit/ash_strings.h" +#include "ash/system/holding_space/holding_space_item_context_menu.h" +#include "ui/base/dragdrop/drag_drop_types.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/gfx/text_constants.h" +#include "ui/views/accessibility/view_accessibility.h" +#include "ui/views/controls/menu/menu_runner.h" + +namespace ash { + +HoldingSpaceItemView::HoldingSpaceItemView(const HoldingSpaceItem* item) + : item_(item), + context_menu_(std::make_unique<HoldingSpaceItemContextMenu>()) { + set_context_menu_controller(context_menu_.get()); + + SetPaintToLayer(); + layer()->SetFillsBoundsOpaquely(false); + + GetViewAccessibility().OverrideName(item->text()); + SetFocusBehavior(FocusBehavior::ALWAYS); +} + +HoldingSpaceItemView::~HoldingSpaceItemView() = default; + +int HoldingSpaceItemView::GetDragOperations(const gfx::Point& point) { + return ui::DragDropTypes::DRAG_COPY; +} + +SkColor HoldingSpaceItemView::GetInkDropBaseColor() const { + return ShelfConfig::Get()->GetInkDropRippleAttributes().base_color; +} + +void HoldingSpaceItemView::WriteDragData(const gfx::Point& point, + ui::OSExchangeData* data) { + data->SetFilename(item_->file_path()); +} + +} // namespace ash
diff --git a/ash/system/holding_space/holding_space_item_view.h b/ash/system/holding_space/holding_space_item_view.h new file mode 100644 index 0000000..b03b15f --- /dev/null +++ b/ash/system/holding_space/holding_space_item_view.h
@@ -0,0 +1,41 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_ITEM_VIEW_H_ +#define ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_ITEM_VIEW_H_ + +#include <memory> + +#include "ash/ash_export.h" +#include "ui/base/dragdrop/drag_drop_types.h" +#include "ui/views/animation/ink_drop_host_view.h" + +namespace ash { + +class HoldingSpaceItem; +class HoldingSpaceItemContextMenu; + +// Base class for HoldingSpaceItemChipView and HoldingSpaceItemScreenshotView. +class ASH_EXPORT HoldingSpaceItemView : public views::InkDropHostView { + public: + explicit HoldingSpaceItemView(const HoldingSpaceItem* item); + HoldingSpaceItemView(const HoldingSpaceItemView&) = delete; + HoldingSpaceItemView& operator=(const HoldingSpaceItemView&) = delete; + ~HoldingSpaceItemView() override; + + // views::InkDropHostView: + int GetDragOperations(const gfx::Point& point) override; + SkColor GetInkDropBaseColor() const override; + void WriteDragData(const gfx::Point& point, ui::OSExchangeData*) override; + + const HoldingSpaceItem* item() const { return item_; } + + private: + const HoldingSpaceItem* const item_; + std::unique_ptr<HoldingSpaceItemContextMenu> const context_menu_; +}; + +} // namespace ash + +#endif // ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_ITEM_VIEW_H_
diff --git a/ash/system/holding_space/holding_space_screenshot_view.cc b/ash/system/holding_space/holding_space_screenshot_view.cc deleted file mode 100644 index e2bce1a..0000000 --- a/ash/system/holding_space/holding_space_screenshot_view.cc +++ /dev/null
@@ -1,58 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/system/holding_space/holding_space_screenshot_view.h" - -#include "ash/public/cpp/holding_space/holding_space_constants.h" -#include "ash/public/cpp/holding_space/holding_space_item.h" -#include "ash/system/tray/tray_constants.h" -#include "ash/system/user/rounded_image_view.h" -#include "ui/base/dragdrop/drag_drop_types.h" -#include "ui/views/accessibility/view_accessibility.h" -#include "ui/views/layout/fill_layout.h" -#include "ui/views/metadata/metadata_impl_macros.h" - -namespace ash { - -HoldingSpaceScreenshotView::HoldingSpaceScreenshotView( - const HoldingSpaceItem* item) - : item_(item) { - SetLayoutManager(std::make_unique<views::FillLayout>()); - - SetPaintToLayer(); - layer()->SetFillsBoundsOpaquely(false); - - GetViewAccessibility().OverrideName(item_->text()); - SetFocusBehavior(FocusBehavior::ALWAYS); - - image_ = - AddChildView(std::make_unique<tray::RoundedImageView>(kTrayItemSize / 2)); - - // Subscribe to be notified of changes to `item_`'s image. - image_subscription_ = - item_->image().AddImageSkiaChangedCallback(base::BindRepeating( - &HoldingSpaceScreenshotView::Update, base::Unretained(this))); - - Update(); -} - -HoldingSpaceScreenshotView::~HoldingSpaceScreenshotView() = default; - -int HoldingSpaceScreenshotView::GetDragOperations(const gfx::Point& point) { - return ui::DragDropTypes::DRAG_COPY; -} - -void HoldingSpaceScreenshotView::WriteDragData(const gfx::Point& point, - ui::OSExchangeData* data) { - data->SetFilename(item_->file_path()); -} - -void HoldingSpaceScreenshotView::Update() { - image_->SetImage(item_->image().image_skia(), kHoldingSpaceScreenshotSize); -} - -BEGIN_METADATA(HoldingSpaceScreenshotView, views::View) -END_METADATA - -} // namespace ash
diff --git a/ash/system/holding_space/holding_space_screenshot_view.h b/ash/system/holding_space/holding_space_screenshot_view.h deleted file mode 100644 index 0100a23..0000000 --- a/ash/system/holding_space/holding_space_screenshot_view.h +++ /dev/null
@@ -1,48 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_SCREENSHOT_VIEW_H_ -#define ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_SCREENSHOT_VIEW_H_ - -#include <memory> - -#include "ash/ash_export.h" -#include "ash/public/cpp/holding_space/holding_space_image.h" -#include "ui/views/metadata/metadata_header_macros.h" -#include "ui/views/view.h" - -namespace ash { - -class HoldingSpaceItem; - -namespace tray { -class RoundedImageView; -} // namespace tray - -class ASH_EXPORT HoldingSpaceScreenshotView : public views::View { - public: - METADATA_HEADER(HoldingSpaceScreenshotView); - - explicit HoldingSpaceScreenshotView(const HoldingSpaceItem* item); - HoldingSpaceScreenshotView(const HoldingSpaceScreenshotView&) = delete; - HoldingSpaceScreenshotView& operator=(const HoldingSpaceScreenshotView&) = - delete; - ~HoldingSpaceScreenshotView() override; - - // views::View: - int GetDragOperations(const gfx::Point& point) override; - void WriteDragData(const gfx::Point& point, ui::OSExchangeData*) override; - - private: - void Update(); - - const HoldingSpaceItem* const item_; - tray::RoundedImageView* image_ = nullptr; - - std::unique_ptr<HoldingSpaceImage::Subscription> image_subscription_; -}; - -} // namespace ash - -#endif // ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_SCREENSHOT_VIEW_H_
diff --git a/ash/system/holding_space/holding_space_test_api.cc b/ash/system/holding_space/holding_space_test_api.cc index f9f6f01..f203695 100644 --- a/ash/system/holding_space/holding_space_test_api.cc +++ b/ash/system/holding_space/holding_space_test_api.cc
@@ -11,7 +11,7 @@ #include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/system/holding_space/holding_space_item_chip_view.h" -#include "ash/system/holding_space/holding_space_screenshot_view.h" +#include "ash/system/holding_space/holding_space_item_screenshot_view.h" #include "ash/system/holding_space/holding_space_tray.h" #include "ash/system/status_area_widget.h" #include "ui/aura/window.h" @@ -114,7 +114,7 @@ std::vector<views::View*> HoldingSpaceTestApi::GetScreenshotViews() { std::vector<views::View*> screenshot_views; if (holding_space_tray_->GetBubbleView()) { - FindDescendentsOfClass<HoldingSpaceScreenshotView>( + FindDescendentsOfClass<HoldingSpaceItemScreenshotView>( holding_space_tray_->GetBubbleView()->GetViewByID( kHoldingSpaceRecentFilesContainerId), &screenshot_views);
diff --git a/ash/system/holding_space/recent_files_container.cc b/ash/system/holding_space/recent_files_container.cc index df22996..6950725 100644 --- a/ash/system/holding_space/recent_files_container.cc +++ b/ash/system/holding_space/recent_files_container.cc
@@ -10,7 +10,7 @@ #include "ash/public/cpp/holding_space/holding_space_model.h" #include "ash/strings/grit/ash_strings.h" #include "ash/system/holding_space/holding_space_item_chips_container.h" -#include "ash/system/holding_space/holding_space_screenshot_view.h" +#include "ash/system/holding_space/holding_space_item_screenshot_view.h" #include "ash/system/tray/tray_constants.h" #include "ash/system/tray/tray_popup_item_style.h" #include "ui/base/l10n/l10n_util.h" @@ -48,7 +48,7 @@ for (const auto& item : HoldingSpaceController::Get()->model()->items()) { if (item->type() == HoldingSpaceItem::Type::kScreenshot) { screenshots_container_->AddChildView( - std::make_unique<HoldingSpaceScreenshotView>(item.get())); + std::make_unique<HoldingSpaceItemScreenshotView>(item.get())); } }
diff --git a/ash/system/tray/tray_background_view.cc b/ash/system/tray/tray_background_view.cc index 149d4f66..52edc6ec 100644 --- a/ash/system/tray/tray_background_view.cc +++ b/ash/system/tray/tray_background_view.cc
@@ -160,8 +160,11 @@ widget_observer_(new TrayWidgetObserver(this)) { DCHECK(shelf_); SetNotifyEnterExitOnChild(true); - set_ink_drop_base_color(ShelfConfig::Get()->GetInkDropBaseColor()); - set_ink_drop_visible_opacity(ShelfConfig::Get()->GetInkDropVisibleOpacity()); + AshColorProvider::RippleAttributes ripple_attributes = + ShelfConfig::Get()->GetInkDropRippleAttributes(); + + set_ink_drop_base_color(ripple_attributes.base_color); + set_ink_drop_visible_opacity(ripple_attributes.inkdrop_opacity); SetInkDropMode(InkDropMode::ON_NO_GESTURE_HANDLER); SetLayoutManager(std::make_unique<views::FillLayout>());
diff --git a/ash/wm/desks/desks_controller.cc b/ash/wm/desks/desks_controller.cc index f37a8c90..49cfd3f 100644 --- a/ash/wm/desks/desks_controller.cc +++ b/ash/wm/desks/desks_controller.cc
@@ -27,6 +27,7 @@ #include "ash/wm/overview/overview_item.h" #include "ash/wm/splitview/split_view_controller.h" #include "ash/wm/splitview/split_view_utils.h" +#include "ash/wm/window_cycle_controller.h" #include "ash/wm/window_util.h" #include "base/auto_reset.h" #include "base/check_op.h" @@ -545,6 +546,13 @@ MaybeUpdateShelfItems(old_active->windows(), active_desk_->windows()); + // If in the middle of a window cycle gesture, reset the window cycle list + // contents so it contains the new active desk's windows. + if (features::IsAltTabLimitedToActiveDesk()) { + auto* window_cycle_controller = Shell::Get()->window_cycle_controller(); + window_cycle_controller->MaybeResetCycleList(); + } + for (auto& observer : observers_) observer.OnDeskActivationChanged(active_desk_, old_active); }
diff --git a/ash/wm/window_cycle_controller.cc b/ash/wm/window_cycle_controller.cc index 3f99cbc0..dbb7b02 100644 --- a/ash/wm/window_cycle_controller.cc +++ b/ash/wm/window_cycle_controller.cc
@@ -30,7 +30,8 @@ // Returns the most recently active window from the |window_list| or nullptr // if the list is empty. -aura::Window* GetActiveWindow(const WindowCycleList::WindowList& window_list) { +aura::Window* GetActiveWindow( + const WindowCycleController::WindowList& window_list) { return window_list.empty() ? nullptr : window_list[0]; } @@ -95,18 +96,8 @@ // (http://crbug.com/895265). Shell::Get()->wallpaper_controller()->MaybeClosePreviewWallpaper(); - WindowCycleList::WindowList window_list = - Shell::Get()->mru_window_tracker()->BuildWindowForCycleWithPipList( - features::IsAltTabLimitedToActiveDesk() ? kActiveDesk : kAllDesks); - // Window cycle list windows will handle showing their transient related - // windows, so if a window in |window_list| has a transient root also in - // |window_list|, we can remove it as the transient root will handle showing - // the window. - window_util::RemoveTransientDescendants(&window_list); - - active_desk_container_id_before_cycle_ = - desks_util::GetActiveDeskContainerId(); - active_window_before_window_cycle_ = GetActiveWindow(window_list); + WindowCycleController::WindowList window_list = CreateWindowList(); + SaveCurrentActiveDeskAndWindow(window_list); window_cycle_list_ = std::make_unique<WindowCycleList>(window_list); event_filter_ = std::make_unique<WindowCycleEventFilter>(); @@ -124,6 +115,17 @@ StopCycling(); } +void WindowCycleController::MaybeResetCycleList() { + if (!IsCycling()) + return; + + WindowCycleController::WindowList window_list = CreateWindowList(); + SaveCurrentActiveDeskAndWindow(window_list); + + DCHECK(window_cycle_list_); + window_cycle_list_->ReplaceWindows(window_list); +} + void WindowCycleController::StepToWindow(aura::Window* window) { DCHECK(window_cycle_list_); window_cycle_list_->StepToWindow(window); @@ -136,6 +138,25 @@ ////////////////////////////////////////////////////////////////////////////// // WindowCycleController, private: +WindowCycleController::WindowList WindowCycleController::CreateWindowList() { + WindowCycleController::WindowList window_list = + Shell::Get()->mru_window_tracker()->BuildWindowForCycleWithPipList( + features::IsAltTabLimitedToActiveDesk() ? kActiveDesk : kAllDesks); + // Window cycle list windows will handle showing their transient related + // windows, so if a window in |window_list| has a transient root also in + // |window_list|, we can remove it as the transient root will handle showing + // the window. + window_util::RemoveTransientDescendants(&window_list); + return window_list; +} + +void WindowCycleController::SaveCurrentActiveDeskAndWindow( + const WindowCycleController::WindowList& window_list) { + active_desk_container_id_before_cycle_ = + desks_util::GetActiveDeskContainerId(); + active_window_before_window_cycle_ = GetActiveWindow(window_list); +} + void WindowCycleController::Step(Direction direction) { DCHECK(window_cycle_list_); window_cycle_list_->Step(direction);
diff --git a/ash/wm/window_cycle_controller.h b/ash/wm/window_cycle_controller.h index 7512a36..bdaca12 100644 --- a/ash/wm/window_cycle_controller.h +++ b/ash/wm/window_cycle_controller.h
@@ -34,6 +34,8 @@ // order. class ASH_EXPORT WindowCycleController { public: + using WindowList = std::vector<aura::Window*>; + enum Direction { FORWARD, BACKWARD }; WindowCycleController(); @@ -60,6 +62,10 @@ void CompleteCycling(); void CancelCycling(); + // If the window cycle list is open, re-construct it. Do nothing if not + // cycling. + void MaybeResetCycleList(); + // Skip window cycle list directly to |window|. void StepToWindow(aura::Window* window); @@ -72,6 +78,16 @@ } private: + // Gets a list of windows from the currently open windows, removing windows + // with transient roots already in the list. The returned list of windows + // is used to populate the window cycle list. + WindowList CreateWindowList(); + + // Populates |active_desk_container_id_before_cycle_| and + // |active_window_before_window_cycle_| when the window cycle list is + // initialized. + void SaveCurrentActiveDeskAndWindow(const WindowList& window_list); + // Cycles to the next or previous window based on |direction|. void Step(Direction direction);
diff --git a/ash/wm/window_cycle_controller_unittest.cc b/ash/wm/window_cycle_controller_unittest.cc index 0a00ac73..f90e416 100644 --- a/ash/wm/window_cycle_controller_unittest.cc +++ b/ash/wm/window_cycle_controller_unittest.cc
@@ -850,6 +850,20 @@ EXPECT_TRUE(base::Contains(cycle_windows, win1.get())); cycle_controller->CompleteCycling(); EXPECT_EQ(win0.get(), window_util::GetActiveWindow()); + + // Swap desks while cycling, contents should update. + cycle_controller->HandleCycleWindow(WindowCycleController::FORWARD); + cycle_windows = GetWindows(cycle_controller); + EXPECT_EQ(2u, cycle_windows.size()); + EXPECT_TRUE(base::Contains(cycle_windows, win0.get())); + EXPECT_TRUE(base::Contains(cycle_windows, win1.get())); + ActivateDesk(desk_2); + EXPECT_TRUE(cycle_controller->IsCycling()); + cycle_windows = GetWindows(cycle_controller); + EXPECT_EQ(1u, cycle_windows.size()); + EXPECT_TRUE(base::Contains(cycle_windows, win2.get())); + cycle_controller->CompleteCycling(); + EXPECT_EQ(win2.get(), window_util::GetActiveWindow()); } class InteractiveWindowCycleControllerTest : public WindowCycleControllerTest {
diff --git a/ash/wm/window_cycle_list.cc b/ash/wm/window_cycle_list.cc index 222eee14..dc6c6fb 100644 --- a/ash/wm/window_cycle_list.cc +++ b/ash/wm/window_cycle_list.cc
@@ -296,6 +296,24 @@ WindowCycleView& operator=(const WindowCycleView&) = delete; ~WindowCycleView() override = default; + void UpdateWindows(const WindowCycleList::WindowList& windows) { + for (auto* window : windows) { + auto* view = mirror_container_->AddChildView( + std::make_unique<WindowCycleItemView>(window)); + window_view_map_[window] = view; + + no_previews_set_.insert(view); + } + + // Resize the widget. + aura::Window* root_window = Shell::GetRootWindowForNewWindows(); + gfx::Rect widget_rect = root_window->GetBoundsInScreen(); + widget_rect.ClampToCenteredSize(GetPreferredSize()); + GetWidget()->SetBounds(widget_rect); + + SetTargetWindow(windows[0]); + } + void FadeInLayer() { DCHECK(GetWidget()); @@ -514,6 +532,25 @@ Shell::Get()->frame_throttling_controller()->EndThrottling(); } +void WindowCycleList::ReplaceWindows(const WindowList& windows) { + if (windows.empty()) { + Shell::Get()->window_cycle_controller()->CancelCycling(); + return; + } + + for (auto* existing_window : windows_) + RemoveWindow(existing_window); + + current_index_ = 0; + windows_ = windows; + + for (auto* new_window : windows_) + new_window->AddObserver(this); + + if (ShouldShowUi() && cycle_view_) + cycle_view_->UpdateWindows(windows_); +} + void WindowCycleList::Step(int offset) { if (windows_.empty()) return; @@ -580,6 +617,29 @@ } void WindowCycleList::OnWindowDestroying(aura::Window* window) { + RemoveWindow(window); + + if (cycle_view_ && windows_.empty()) { + // This deletes us. + Shell::Get()->window_cycle_controller()->CancelCycling(); + } +} + +void WindowCycleList::OnDisplayMetricsChanged(const display::Display& display, + uint32_t changed_metrics) { + if (cycle_ui_widget_ && + display.id() == + display::Screen::GetScreen() + ->GetDisplayNearestWindow(cycle_ui_widget_->GetNativeWindow()) + .id() && + (changed_metrics & (DISPLAY_METRIC_BOUNDS | DISPLAY_METRIC_ROTATION))) { + Shell::Get()->window_cycle_controller()->CancelCycling(); + // |this| is deleted. + return; + } +} + +void WindowCycleList::RemoveWindow(aura::Window* window) { window->RemoveObserver(this); WindowList::iterator i = std::find(windows_.begin(), windows_.end(), window); @@ -596,25 +656,6 @@ auto* new_target_window = windows_.empty() ? nullptr : windows_[current_index_]; cycle_view_->HandleWindowDestruction(window, new_target_window); - if (windows_.empty()) { - // This deletes us. - Shell::Get()->window_cycle_controller()->CancelCycling(); - return; - } - } -} - -void WindowCycleList::OnDisplayMetricsChanged(const display::Display& display, - uint32_t changed_metrics) { - if (cycle_ui_widget_ && - display.id() == - display::Screen::GetScreen() - ->GetDisplayNearestWindow(cycle_ui_widget_->GetNativeWindow()) - .id() && - (changed_metrics & (DISPLAY_METRIC_BOUNDS | DISPLAY_METRIC_ROTATION))) { - Shell::Get()->window_cycle_controller()->CancelCycling(); - // |this| is deleted. - return; } }
diff --git a/ash/wm/window_cycle_list.h b/ash/wm/window_cycle_list.h index 16b899b..f281af8 100644 --- a/ash/wm/window_cycle_list.h +++ b/ash/wm/window_cycle_list.h
@@ -42,6 +42,10 @@ WindowCycleList& operator=(const WindowCycleList&) = delete; ~WindowCycleList() override; + // Removes the existing windows and replaces them with |windows|. If + // |windows| is empty, cancels cycling. + void ReplaceWindows(const WindowList& windows); + // Cycles to the next or previous window based on |direction|. void Step(WindowCycleController::Direction direction); @@ -75,6 +79,10 @@ void OnDisplayMetricsChanged(const display::Display& display, uint32_t changed_metrics) override; + // Removes |window| from the window list. Also removes the window from + // |cycle_view_| if |cycle_view_| exists. + void RemoveWindow(aura::Window* window); + // Returns true if the window list overlay should be shown. bool ShouldShowUi();
diff --git a/base/android/java_exception_reporter.cc b/base/android/java_exception_reporter.cc index 6859003c..fa3a72a 100644 --- a/base/android/java_exception_reporter.cc +++ b/base/android/java_exception_reporter.cc
@@ -61,8 +61,11 @@ } void SetJavaException(const char* exception) { - DCHECK(g_java_exception_callback); - g_java_exception_callback(exception); + // No need to print exception because they are already logged via + // env->ExceptionDescribe() within jni_android.cc. + if (g_java_exception_callback) { + g_java_exception_callback(exception); + } } void JNI_JavaExceptionReporter_ReportJavaException(
diff --git a/base/json/json_reader.cc b/base/json/json_reader.cc index 9456cfd..c40ff80 100644 --- a/base/json/json_reader.cc +++ b/base/json/json_reader.cc
@@ -46,7 +46,6 @@ ret.value = parser.Parse(json); if (!ret.value) { ret.error_message = parser.GetErrorMessage(); - ret.error_code = parser.error_code(); ret.error_line = parser.error_line(); ret.error_column = parser.error_column(); }
diff --git a/base/json/json_reader.h b/base/json/json_reader.h index 007f843..65753a4 100644 --- a/base/json/json_reader.h +++ b/base/json/json_reader.h
@@ -76,7 +76,6 @@ // Contains default values if |value| exists, or the error status if |value| // is base::nullopt. - int error_code = ValueDeserializer::kErrorCodeNoError; std::string error_message; int error_line = 0; int error_column = 0;
diff --git a/base/json/json_reader_fuzzer.cc b/base/json/json_reader_fuzzer.cc index 5f27ac2..ea9c62051 100644 --- a/base/json/json_reader_fuzzer.cc +++ b/base/json/json_reader_fuzzer.cc
@@ -24,9 +24,6 @@ JSONReader::ValueWithError json_val = JSONReader::ReadAndReturnValueWithError(input_string, options); - CHECK((json_val.error_code == base::ValueDeserializer::kErrorCodeNoError) == - json_val.value.has_value()); - if (json_val.value) { // Check that the value can be serialized and deserialized back to an // equivalent |Value|.
diff --git a/base/json/json_reader_unittest.cc b/base/json/json_reader_unittest.cc index 519a884..4ff15f1 100644 --- a/base/json/json_reader_unittest.cc +++ b/base/json/json_reader_unittest.cc
@@ -189,8 +189,6 @@ auto value_with_error = JSONReader::ReadAndReturnValueWithError("1e1000", JSON_PARSE_RFC); ASSERT_FALSE(value_with_error.value); - ASSERT_NE(base::ValueDeserializer::kErrorCodeNoError, - value_with_error.error_code); } TEST(JSONReaderTest, FractionalNumbers) {
diff --git a/base/json/json_string_value_serializer.cc b/base/json/json_string_value_serializer.cc index d98a62e3..7cd2119 100644 --- a/base/json/json_string_value_serializer.cc +++ b/base/json/json_string_value_serializer.cc
@@ -55,7 +55,7 @@ return base::Value::ToUniquePtrValue(std::move(*ret.value)); if (error_code) - *error_code = ret.error_code; + *error_code = base::ValueDeserializer::kErrorCodeInvalidFormat; if (error_str) *error_str = std::move(ret.error_message); return nullptr;
diff --git a/base/profiler/module_cache.cc b/base/profiler/module_cache.cc index ec08963..4d93da2 100644 --- a/base/profiler/module_cache.cc +++ b/base/profiler/module_cache.cc
@@ -54,38 +54,41 @@ } void ModuleCache::UpdateNonNativeModules( - const std::vector<const Module*>& to_remove, - std::vector<std::unique_ptr<const Module>> to_add) { + const std::vector<const Module*>& defunct_modules, + std::vector<std::unique_ptr<const Module>> new_modules) { // Insert the modules to remove into a set to support O(log(n)) lookup below. - flat_set<const Module*> to_remove_set(to_remove.begin(), to_remove.end()); + flat_set<const Module*> defunct_modules_set(defunct_modules.begin(), + defunct_modules.end()); // Reorder the modules to be removed to the last slots in the set, then move // them to the inactive modules, then erase the moved-from modules from the - // set. The flat_set docs endorse using base::EraseIf() which performs the - // same operations -- exclusive of the moves -- so this is OK even though it - // might seem like we're messing with the internal set representation. + // set. This is a variation on the standard erase-remove idiom, which is + // explicitly endorsed for implementing erase behavior on flat_sets. // - // remove_if is O(m*log(r)) where m is the number of current modules and r is - // the number of modules to remove. insert and erase are both O(r). - auto first_module_to_remove = std::remove_if( + // stable_partition is O(m*log(r)) where m is the number of current modules + // and r is the number of modules to remove. insert and erase are both O(r). + auto first_module_defunct_modules = std::stable_partition( non_native_modules_.begin(), non_native_modules_.end(), - [&to_remove_set](const std::unique_ptr<const Module>& module) { - return to_remove_set.find(module.get()) != to_remove_set.end(); + [&defunct_modules_set](const std::unique_ptr<const Module>& module) { + return defunct_modules_set.find(module.get()) == + defunct_modules_set.end(); }); // All modules requested to be removed should have been found. - DCHECK_EQ(static_cast<ptrdiff_t>(to_remove.size()), - std::distance(first_module_to_remove, non_native_modules_.end())); + DCHECK_EQ( + static_cast<ptrdiff_t>(defunct_modules.size()), + std::distance(first_module_defunct_modules, non_native_modules_.end())); inactive_non_native_modules_.insert( inactive_non_native_modules_.end(), - std::make_move_iterator(first_module_to_remove), + std::make_move_iterator(first_module_defunct_modules), std::make_move_iterator(non_native_modules_.end())); - non_native_modules_.erase(first_module_to_remove, non_native_modules_.end()); + non_native_modules_.erase(first_module_defunct_modules, + non_native_modules_.end()); // Insert the modules to be added. This operation is O((m + a) + a*log(a)) // where m is the number of current modules and a is the number of modules to // be added. - non_native_modules_.insert(std::make_move_iterator(to_add.begin()), - std::make_move_iterator(to_add.end())); + non_native_modules_.insert(std::make_move_iterator(new_modules.begin()), + std::make_move_iterator(new_modules.end())); } void ModuleCache::AddCustomNativeModule(std::unique_ptr<const Module> module) {
diff --git a/base/profiler/module_cache.h b/base/profiler/module_cache.h index 9bc601e..db0b2c0 100644 --- a/base/profiler/module_cache.h +++ b/base/profiler/module_cache.h
@@ -84,14 +84,14 @@ // GetModuleForAddress() will return the non-native module rather than the // native module for the memory region it occupies. // - // Modules in |to_remove| are removed from the set of active modules; + // Modules in |defunct_modules| are removed from the set of active modules; // specifically they no longer participate in the GetModuleForAddress() // lookup. They continue to exist for the lifetime of the ModuleCache, // however, so that existing references to them remain valid. Modules in - // |to_add| are added to the set of active non-native modules. + // |new_modules| are added to the set of active non-native modules. void UpdateNonNativeModules( - const std::vector<const Module*>& to_remove, - std::vector<std::unique_ptr<const Module>> to_add); + const std::vector<const Module*>& defunct_modules, + std::vector<std::unique_ptr<const Module>> new_modules); // Adds a custom native module to the cache. This is intended to support // native modules that require custom handling. In general, native modules
diff --git a/base/profiler/module_cache_unittest.cc b/base/profiler/module_cache_unittest.cc index 919899e0..b6eb063f 100644 --- a/base/profiler/module_cache_unittest.cc +++ b/base/profiler/module_cache_unittest.cc
@@ -226,6 +226,28 @@ EXPECT_TRUE(was_destroyed); } +// Regression test to validate that when modules are partitioned into modules to +// keep and modules to remove, the modules to remove are not destroyed. +// https://crbug.com/1127466 case 2. +MAYBE_TEST(ModuleCacheTest, UpdateNonNativeModulesPartitioning) { + int destroyed_count = 0; + const auto record_destroyed = [&destroyed_count]() { ++destroyed_count; }; + { + ModuleCache cache; + std::vector<std::unique_ptr<const ModuleCache::Module>> modules; + modules.push_back(std::make_unique<FakeModule>( + 1, 1, false, BindLambdaForTesting(record_destroyed))); + const ModuleCache::Module* module1 = modules.back().get(); + modules.push_back(std::make_unique<FakeModule>( + 2, 1, false, BindLambdaForTesting(record_destroyed))); + cache.UpdateNonNativeModules({}, std::move(modules)); + cache.UpdateNonNativeModules({module1}, {}); + + EXPECT_EQ(0, destroyed_count); + } + EXPECT_EQ(2, destroyed_count); +} + MAYBE_TEST(ModuleCacheTest, UpdateNonNativeModulesReplace) { ModuleCache cache; // Replace a module with another larger module at the same base address.
diff --git a/base/strings/string_piece.h b/base/strings/string_piece.h index 841fc38..b10707d9 100644 --- a/base/strings/string_piece.h +++ b/base/strings/string_piece.h
@@ -30,7 +30,6 @@ #include <type_traits> #include "base/base_export.h" -#include "base/check.h" #include "base/check_op.h" #include "base/strings/char_traits.h" #include "base/strings/string16.h" @@ -159,13 +158,25 @@ // in a "const char*" or a "string" wherever a "StringPiece" is // expected (likewise for char16, string16, StringPiece16). constexpr BasicStringPiece() : ptr_(nullptr), length_(0) {} + // TODO(crbug.com/1049498): Construction from nullptr is not allowed for + // std::basic_string_view, so remove the special handling for it. // Note: This doesn't just use STRING_TYPE::traits_type::length(), since that - // isn't constexpr until C++17. Furthermore, this CHECKs `str`, since passing - // a nullptr to std::basic_string_view is undefined behavior. In order to - // ensure we don't pass nullptr to CharTraits::length we perform the CHECK - // during the initialization of `length_`. + // isn't constexpr until C++17. constexpr BasicStringPiece(const value_type* str) - : ptr_(str), length_((CHECK(str), CharTraits<value_type>::length(str))) {} + : ptr_(str), length_(!str ? 0 : CharTraits<value_type>::length(str)) {} + // Explicitly disallow construction from nullptr. Note that this does not + // catch construction from runtime strings that might be null. + // Note: The following is just a more elaborate way of spelling + // `BasicStringPiece(nullptr_t) = delete`, but unfortunately the terse form is + // not supported by the PNaCl toolchain. + // TODO(crbug.com/1049498): Remove once we CHECK(str) in the constructor + // above. + template <class T, class = std::enable_if_t<std::is_null_pointer<T>::value>> + BasicStringPiece(T) { + static_assert(sizeof(T) == 0, // Always false. + "StringPiece does not support construction from nullptr, use " + "the default constructor instead."); + } BasicStringPiece(const STRING_TYPE& str) : ptr_(str.data()), length_(str.size()) {} constexpr BasicStringPiece(const value_type* offset, size_type len)
diff --git a/base/strings/string_piece_unittest.cc b/base/strings/string_piece_unittest.cc index 506cff2..ee4e0cf 100644 --- a/base/strings/string_piece_unittest.cc +++ b/base/strings/string_piece_unittest.cc
@@ -650,7 +650,6 @@ } TEST(StringPieceTest, OutOfBoundsDeath) { - { ASSERT_DEATH_IF_SUPPORTED(StringPiece(nullptr), ""); } { constexpr StringPiece piece; ASSERT_DEATH_IF_SUPPORTED(piece[0], "");
diff --git a/build/android/gyp/write_build_config.py b/build/android/gyp/write_build_config.py index 84b5e35..c4071d9 100755 --- a/build/android/gyp/write_build_config.py +++ b/build/android/gyp/write_build_config.py
@@ -783,7 +783,10 @@ ret[index:index + 1] = expanded_configs -def _DepsFromPaths(dep_paths, target_type, filter_root_targets=True): +def _DepsFromPaths(dep_paths, + target_type, + filter_root_targets=True, + recursive_resource_deps=False): """Resolves all groups and trims dependency branches that we never want. E.g. When a resource or asset depends on an apk target, the intent is to @@ -806,6 +809,10 @@ # Don't allow java libraries to cross through assets/resources. if target_type in _RESOURCE_TYPES: allowlist.extend(_RESOURCE_TYPES) + # Pretend that this target directly depends on all of its transitive + # dependencies. + if recursive_resource_deps: + dep_paths = GetAllDepsConfigsInOrder(dep_paths) return _DepsFromPathsWithFilters(dep_paths, blocklist, allowlist) @@ -914,6 +921,10 @@ action='store_true', help='Whether resources passed in via --resources-zip should override ' 'resources with the same name') + parser.add_option( + '--recursive-resource-deps', + action='store_true', + help='Whether deps should be walked recursively to find resource deps.') # android_assets options parser.add_option('--asset-sources', help='List of asset sources.') @@ -1177,7 +1188,9 @@ } deps_configs_paths = build_utils.ParseGnList(options.deps_configs) - deps = _DepsFromPaths(deps_configs_paths, options.type) + deps = _DepsFromPaths(deps_configs_paths, + options.type, + recursive_resource_deps=options.recursive_resource_deps) processor_deps = _DepsFromPaths( build_utils.ParseGnList(options.annotation_processor_configs or ''), options.type, filter_root_targets=False)
diff --git a/build/android/pylib/gtest/gtest_test_instance.py b/build/android/pylib/gtest/gtest_test_instance.py index 9d3adcc..15d65ddc7 100644 --- a/build/android/pylib/gtest/gtest_test_instance.py +++ b/build/android/pylib/gtest/gtest_test_instance.py
@@ -3,6 +3,7 @@ # found in the LICENSE file. import HTMLParser +import json import logging import os import re @@ -254,6 +255,29 @@ return results +def ParseGTestJSON(json_content): + """Parse results in the JSON Test Results format.""" + results = [] + if not json_content: + return results + + json_data = json.loads(json_content) + + openstack = json_data['tests'].items() + + while openstack: + name, value = openstack.pop() + + if 'expected' in value and 'actual' in value: + result_type = base_test_result.ResultType.PASS if value[ + 'actual'] == 'PASS' else base_test_result.ResultType.FAIL + results.append(base_test_result.BaseTestResult(name, result_type)) + else: + openstack += [("%s.%s" % (name, k), v) for k, v in value.iteritems()] + + return results + + def TestNameWithoutDisabledPrefix(test_name): """Modify the test name without disabled prefix if prefix 'DISABLED_' or 'FLAKY_' presents. @@ -281,6 +305,7 @@ self._extract_test_list_from_filter = args.extract_test_list_from_filter self._filter_tests_lock = threading.Lock() self._gs_test_artifacts_bucket = args.gs_test_artifacts_bucket + self._isolated_script_test_output = args.isolated_script_test_output self._isolated_script_test_perf_output = ( args.isolated_script_test_perf_output) self._shard_timeout = args.shard_timeout @@ -428,6 +453,10 @@ return self._gtest_filter @property + def isolated_script_test_output(self): + return self._isolated_script_test_output + + @property def isolated_script_test_perf_output(self): return self._isolated_script_test_perf_output
diff --git a/build/android/pylib/gtest/gtest_test_instance_test.py b/build/android/pylib/gtest/gtest_test_instance_test.py index b1a74dc..2a8c9b98 100755 --- a/build/android/pylib/gtest/gtest_test_instance_test.py +++ b/build/android/pylib/gtest/gtest_test_instance_test.py
@@ -216,6 +216,48 @@ actual = gtest_test_instance.ParseGTestXML(None) self.assertEquals([], actual) + def testParseGTestJSON_none(self): + actual = gtest_test_instance.ParseGTestJSON(None) + self.assertEquals([], actual) + + def testParseGTestJSON_example(self): + raw_json = """ + { + "tests": { + "mojom_tests": { + "parse": { + "ast_unittest": { + "ASTTest": { + "testNodeBase": { + "expected": "PASS", + "actual": "PASS", + "artifacts": { + "screenshot": ["screenshots/page.png"] + } + } + } + } + } + } + }, + "interrupted": false, + "path_delimiter": ".", + "version": 3, + "seconds_since_epoch": 1406662283.764424, + "num_failures_by_type": { + "FAIL": 0, + "PASS": 1 + }, + "artifact_types": { + "screenshot": "image/png" + } + }""" + actual = gtest_test_instance.ParseGTestJSON(raw_json) + self.assertEquals(1, len(actual)) + self.assertEquals('mojom_tests.parse.ast_unittest.ASTTest.testNodeBase', + actual[0].GetName()) + self.assertEquals(base_test_result.ResultType.PASS, actual[0].GetType()) + def testTestNameWithoutDisabledPrefix_disabled(self): test_name_list = [ 'A.DISABLED_B',
diff --git a/build/android/pylib/local/device/local_device_gtest_run.py b/build/android/pylib/local/device/local_device_gtest_run.py index 3ca6042..b38ff12b 100644 --- a/build/android/pylib/local/device/local_device_gtest_run.py +++ b/build/android/pylib/local/device/local_device_gtest_run.py
@@ -621,10 +621,15 @@ tombstones.ClearAllTombstones(device) test_perf_output_filename = next(self._test_perf_output_filenames) + if self._test_instance.isolated_script_test_output: + suffix = '.json' + else: + suffix = '.xml' + with device_temp_file.DeviceTempFile( adb=device.adb, dir=self._delegate.ResultsDirectory(device), - suffix='.xml') as device_tmp_results_file: + suffix=suffix) as device_tmp_results_file: with contextlib_ext.Optional( device_temp_file.NamedDeviceTemporaryDirectory( adb=device.adb, dir='/sdcard/'), @@ -641,9 +646,13 @@ if self._test_instance.gs_test_artifacts_bucket: flags.append('--test_artifacts_dir=%s' % test_artifacts_dir.name) + if self._test_instance.isolated_script_test_output: + flags.append('--isolated-script-test-output=%s' % + device_tmp_results_file.name) + if test_perf_output_filename: - flags.append('--isolated_script_test_perf_output=%s' - % isolated_script_test_perf_output.name) + flags.append('--isolated-script-test-perf-output=%s' % + isolated_script_test_perf_output.name) logging.info('flags:') for f in flags: @@ -658,24 +667,27 @@ if self._test_instance.enable_xml_result_parsing: try: - gtest_xml = device.ReadFile( - device_tmp_results_file.name, - as_root=True) - except device_errors.CommandFailedError as e: - logging.warning( - 'Failed to pull gtest results XML file %s: %s', - device_tmp_results_file.name, - str(e)) + gtest_xml = device.ReadFile(device_tmp_results_file.name) + except device_errors.CommandFailedError: + logging.exception('Failed to pull gtest results XML file %s', + device_tmp_results_file.name) gtest_xml = None + if self._test_instance.isolated_script_test_output: + try: + gtest_json = device.ReadFile(device_tmp_results_file.name) + except device_errors.CommandFailedError: + logging.exception('Failed to pull gtest results JSON file %s', + device_tmp_results_file.name) + gtest_json = None + if test_perf_output_filename: try: device.PullFile(isolated_script_test_perf_output.name, test_perf_output_filename) - except device_errors.CommandFailedError as e: - logging.warning( - 'Failed to pull chartjson results %s: %s', - isolated_script_test_perf_output.name, str(e)) + except device_errors.CommandFailedError: + logging.exception('Failed to pull chartjson results %s', + isolated_script_test_perf_output.name) test_artifacts_url = self._UploadTestArtifacts(device, test_artifacts_dir) @@ -695,6 +707,8 @@ # TODO(jbudorick): Transition test scripts away from parsing stdout. if self._test_instance.enable_xml_result_parsing: results = gtest_test_instance.ParseGTestXML(gtest_xml) + elif self._test_instance.isolated_script_test_output: + results = gtest_test_instance.ParseGTestJSON(gtest_json) else: results = gtest_test_instance.ParseGTestOutput( output, self._test_instance.symbolizer, device.product_cpu_abi)
diff --git a/build/android/pylib/results/json_results.py b/build/android/pylib/results/json_results.py index 6a10ba4..38ede80e 100644 --- a/build/android/pylib/results/json_results.py +++ b/build/android/pylib/results/json_results.py
@@ -6,6 +6,7 @@ import itertools import json import logging +import time from pylib.base import base_test_result @@ -111,6 +112,58 @@ } +def GenerateJsonTestResultFormatDict(test_run_results): + """Create a results dict from |test_run_results| suitable for writing to JSON. + + Args: + test_run_results: a list of base_test_result.TestRunResults objects. + Returns: + A results dict that mirrors the standard JSON Test Results Format. + """ + + tests = {} + pass_count = 0 + fail_count = 0 + + for test_run_result in test_run_results: + if isinstance(test_run_result, list): + results_iterable = itertools.chain(*(t.GetAll() for t in test_run_result)) + else: + results_iterable = test_run_result.GetAll() + + for r in results_iterable: + element = tests + for key in r.GetName().split('.'): + if key not in element: + element[key] = {} + element = element[key] + + element['expected'] = 'PASS' + + if r.GetType() == base_test_result.ResultType.PASS: + element['actual'] = 'PASS' + pass_count += 1 + else: + element['actual'] = 'FAIL' + fail_count += 1 + + if r.GetDuration() != 0: + element['time'] = r.GetDuration() + + # Fill in required fields. + return { + 'interrupted': False, + 'num_failures_by_type': { + 'FAIL': fail_count, + 'PASS': pass_count, + }, + 'path_delimiter': '.', + 'seconds_since_epoch': time.time(), + 'tests': tests, + 'version': 3, + } + + def GenerateJsonResultsFile(test_run_result, file_path, global_tags=None, **kwargs): """Write |test_run_result| to JSON. @@ -129,6 +182,21 @@ logging.info('Generated json results file at %s', file_path) +def GenerateJsonTestResultFormatFile(test_run_result, file_path, **kwargs): + """Write |test_run_result| to JSON. + + This uses the official Chromium Test Results Format. + + Args: + test_run_result: a base_test_result.TestRunResults object. + file_path: The path to the JSON file to write. + """ + with open(file_path, 'w') as json_result_file: + json_result_file.write( + json.dumps(GenerateJsonTestResultFormatDict(test_run_result), **kwargs)) + logging.info('Generated json results file at %s', file_path) + + def ParseResultsFromJson(json_results): """Creates a list of BaseTestResult objects from JSON.
diff --git a/build/android/pylib/results/json_results_test.py b/build/android/pylib/results/json_results_test.py index 68e71f57..2c1a422 100755 --- a/build/android/pylib/results/json_results_test.py +++ b/build/android/pylib/results/json_results_test.py
@@ -202,6 +202,40 @@ self.assertTrue('output_snippet_base64' in test_iteration_result) self.assertEquals('', test_iteration_result['output_snippet_base64']) + def testGenerateJsonTestResultFormatDict_passedResult(self): + result = base_test_result.BaseTestResult('test.package.TestName', + base_test_result.ResultType.PASS) + + all_results = base_test_result.TestRunResults() + all_results.AddResult(result) + + results_dict = json_results.GenerateJsonTestResultFormatDict([all_results]) + self.assertEquals(1, len(results_dict['tests'])) + self.assertEquals(1, len(results_dict['tests']['test'])) + self.assertEquals(1, len(results_dict['tests']['test']['package'])) + self.assertEquals( + 'PASS', + results_dict['tests']['test']['package']['TestName']['expected']) + self.assertEquals( + 'PASS', results_dict['tests']['test']['package']['TestName']['actual']) + + def testGenerateJsonTestResultFormatDict_failedResult(self): + result = base_test_result.BaseTestResult('test.package.TestName', + base_test_result.ResultType.FAIL) + + all_results = base_test_result.TestRunResults() + all_results.AddResult(result) + + results_dict = json_results.GenerateJsonTestResultFormatDict([all_results]) + self.assertEquals(1, len(results_dict['tests'])) + self.assertEquals(1, len(results_dict['tests']['test'])) + self.assertEquals(1, len(results_dict['tests']['test']['package'])) + self.assertEquals( + 'PASS', + results_dict['tests']['test']['package']['TestName']['expected']) + self.assertEquals( + 'FAIL', results_dict['tests']['test']['package']['TestName']['actual']) + if __name__ == '__main__': unittest.main(verbosity=2)
diff --git a/build/android/test_runner.py b/build/android/test_runner.py index 6c5848c9..521afea 100755 --- a/build/android/test_runner.py +++ b/build/android/test_runner.py
@@ -227,6 +227,12 @@ dest='run_disabled', action='store_true', help='Also run disabled tests if applicable.') + # This is currently only implemented for gtests. + parser.add_argument('--isolated-script-test-output', + help='If present, store test results on this path.') + parser.add_argument('--isolated-script-test-perf-output', + help='If present, store chartjson results on this path.') + AddTestLauncherOptions(parser) @@ -349,9 +355,6 @@ help='Host directory to which app data files will be' ' saved. Used with --app-data-file.') parser.add_argument( - '--isolated-script-test-perf-output', - help='If present, store chartjson results on this path.') - parser.add_argument( '--delete-stale-data', dest='delete_stale_data', action='store_true', help='Delete stale test data on the device.') @@ -835,6 +838,8 @@ finally: if args.json_results_file and os.path.exists(json_file.name): shutil.move(json_file.name, args.json_results_file) + elif args.isolated_script_test_output and os.path.exists(json_file.name): + shutil.move(json_file.name, args.isolated_script_test_output) else: os.remove(json_file.name) @@ -846,10 +851,16 @@ global_results_tags.add('UNRELIABLE_RESULTS') raise finally: - json_results.GenerateJsonResultsFile( - all_raw_results, json_file.name, - global_tags=list(global_results_tags), - indent=2) + if args.isolated_script_test_output: + json_results.GenerateJsonTestResultFormatFile(all_raw_results, + json_file.name, + indent=2) + else: + json_results.GenerateJsonResultsFile( + all_raw_results, + json_file.name, + global_tags=list(global_results_tags), + indent=2) @contextlib.contextmanager def upload_logcats_file(): @@ -953,7 +964,8 @@ str(tot_tests), str(iteration_count)) - if args.local_output or not local_utils.IsOnSwarming(): + if (args.local_output or not local_utils.IsOnSwarming() + ) and not args.isolated_script_test_output: with out_manager.ArchivedTempfile( 'test_results_presentation.html', 'test_results_presentation',
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni index 3724ee59..5290e4ad 100644 --- a/build/config/android/internal_rules.gni +++ b/build/config/android/internal_rules.gni
@@ -575,6 +575,10 @@ invoker.version_code, ] } + if (defined(invoker.recursive_resource_deps) && + invoker.recursive_resource_deps) { + args += [ "--recursive-resource-deps" ] + } if (current_toolchain != default_toolchain) { # This has to be a built-time error rather than a GN assert because many # packages have a mix of java and non-java targets. For example, the
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index 8bf6bca8..85d76f8 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni
@@ -897,6 +897,8 @@ # other. # r_text_file: (optional) path to pre-generated R.txt to be used when # generating R.java instead of resource-based aapt-generated one. + # recursive_resource_deps: (optional) whether deps should be walked + # recursively to find resource deps. # # Example: # android_resources("foo_resources") { @@ -982,6 +984,7 @@ "android_manifest_dep", "custom_package", "resource_overlay", + "recursive_resource_deps", ]) # No package means resources override their deps.
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index cfc02703..2dffbde 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -0.20200914.1.1 +0.20200914.3.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index cfc02703..19ffc48 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -0.20200914.1.1 +0.20200914.2.1
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc index eb78104..a5641c1 100644 --- a/cc/layers/picture_layer_impl.cc +++ b/cc/layers/picture_layer_impl.cc
@@ -596,11 +596,9 @@ if (layer_tree_impl()->IsActiveTree()) CleanUpTilingsOnActiveLayer(last_append_quads_tilings_); - const float old_ideal_contents_scale = ideal_contents_scale_; UpdateIdealScales(); - const bool should_adjust_raster_scale = - ShouldAdjustRasterScale(old_ideal_contents_scale); + const bool should_adjust_raster_scale = ShouldAdjustRasterScale(); if (should_adjust_raster_scale) RecalculateRasterScales(); UpdateTilingsForRasterScaleAndTranslation(should_adjust_raster_scale); @@ -1168,33 +1166,6 @@ return adjusted_raster_scale; } -// Log either the tile area saved or added due to directly compositing an -// image. This is logged every time we choose a raster source scale for a -// directly composited image. -void PictureLayerImpl::LogDirectlyCompositedImageRasterScaleUMAs() const { - base::CheckedNumeric<int> actual_area = - ScaleToCeiledSize(bounds(), raster_source_scale_).GetCheckedArea(); - base::CheckedNumeric<int> ideal_area = - ScaleToCeiledSize(bounds(), ideal_source_scale_).GetCheckedArea(); - if (actual_area.IsValid() && ideal_area.IsValid()) { - int area_difference = - std::abs(static_cast<int>((actual_area - ideal_area).ValueOrDie())); - bool raster_area_matches = raster_source_scale_ == ideal_source_scale_; - UMA_HISTOGRAM_BOOLEAN( - "Compositing.Renderer.DirectlyCompositedImage.TileAreaMatches", - raster_area_matches); - if (raster_source_scale_ < ideal_source_scale_) { - UMA_HISTOGRAM_COUNTS_10M( - "Compositing.Renderer.DirectlyCompositedImage.TileAreaSaved", - area_difference); - } else if (raster_source_scale_ > ideal_source_scale_) { - UMA_HISTOGRAM_COUNTS_10M( - "Compositing.Renderer.DirectlyCompositedImage.TileAreaAdded", - area_difference); - } - } -} - PictureLayerTiling* PictureLayerImpl::AddTiling( const gfx::AxisTransform2d& raster_transform) { DCHECK(CanHaveTilings()); @@ -1295,8 +1266,7 @@ SanityCheckTilingState(); } -bool PictureLayerImpl::ShouldAdjustRasterScale( - float old_ideal_contents_scale) const { +bool PictureLayerImpl::ShouldAdjustRasterScale() const { if (!raster_contents_scale_) return true; @@ -1324,23 +1294,8 @@ // changed. We should recalculate in order to raster at the intrinsic image // size. Note that this is not a comparison of the used raster_source_scale_ // and desired because of the adjustments in RecalculateRasterScales. - bool ideal_contents_scale_changed = - old_ideal_contents_scale != 0 && - old_ideal_contents_scale != ideal_contents_scale_; bool default_raster_scale_changed = default_raster_scale != directly_composited_image_initial_raster_scale_; - if (ideal_contents_scale_changed && !default_raster_scale_changed) { - // Log a histogram to indicate that we most likely saved raster costs, - // if the ideal contents scale changed but we did not need to recalculate - // raster scales because this layer is a directly composited image. - bool transform_trigger = - draw_properties().screen_space_transform_is_animating || - HasWillChangeTransformHint(); - UMA_HISTOGRAM_BOOLEAN( - "Compositing.Renderer.DirectlyCompositedImage." - "AvoidRasterAdjustmentWithTransformTrigger", - transform_trigger); - } return default_raster_scale_changed; } @@ -1431,14 +1386,7 @@ void PictureLayerImpl::RecalculateRasterScales() { if (directly_composited_image_size_) { float used_raster_scale = CalculateDirectlyCompositedImageRasterScale(); - const bool should_directly_composite = - ShouldDirectlyCompositeImage(used_raster_scale); - - UMA_HISTOGRAM_BOOLEAN( - "Compositing.Renderer.DirectlyCompositedImage." - "RasterScaleDirectlyComposited", - should_directly_composite); - if (should_directly_composite) { + if (ShouldDirectlyCompositeImage(used_raster_scale)) { directly_composited_image_initial_raster_scale_ = GetDefaultDirectlyCompositedImageRasterScale(); raster_source_scale_ = used_raster_scale; @@ -1446,8 +1394,6 @@ raster_device_scale_ = 1.f; raster_contents_scale_ = raster_source_scale_; low_res_raster_contents_scale_ = raster_contents_scale_; - - LogDirectlyCompositedImageRasterScaleUMAs(); return; }
diff --git a/cc/layers/picture_layer_impl.h b/cc/layers/picture_layer_impl.h index cfa31c95..935281ee 100644 --- a/cc/layers/picture_layer_impl.h +++ b/cc/layers/picture_layer_impl.h
@@ -175,7 +175,7 @@ const PictureLayerTiling& high_res) const; void UpdateTilingsForRasterScaleAndTranslation(bool adjusted_raster_scale); void AddLowResolutionTilingIfNeeded(); - bool ShouldAdjustRasterScale(float old_ideal_contents_scale) const; + bool ShouldAdjustRasterScale() const; void RecalculateRasterScales(); // Returns false if raster translation is not applicable. bool CalculateRasterTranslation(gfx::Vector2dF& raster_translation) const; @@ -199,7 +199,6 @@ // factors, and bumps up the reduced scale if those layers end up increasing // their contents scale. float CalculateDirectlyCompositedImageRasterScale() const; - void LogDirectlyCompositedImageRasterScaleUMAs() const; void SanityCheckTilingState() const;
diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc index 3c10b66..b59d5c98 100644 --- a/cc/layers/picture_layer_impl_unittest.cc +++ b/cc/layers/picture_layer_impl_unittest.cc
@@ -14,7 +14,6 @@ #include "base/location.h" #include "base/stl_util.h" -#include "base/test/metrics/histogram_tester.h" #include "base/threading/thread_task_runner_handle.h" #include "cc/animation/animation_host.h" #include "cc/base/math_util.h" @@ -5640,210 +5639,6 @@ ->contents_scale_key()); } -TEST_F(LegacySWPictureLayerImplTest, CompositedImageHistograms) { - base::HistogramTester histogram_tester; - - gfx::Size layer_bounds(5, 5); - scoped_refptr<FakeRasterSource> pending_raster_source = - FakeRasterSource::CreateFilled(layer_bounds); - - SetupPendingTree(pending_raster_source); - - // Set the image and bounds to values that make the layer not eligible for - // direct compositing. This must be reflected by a |contents_scale_key()| of - // 0.2f (matching the ideal source scale). - gfx::Size image_size(300, 300); - pending_layer()->SetDirectlyCompositedImageSize(image_size); - SetupDrawPropertiesAndUpdateTiles(pending_layer(), 0.2f, 1.f, 1.f, 1.f, 1.f, - false); - EXPECT_FLOAT_EQ(0.2f, pending_layer() - ->picture_layer_tiling_set() - ->FindTilingWithResolution(HIGH_RESOLUTION) - ->contents_scale_key()); - histogram_tester.ExpectBucketCount( - "Compositing.Renderer.DirectlyCompositedImage." - "RasterScaleDirectlyComposited", - false, 1); - histogram_tester.ExpectBucketCount( - "Compositing.Renderer.DirectlyCompositedImage." - "RasterScaleDirectlyComposited", - true, 0); - - // At ideal scale of 1, we save 270000 pixels for a 600x600 layer directly - // compositing a 300x300 image. - pending_layer()->SetBounds(gfx::Size(600, 600)); - pending_layer()->SetDirectlyCompositedImageSize(image_size); - SetupDrawPropertiesAndUpdateTiles(pending_layer(), 1.f, 1.f, 1.f, 1.f, 1.f, - false); - histogram_tester.ExpectBucketCount( - "Compositing.Renderer.DirectlyCompositedImage." - "TileAreaSaved", - 270000, 1); - histogram_tester.ExpectTotalCount( - "Compositing.Renderer.DirectlyCompositedImage." - "TileAreaSaved", - 1); - histogram_tester.ExpectTotalCount( - "Compositing.Renderer.DirectlyCompositedImage." - "TileAreaAdded", - 0); - histogram_tester.ExpectBucketCount( - "Compositing.Renderer.DirectlyCompositedImage." - "TileAreaMatches", - true, 0); - histogram_tester.ExpectBucketCount( - "Compositing.Renderer.DirectlyCompositedImage." - "TileAreaMatches", - false, 1); - histogram_tester.ExpectBucketCount( - "Compositing.Renderer.DirectlyCompositedImage." - "RasterScaleDirectlyComposited", - true, 1); - - // Matching bounds should log TileAreaMatches. - pending_layer()->SetDirectlyCompositedImageSize(gfx::Size(600, 600)); - SetupDrawPropertiesAndUpdateTiles(pending_layer(), 1.f, 1.f, 1.f, 1.f, 1.f, - false); - histogram_tester.ExpectBucketCount( - "Compositing.Renderer.DirectlyCompositedImage." - "TileAreaMatches", - true, 1); - histogram_tester.ExpectBucketCount( - "Compositing.Renderer.DirectlyCompositedImage." - "TileAreaMatches", - false, 1); - histogram_tester.ExpectTotalCount( - "Compositing.Renderer.DirectlyCompositedImage." - "TileAreaSaved", - 1); - histogram_tester.ExpectTotalCount( - "Compositing.Renderer.DirectlyCompositedImage." - "TileAreaAdded", - 0); - histogram_tester.ExpectBucketCount( - "Compositing.Renderer.DirectlyCompositedImage." - "RasterScaleDirectlyComposited", - true, 2); - - // Changing the bounds to be smaller than the image should add a TileAreaAdded - // histogram bucket count. - pending_layer()->SetBounds(gfx::Size(300, 300)); - SetupDrawPropertiesAndUpdateTiles(pending_layer(), 1.f, 1.f, 1.f, 1.f, 1.f, - false); - histogram_tester.ExpectBucketCount( - "Compositing.Renderer.DirectlyCompositedImage." - "TileAreaAdded", - 270000, 1); - histogram_tester.ExpectTotalCount( - "Compositing.Renderer.DirectlyCompositedImage." - "TileAreaSaved", - 1); - histogram_tester.ExpectTotalCount( - "Compositing.Renderer.DirectlyCompositedImage." - "TileAreaAdded", - 1); - histogram_tester.ExpectBucketCount( - "Compositing.Renderer.DirectlyCompositedImage." - "TileAreaMatches", - true, 1); - histogram_tester.ExpectBucketCount( - "Compositing.Renderer.DirectlyCompositedImage." - "TileAreaMatches", - false, 2); - histogram_tester.ExpectBucketCount( - "Compositing.Renderer.DirectlyCompositedImage." - "RasterScaleDirectlyComposited", - true, 3); - - // So far we haven't avoided any re-raster (as sizes have been updated at - // every stage of the test). Similarly, just updating tiles with no scale - // changes should not result in those histograms being logged. - SetupDrawPropertiesAndUpdateTiles(pending_layer(), 1.f, 1.f, 1.f, 1.f, 1.f, - false); - histogram_tester.ExpectBucketCount( - "Compositing.Renderer.DirectlyCompositedImage." - "AvoidRasterAdjustmentWithTransformTrigger", - false, 0); - histogram_tester.ExpectBucketCount( - "Compositing.Renderer.DirectlyCompositedImage." - "AvoidRasterAdjustmentWithTransformTrigger", - true, 0); - - // Reduce the ideal scale - directly composited image should not re-raster. - // Neither will-change:transform or active transformation so the 'false' - // bucket should get an entry. - SetupDrawPropertiesAndUpdateTiles(pending_layer(), 0.5f, 1.f, 1.f, 1.f, 1.f, - false); - histogram_tester.ExpectBucketCount( - "Compositing.Renderer.DirectlyCompositedImage." - "AvoidRasterAdjustmentWithTransformTrigger", - false, 1); - histogram_tester.ExpectBucketCount( - "Compositing.Renderer.DirectlyCompositedImage." - "AvoidRasterAdjustmentWithTransformTrigger", - true, 0); - - // Set will-change:transform and update tiles with a different ideal scale. - GetTransformNode(pending_layer())->will_change_transform = true; - SetupDrawPropertiesAndUpdateTiles(pending_layer(), 0.6f, 1.f, 1.f, 1.f, 1.f, - false); - histogram_tester.ExpectBucketCount( - "Compositing.Renderer.DirectlyCompositedImage." - "AvoidRasterAdjustmentWithTransformTrigger", - false, 1); - histogram_tester.ExpectBucketCount( - "Compositing.Renderer.DirectlyCompositedImage." - "AvoidRasterAdjustmentWithTransformTrigger", - true, 1); - - // None of the operations past the first one should have incremented this - // histogram. - histogram_tester.ExpectBucketCount( - "Compositing.Renderer.DirectlyCompositedImage." - "RasterScaleDirectlyComposited", - false, 1); -} - -TEST_F(LegacySWPictureLayerImplTest, CompositedImageHistogramsOverflow) { - base::HistogramTester histogram_tester; - - constexpr int kLargeDimension = std::numeric_limits<int>::max() / 2; - gfx::Size layer_bounds(kLargeDimension, kLargeDimension); - scoped_refptr<FakeRasterSource> pending_raster_source = - FakeRasterSource::CreateFilled(layer_bounds); - - // Overflow the area calculation for the histograms - we should still get - // the correct high res scale key, but no histograms should be logged. - SetupPendingTree(pending_raster_source); - pending_layer()->SetDirectlyCompositedImageSize(layer_bounds); - SetupDrawPropertiesAndUpdateTiles(pending_layer(), 1.f, 1.f, 1.f, 1.f, 1.f, - false); - EXPECT_FLOAT_EQ(1.f, pending_layer() - ->picture_layer_tiling_set() - ->FindTilingWithResolution(HIGH_RESOLUTION) - ->contents_scale_key()); - histogram_tester.ExpectTotalCount( - "Compositing.Renderer.DirectlyCompositedImage." - "TileAreaSaved", - 0); - histogram_tester.ExpectTotalCount( - "Compositing.Renderer.DirectlyCompositedImage." - "TileAreaAdded", - 0); - histogram_tester.ExpectTotalCount( - "Compositing.Renderer.DirectlyCompositedImage." - "TileAreaMatches", - 0); - histogram_tester.ExpectBucketCount( - "Compositing.Renderer.DirectlyCompositedImage." - "RasterScaleDirectlyComposited", - true, 1); - histogram_tester.ExpectBucketCount( - "Compositing.Renderer.DirectlyCompositedImage." - "RasterScaleDirectlyComposited", - false, 0); -} - TEST_F(LegacySWPictureLayerImplTest, ChangeRasterTranslationNukePendingLayerTiles) { gfx::Size layer_bounds(200, 200);
diff --git a/cc/metrics/compositor_frame_reporter.cc b/cc/metrics/compositor_frame_reporter.cc index 8335921e..7185f52 100644 --- a/cc/metrics/compositor_frame_reporter.cc +++ b/cc/metrics/compositor_frame_reporter.cc
@@ -849,12 +849,19 @@ FrameTerminationStatus::kDidNotProduceFrame) { state = ChromeFrameReporter::STATE_NO_UPDATE_DESIRED; } else { - state = ChromeFrameReporter::STATE_PRESENTED_ALL; + state = has_partial_update() + ? ChromeFrameReporter::STATE_PRESENTED_PARTIAL + : ChromeFrameReporter::STATE_PRESENTED_ALL; } auto* reporter = context.event()->set_chrome_frame_reporter(); reporter->set_state(state); reporter->set_frame_source(args_.frame_id.source_id); reporter->set_frame_sequence(args_.frame_id.sequence_number); + if (IsDroppedFrameAffectingSmoothness()) { + DCHECK(state == ChromeFrameReporter::STATE_DROPPED || + state == ChromeFrameReporter::STATE_PRESENTED_PARTIAL); + reporter->set_affects_smoothness(true); + } // TODO(crbug.com/1086974): Set 'drop reason' if applicable. });
diff --git a/chrome/VERSION b/chrome/VERSION index 77fb3c0..ec3c961 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=87 MINOR=0 -BUILD=4264 +BUILD=4265 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index d0aa1fa0..597ba0d 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -465,7 +465,6 @@ "//third_party/android_deps:androidx_customview_customview_java", "//third_party/android_deps:androidx_gridlayout_gridlayout_java", "//third_party/android_deps:androidx_interpolator_interpolator_java", - "//third_party/android_deps:androidx_legacy_legacy_support_v13_java", "//third_party/android_deps:androidx_lifecycle_lifecycle_common_java", "//third_party/android_deps:androidx_lifecycle_lifecycle_common_java8_java", "//third_party/android_deps:androidx_lifecycle_lifecycle_runtime_java", @@ -3119,12 +3118,6 @@ "java/src/org/chromium/chrome/browser/safe_browsing/SafeBrowsingPasswordReuseDialogBridge.java", "java/src/org/chromium/chrome/browser/screenshot/EditorScreenshotTask.java", "java/src/org/chromium/chrome/browser/search_engines/TemplateUrlServiceFactory.java", - "java/src/org/chromium/chrome/browser/send_tab_to_self/NotificationManager.java", - "java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfAndroidBridge.java", - "java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfEntry.java", - "java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfInfoBar.java", - "java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfModelObserverBridge.java", - "java/src/org/chromium/chrome/browser/send_tab_to_self/TargetDeviceInfo.java", "java/src/org/chromium/chrome/browser/sharing/SharingJNIBridge.java", "java/src/org/chromium/chrome/browser/sharing/SharingServiceProxy.java", "java/src/org/chromium/chrome/browser/sharing/click_to_call/ClickToCallMessageHandler.java",
diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_java_resources.gni index 55ccab9f..a12cad4c 100644 --- a/chrome/android/chrome_java_resources.gni +++ b/chrome/android/chrome_java_resources.gni
@@ -762,6 +762,7 @@ "java/res/drawable/tile_view_highlight_plain.xml", "java/res/drawable/tile_view_icon_background_modern.xml", "java/res/drawable/toolbar_shadow.xml", + "java/res/drawable/trending_up_black_24dp.xml", "java/res/drawable/visa_card.xml", "java/res/font/google_sans.xml", "java/res/font/google_sans_medium.xml",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni index dff36488..0d6e529 100644 --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni
@@ -351,6 +351,7 @@ "java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java", "java/src/org/chromium/chrome/browser/contextmenu/ContextMenuHelper.java", "java/src/org/chromium/chrome/browser/contextmenu/ContextMenuUi.java", + "java/src/org/chromium/chrome/browser/contextmenu/ContextMenuUtils.java", "java/src/org/chromium/chrome/browser/contextmenu/LensAsyncManager.java", "java/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuChipController.java", "java/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuCoordinator.java", @@ -1342,19 +1343,7 @@ "java/src/org/chromium/chrome/browser/searchwidget/SearchActivityLocationBarLayout.java", "java/src/org/chromium/chrome/browser/searchwidget/SearchBoxDataProvider.java", "java/src/org/chromium/chrome/browser/searchwidget/SearchWidgetProvider.java", - "java/src/org/chromium/chrome/browser/send_tab_to_self/DevicePickerBottomSheetAdapter.java", - "java/src/org/chromium/chrome/browser/send_tab_to_self/DevicePickerBottomSheetContent.java", - "java/src/org/chromium/chrome/browser/send_tab_to_self/NotificationManager.java", - "java/src/org/chromium/chrome/browser/send_tab_to_self/NotificationSharedPrefManager.java", - "java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfAndroidBridge.java", - "java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfCoordinator.java", - "java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfEntry.java", - "java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfInfoBar.java", - "java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfInfoBarController.java", - "java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfMetrics.java", - "java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfModelObserverBridge.java", "java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfShareActivity.java", - "java/src/org/chromium/chrome/browser/send_tab_to_self/TargetDeviceInfo.java", "java/src/org/chromium/chrome/browser/services/AccountsChangedReceiver.java", "java/src/org/chromium/chrome/browser/services/AndroidChildAccountHelper.java", "java/src/org/chromium/chrome/browser/services/gcm/ChromeGcmListenerService.java",
diff --git a/chrome/android/chrome_junit_test_java_sources.gni b/chrome/android/chrome_junit_test_java_sources.gni index 2fd2ca1c..f15b0ac 100644 --- a/chrome/android/chrome_junit_test_java_sources.gni +++ b/chrome/android/chrome_junit_test_java_sources.gni
@@ -202,8 +202,6 @@ "junit/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceMetricsTest.java", "junit/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceNotificationTest.java", "junit/src/org/chromium/chrome/browser/search_engines/settings/SearchEngineAdapterTest.java", - "junit/src/org/chromium/chrome/browser/send_tab_to_self/NotificationSharedPrefManagerTest.java", - "junit/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfAndroidBridgeTest.java", "junit/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfShareActivityTest.java", "junit/src/org/chromium/chrome/browser/sharing/click_to_call/ClickToCallMessageHandlerTest.java", "junit/src/org/chromium/chrome/browser/signin/ConfirmImportSyncDataDialogTest.java",
diff --git a/chrome/android/chrome_test_java_sources.gni b/chrome/android/chrome_test_java_sources.gni index 8c0e91f..d3514a68 100644 --- a/chrome/android/chrome_test_java_sources.gni +++ b/chrome/android/chrome_test_java_sources.gni
@@ -104,6 +104,7 @@ "javatests/src/org/chromium/chrome/browser/compositor/layouts/MockResourcesForLayout.java", "javatests/src/org/chromium/chrome/browser/compositor/overlays/strip/TabStripTest.java", "javatests/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulatorTest.java", + "javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuUtilsTest.java", "javatests/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuChipControllerTest.java", "javatests/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuHeaderViewTest.java", "javatests/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuItemViewTest.java", @@ -483,7 +484,6 @@ "javatests/src/org/chromium/chrome/browser/search_engines/settings/SearchEngineSettingsTest.java", "javatests/src/org/chromium/chrome/browser/searchwidget/SearchActivityTest.java", "javatests/src/org/chromium/chrome/browser/searchwidget/SearchWidgetProviderTest.java", - "javatests/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfCoordinatorTest.java", "javatests/src/org/chromium/chrome/browser/settings/MainSettingsFragmentTest.java", "javatests/src/org/chromium/chrome/browser/settings/SettingsActivityTest.java", "javatests/src/org/chromium/chrome/browser/shape_detection/ShapeDetectionTest.java",
diff --git a/chrome/android/expectations/lint-suppressions.xml b/chrome/android/expectations/lint-suppressions.xml index 287b445..0190b8b 100644 --- a/chrome/android/expectations/lint-suppressions.xml +++ b/chrome/android/expectations/lint-suppressions.xml
@@ -273,15 +273,11 @@ <!-- crbug.com/1076538 remove this line and the following two lines after the bug is resolved --> <ignore regexp="The resource `R.string.accessibility_tab_suggestion_group_tabs_message` appears to be unused"/> <ignore regexp="The resource `R.string.tab_suggestion_group_tabs_message` appears to be unused"/> - <!-- crbug.com/1114311 remove this line and the following two lines after the bug is resolved --> - <ignore regexp="The resource `R.string.languages_set_application_language_prompt` appears to be unused"/> - <ignore regexp="The resource `R.string.languages_set_as_application_language` appears to be unused"/> <!-- crbug.com/1111942 remove this line and following 7 lines after the bug is resolved --> <ignore regexp="The resource `R.string.accessibility_tab_switcher` appears to be unused"/> <ignore regexp="The resource `R.string.accessibility_close_tab_group_button` appears to be unused"/> <ignore regexp="The resource `R.string.accessibility_close_tab_group_button_with_group_name` appears to be unused"/> <ignore regexp="The resource `R.string.accessibility_expand_tab_group_with_group_name` appears to be unused"/> - <ignore regexp="The resource `R.string.tab_grid_dialog_toolbar_edit_group_name` appears to be unused"/> <!-- Old-style and new-style WebAPKs use same resources for simplicity. Old-style WebAPKs do not use R.style.SplashTheme but new-style WebAPKs do. TODO(crbug.com/971254): Remove suppression once old-style WebAPKs are deprecated. -->
diff --git a/chrome/android/features/autofill_assistant/BUILD.gn b/chrome/android/features/autofill_assistant/BUILD.gn index 70ff913..00635667e 100644 --- a/chrome/android/features/autofill_assistant/BUILD.gn +++ b/chrome/android/features/autofill_assistant/BUILD.gn
@@ -61,8 +61,6 @@ "//third_party/android_deps:androidx_coordinatorlayout_coordinatorlayout_java", "//third_party/android_deps:androidx_core_core_java", "//third_party/android_deps:androidx_gridlayout_gridlayout_java", - "//third_party/android_deps:androidx_legacy_legacy_support_core_ui_java", - "//third_party/android_deps:androidx_legacy_legacy_support_core_utils_java", "//third_party/android_deps:androidx_lifecycle_lifecycle_common_java", "//third_party/android_deps:androidx_lifecycle_lifecycle_runtime_java", "//third_party/android_deps:androidx_recyclerview_recyclerview_java",
diff --git a/chrome/android/features/tab_ui/BUILD.gn b/chrome/android/features/tab_ui/BUILD.gn index c9185fe2..188e7a86 100644 --- a/chrome/android/features/tab_ui/BUILD.gn +++ b/chrome/android/features/tab_ui/BUILD.gn
@@ -210,7 +210,6 @@ "//third_party/android_deps:androidx_annotation_annotation_java", "//third_party/android_deps:androidx_appcompat_appcompat_resources_java", "//third_party/android_deps:androidx_core_core_java", - "//third_party/android_deps:androidx_legacy_legacy_support_v13_java", "//third_party/android_deps:androidx_lifecycle_lifecycle_common_java", "//third_party/android_deps:androidx_lifecycle_lifecycle_runtime_java", "//third_party/android_deps:androidx_lifecycle_lifecycle_viewmodel_java",
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java index cb1656da..fac19dcd 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java
@@ -227,8 +227,10 @@ // Setup ScrimView click Runnable. mScrimClickRunnable = () -> { - mModel.set(TabGridPanelProperties.IS_KEYBOARD_VISIBLE, false); - mModel.set(TabGridPanelProperties.IS_TITLE_TEXT_FOCUSED, false); + if (!TabUiFeatureUtilities.isLaunchPolishEnabled()) { + mModel.set(TabGridPanelProperties.IS_KEYBOARD_VISIBLE, false); + mModel.set(TabGridPanelProperties.IS_TITLE_TEXT_FOCUSED, false); + } hideDialog(true); RecordUserAction.record("TabGridDialog.Exit"); }; @@ -247,7 +249,9 @@ mToolbarMenuCallback = result -> { if (result == R.id.ungroup_tab) { - mModel.set(TabGridPanelProperties.IS_KEYBOARD_VISIBLE, false); + if (!TabUiFeatureUtilities.isLaunchPolishEnabled()) { + mModel.set(TabGridPanelProperties.IS_KEYBOARD_VISIBLE, false); + } mModel.set(TabGridPanelProperties.IS_TITLE_TEXT_FOCUSED, false); List<Tab> tabs = getRelatedTabs(mCurrentTabId); if (mTabSelectionEditorController != null) { @@ -279,6 +283,12 @@ .build(); mShareDelegateSupplier.get().share(shareParams, chromeShareExtras); } + + if (TabUiFeatureUtilities.isLaunchPolishEnabled()) { + if (result == R.id.edit_group_name) { + mModel.set(TabGridPanelProperties.IS_TITLE_TEXT_FOCUSED, true); + } + } }; // Setup toolbar button click listeners. @@ -308,6 +318,9 @@ mTabSelectionEditorController.hide(); } saveCurrentGroupModifiedTitle(); + if (TabUiFeatureUtilities.isLaunchPolishEnabled()) { + mModel.set(TabGridPanelProperties.IS_TITLE_TEXT_FOCUSED, false); + } mDialogController.resetWithListOfTabs(null); } @@ -431,8 +444,12 @@ private void setupToolbarEditText() { mKeyboardVisibilityListener = isShowing -> { mModel.set(TabGridPanelProperties.TITLE_CURSOR_VISIBILITY, isShowing); - mModel.set(TabGridPanelProperties.IS_TITLE_TEXT_FOCUSED, isShowing); - mModel.set(TabGridPanelProperties.IS_KEYBOARD_VISIBLE, isShowing); + if (!TabUiFeatureUtilities.isLaunchPolishEnabled()) { + mModel.set(TabGridPanelProperties.IS_TITLE_TEXT_FOCUSED, isShowing); + mModel.set(TabGridPanelProperties.IS_KEYBOARD_VISIBLE, isShowing); + } else if (TabUiFeatureUtilities.isLaunchPolishEnabled() && !isShowing) { + mModel.set(TabGridPanelProperties.IS_TITLE_TEXT_FOCUSED, false); + } if (!isShowing) { saveCurrentGroupModifiedTitle(); } @@ -455,14 +472,20 @@ }; mModel.set(TabGridPanelProperties.TITLE_TEXT_WATCHER, textWatcher); - View.OnFocusChangeListener onFocusChangeListener = - (v, hasFocus) -> mIsUpdatingTitle = hasFocus; + View.OnFocusChangeListener onFocusChangeListener = (v, hasFocus) -> { + mIsUpdatingTitle = hasFocus; + if (!TabUiFeatureUtilities.isLaunchPolishEnabled()) return; + mModel.set(TabGridPanelProperties.IS_KEYBOARD_VISIBLE, hasFocus); + mModel.set(TabGridPanelProperties.IS_TITLE_TEXT_FOCUSED, hasFocus); + }; mModel.set(TabGridPanelProperties.TITLE_TEXT_ON_FOCUS_LISTENER, onFocusChangeListener); } private View.OnClickListener getCollapseButtonClickListener() { return view -> { - mModel.set(TabGridPanelProperties.IS_KEYBOARD_VISIBLE, false); + if (!TabUiFeatureUtilities.isLaunchPolishEnabled()) { + mModel.set(TabGridPanelProperties.IS_KEYBOARD_VISIBLE, false); + } hideDialog(true); RecordUserAction.record("TabGridDialog.Exit"); };
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMenuCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMenuCoordinator.java index a5ad8c3..e78cb15 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMenuCoordinator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMenuCoordinator.java
@@ -149,6 +149,11 @@ itemList.add(new ListItem(ListItemType.MENU_ITEM, buildPropertyModel(context, R.string.tab_grid_dialog_toolbar_share_group, R.id.share_tab_group))); + if (TabUiFeatureUtilities.isLaunchPolishEnabled()) { + itemList.add(new ListItem(ListItemType.MENU_ITEM, + buildPropertyModel(context, R.string.tab_grid_dialog_toolbar_edit_group_name, + R.id.edit_group_name))); + } return itemList; }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridPanelViewBinder.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridPanelViewBinder.java index 273d1f0..f35c9fd 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridPanelViewBinder.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridPanelViewBinder.java
@@ -131,11 +131,19 @@ } else if (TITLE_CURSOR_VISIBILITY == propertyKey) { viewHolder.toolbarView.setTitleCursorVisibility(model.get(TITLE_CURSOR_VISIBILITY)); } else if (IS_TITLE_TEXT_FOCUSED == propertyKey) { + if (TabUiFeatureUtilities.isLaunchPolishEnabled()) { + viewHolder.toolbarView.updateTitleTextFocus(model.get(IS_TITLE_TEXT_FOCUSED)); + return; + } // Don't explicitly request focus since it should happen automatically. if (!model.get(IS_TITLE_TEXT_FOCUSED)) { viewHolder.toolbarView.clearTitleTextFocus(); } } else if (IS_KEYBOARD_VISIBLE == propertyKey) { + if (TabUiFeatureUtilities.isLaunchPolishEnabled()) { + viewHolder.toolbarView.updateKeyboardVisibility(model.get(IS_KEYBOARD_VISIBLE)); + return; + } // Don't explicitly show keyboard since it should happen automatically. if (!model.get(IS_KEYBOARD_VISIBLE)) { viewHolder.toolbarView.hideKeyboard();
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiToolbarView.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiToolbarView.java index a5564c1d..cc3f603 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiToolbarView.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiToolbarView.java
@@ -80,6 +80,40 @@ mTitleTextView.setCursorVisible(isVisible); } + void updateTitleTextFocus(boolean shouldFocus) { + if (!TabUiFeatureUtilities.isLaunchPolishEnabled()) return; + if (mTitleTextView.isFocused() == shouldFocus) return; + if (shouldFocus) { + mTitleTextView.requestFocus(); + } else { + clearTitleTextFocus(); + } + } + + void updateKeyboardVisibility(boolean shouldShow) { + if (!TabUiFeatureUtilities.isLaunchPolishEnabled()) return; + // This is equal to the animation duration of toolbar menu hiding. + int showKeyboardDelay = 150; + if (shouldShow) { + // TODO(crbug.com/1116644) Figure out why a call to show keyboard without delay still + // won't work when the window gets focus in onWindowFocusChanged call. + // Wait until the current window has focus to show the keyboard. This is to deal with + // the case where the keyboard showing is caused by toolbar menu. In this case, we need + // to wait for the menu window to hide and current window to gain focus so that we can + // show the keyboard. + KeyboardVisibilityDelegate delegate = KeyboardVisibilityDelegate.getInstance(); + postDelayed(new Runnable() { + @Override + public void run() { + assert hasWindowFocus(); + delegate.showKeyboard(mTitleTextView); + } + }, showKeyboardDelay); + } else { + hideKeyboard(); + } + } + void clearTitleTextFocus() { mTitleTextView.clearFocus(); }
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogTest.java index b2b21b1..922e1497 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogTest.java
@@ -625,6 +625,37 @@ @Test @MediumTest + // clang-format off + @Features.EnableFeatures({ChromeFeatureList.TAB_GROUPS_CONTINUATION_ANDROID, + ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID + "<Study"}) + @CommandLineFlags.Add({"force-fieldtrials=Study/Group", TAB_GROUP_LAUNCH_POLISH_PARAMS}) + public void testTabGroupNaming_KeyboardVisibility() throws ExecutionException { + // clang-format on + final ChromeTabbedActivity cta = mActivityTestRule.getActivity(); + createTabs(cta, false, 2); + enterTabSwitcher(cta); + verifyTabSwitcherCardCount(cta, 2); + + // Create a tab group. + mergeAllNormalTabsToAGroup(cta); + verifyTabSwitcherCardCount(cta, 1); + openDialogFromTabSwitcherAndVerify(cta, 2, + cta.getResources().getQuantityString( + R.plurals.bottom_tab_grid_title_placeholder, 2, 2)); + + // Test title text focus in dialog in tab switcher. + testTitleTextFocus(cta); + + // Test title text focus in dialog from tab strip. + openDialogFromTabSwitcherAndVerify(cta, 2, null); + clickFirstTabInDialog(cta); + waitForDialogHidingAnimation(cta); + openDialogFromStripAndVerify(cta, 2, null); + testTitleTextFocus(cta); + } + + @Test + @MediumTest @DisableIf.Build(supported_abis_includes = "x86", message = "https://crbug.com/1124336") public void testDialogInitialShowFromStrip() throws Exception { final ChromeTabbedActivity cta = mActivityTestRule.getActivity(); @@ -1035,6 +1066,11 @@ // Verify if we can grab focus on the editText or not. assertEquals(isEnabled, v.isFocused()); }); + // Verify if the keyboard shows or not. + CriteriaHelper.pollUiThread(() + -> isEnabled + == KeyboardVisibilityDelegate.getInstance().isKeyboardShowing( + cta, cta.getCompositorViewHolder())); } private void openDialogToolbarMenuAndVerify(ChromeTabbedActivity cta) { @@ -1046,11 +1082,17 @@ if (noMatchException != null) throw noMatchException; Assert.assertTrue(v instanceof ListView); ListView listView = (ListView) v; - assertEquals(2, listView.getCount()); verifyTabGridDialogToolbarMenuItem(listView, 0, cta.getString(R.string.tab_grid_dialog_toolbar_remove_from_group)); verifyTabGridDialogToolbarMenuItem(listView, 1, cta.getString(R.string.tab_grid_dialog_toolbar_share_group)); + if (TabUiFeatureUtilities.isLaunchPolishEnabled()) { + assertEquals(3, listView.getCount()); + verifyTabGridDialogToolbarMenuItem(listView, 2, + cta.getString(R.string.tab_grid_dialog_toolbar_edit_group_name)); + } else { + assertEquals(2, listView.getCount()); + } }); } @@ -1218,4 +1260,39 @@ isDescendantOfA(withId(R.id.dialog_container_view)))) .check((v, e) -> assertEquals(s, v.getContentDescription())); } + + private void testTitleTextFocus(ChromeTabbedActivity cta) throws ExecutionException { + // Click the text field to grab focus and click back button to lose focus. + onView(allOf(withParent(withId(R.id.main_content)), withId(R.id.title))).perform(click()); + verifyTitleTextFocus(cta, true); + Espresso.pressBack(); + verifyTitleTextFocus(cta, false); + verifyShowingDialog(cta, 2, null); + + // Use toolbar menu to grab focus and click back button to lose focus. + openDialogToolbarMenuAndVerify(cta); + selectTabGridDialogToolbarMenuItem(cta, "Edit group name"); + verifyTitleTextFocus(cta, true); + Espresso.pressBack(); + verifyTitleTextFocus(cta, false); + verifyShowingDialog(cta, 2, null); + + // Click the text field to grab focus and click scrim to lose focus. + onView(allOf(withParent(withId(R.id.main_content)), withId(R.id.title))).perform(click()); + verifyTitleTextFocus(cta, true); + clickScrimToExitDialog(cta); + waitForDialogHidingAnimation(cta); + verifyTitleTextFocus(cta, false); + } + + private void verifyTitleTextFocus(ChromeTabbedActivity cta, boolean shouldFocus) { + CriteriaHelper.pollUiThread(() -> { + View titleTextView = cta.findViewById(R.id.tab_group_toolbar).findViewById(R.id.title); + KeyboardVisibilityDelegate delegate = KeyboardVisibilityDelegate.getInstance(); + boolean keyboardVisible = + delegate.isKeyboardShowing(cta, cta.getCompositorViewHolder()); + boolean isFocused = titleTextView.isFocused(); + return (!shouldFocus ^ isFocused) && (!shouldFocus ^ keyboardVisible); + }); + } }
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedImageFetchClient.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedImageFetchClient.java index 95e8248..936f815 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedImageFetchClient.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedImageFetchClient.java
@@ -36,9 +36,21 @@ } @Override - public void sendRequest(String url, ImageFetchClient.HttpResponseConsumer responseConsumer) { + public int sendCancelableRequest( + String url, ImageFetchClient.HttpResponseConsumer responseConsumer) { assert ThreadUtils.runningOnUiThread(); - FeedImageFetchClientJni.get().sendRequest(url, responseConsumer); + return FeedImageFetchClientJni.get().sendRequest(url, responseConsumer); + } + + @Override + public void sendRequest(String url, ImageFetchClient.HttpResponseConsumer responseConsumer) { + sendCancelableRequest(url, responseConsumer); + } + + @Override + public void cancel(int requestId) { + assert ThreadUtils.runningOnUiThread(); + FeedImageFetchClientJni.get().cancel(requestId); } @CalledByNative @@ -49,6 +61,7 @@ @NativeMethods interface Natives { - void sendRequest(String url, ImageFetchClient.HttpResponseConsumer responseConsumer); + int sendRequest(String url, ImageFetchClient.HttpResponseConsumer responseConsumer); + void cancel(int requestId); } }
diff --git a/chrome/android/java/res/drawable/trending_up_black_24dp.xml b/chrome/android/java/res/drawable/trending_up_black_24dp.xml new file mode 100644 index 0000000..b20c66c2 --- /dev/null +++ b/chrome/android/java/res/drawable/trending_up_black_24dp.xml
@@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2020 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. --> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + tools:targetApi="21" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + <path + android:pathData="M16,6v2h2.58l-5.17,5.17 -4,-4L2,16.59 3.41,18l6,-6 4,4L20,9.42V12h2V6z" + android:fillColor="#000000"/> +</vector>
diff --git a/chrome/android/java/res/layout/share_sheet_content.xml b/chrome/android/java/res/layout/share_sheet_content.xml index 20aafc0..c316ac2 100644 --- a/chrome/android/java/res/layout/share_sheet_content.xml +++ b/chrome/android/java/res/layout/share_sheet_content.xml
@@ -45,32 +45,30 @@ <TextView android:id="@+id/title_preview" android:ellipsize="end" - android:layout_width="fill_parent" + android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_toEndOf="@id/image_preview" android:maxLines="1" android:minHeight="18dp" android:paddingEnd="16dp" android:paddingStart="12dp" - android:gravity="center_vertical" - android:textAlignment="viewStart" - android:textAppearance="@style/TextAppearance.TextMediumThick.Primary"/> + android:paddingBottom="4dp" + android:textAlignment="viewStart"/> <TextView - android:id="@+id/url_preview" + android:id="@+id/subtitle_preview" android:ellipsize="end" android:layout_below="@id/title_preview" - android:layout_width="fill_parent" + android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_toEndOf="@id/image_preview" + android:layout_centerVertical="true" android:maxLines="1" android:minHeight="18dp" android:paddingEnd="16dp" android:paddingStart="12dp" - android:paddingTop="4dp" - android:gravity="center_vertical" android:textAlignment="viewStart" - android:textAppearance="@style/TextAppearance.TextMedium.Secondary"/> + android:textAppearance="@style/TextAppearance.TextMedium.Primary"/> </RelativeLayout> <View
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java b/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java index 8e4cb23..1831bdb5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java
@@ -47,10 +47,10 @@ import org.chromium.chrome.browser.xsurface.ProcessScopeDependencyProvider; import org.chromium.components.browser_ui.widget.FeatureHighlightProvider; import org.chromium.components.external_intents.AuthenticatorNavigationInterceptor; +import org.chromium.components.policy.AppRestrictionsProvider; +import org.chromium.components.policy.CombinedPolicyProvider; import org.chromium.components.signin.AccountManagerDelegate; import org.chromium.components.signin.SystemAccountManagerDelegate; -import org.chromium.policy.AppRestrictionsProvider; -import org.chromium.policy.CombinedPolicyProvider; import java.util.Collections; import java.util.List; @@ -262,6 +262,13 @@ new AppRestrictionsProvider(ContextUtils.getApplicationContext())); } + // TODO(zmin): Delete once the internal code is migrated. + public void registerPolicyProviders( + org.chromium.policy.CombinedPolicyProvider combinedProvider) { + combinedProvider.registerProvider( + new AppRestrictionsProvider(ContextUtils.getApplicationContext())); + } + /** * TODO(crbug.com/1102812) : Remove this method after updating the downstream to use the new * method {@link getOfflinePagesCctAllowlist} instead.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java index 3cb5daf..dce76474 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
@@ -179,14 +179,14 @@ import org.chromium.components.feature_engagement.EventConstants; import org.chromium.components.feature_engagement.Tracker; import org.chromium.components.page_info.PageInfoController; +import org.chromium.components.policy.CombinedPolicyProvider; +import org.chromium.components.policy.CombinedPolicyProvider.PolicyChangeListener; import org.chromium.components.user_prefs.UserPrefs; import org.chromium.components.webapk.lib.client.WebApkValidator; import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.browser.SelectionPopupController; import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.common.ContentSwitches; -import org.chromium.policy.CombinedPolicyProvider; -import org.chromium.policy.CombinedPolicyProvider.PolicyChangeListener; import org.chromium.printing.PrintManagerDelegateImpl; import org.chromium.printing.PrintingController; import org.chromium.printing.PrintingControllerImpl;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/send_tab_to_self/SendTabToSelfNotificationReceiver.java b/chrome/android/java/src/org/chromium/chrome/browser/app/send_tab_to_self/SendTabToSelfNotificationReceiver.java index ec9198c..96f0fa7b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/send_tab_to_self/SendTabToSelfNotificationReceiver.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/send_tab_to_self/SendTabToSelfNotificationReceiver.java
@@ -12,7 +12,7 @@ import org.chromium.chrome.browser.init.BrowserParts; import org.chromium.chrome.browser.init.ChromeBrowserInitializer; import org.chromium.chrome.browser.init.EmptyBrowserParts; -import org.chromium.chrome.browser.send_tab_to_self.NotificationManager; +import org.chromium.chrome.browser.share.send_tab_to_self.NotificationManager; /** Handles changes to notifications based on user action or timeout. */ public class SendTabToSelfNotificationReceiver extends BroadcastReceiver {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java index 241c10c..0cb83b1e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java
@@ -695,7 +695,10 @@ } else if (itemId == R.id.contextmenu_share_link) { recordContextMenuSelection(params, ContextMenuUma.Action.SHARE_LINK); ShareParams linkShareParams = - new ShareParams.Builder(getWindow(), params.getUrl(), params.getUrl()).build(); + new ShareParams + .Builder( + getWindow(), ContextMenuUtils.getTitle(params), params.getUrl()) + .build(); mShareDelegateSupplier.get().share( linkShareParams, new ChromeShareExtras.Builder().setSaveLastUsed(true).build()); } else if (itemId == R.id.contextmenu_search_with_google_lens) { @@ -735,7 +738,7 @@ ChromePreferenceKeys.CONTEXT_MENU_SEARCH_SIMILAR_PRODUCTS_CLICKED, true); } else if (itemId == R.id.contextmenu_share_image) { recordContextMenuSelection(params, ContextMenuUma.Action.SHARE_IMAGE); - shareImage(renderFrameHost, params.getSrcUrl()); + shareImage(renderFrameHost, params); } else if (itemId == R.id.contextmenu_open_in_chrome) { recordContextMenuSelection(params, ContextMenuUma.Action.OPEN_IN_CHROME); mDelegate.onOpenInChrome(params.getUrl(), params.getPageUrl()); @@ -820,9 +823,9 @@ * Package-private, allowing access only from the context menu item to ensure that * it will use the right activity set when the menu was displayed. * @param renderFrameHost {@link RenderFrameHost} to get the encoded images from. - * @param srcUrl url of the image. + * @param params The {@link ContextMenuParams} for the image. */ - private void shareImage(RenderFrameHost renderFrameHost, String srcUrl) { + private void shareImage(RenderFrameHost renderFrameHost, ContextMenuParams params) { retrieveImage(renderFrameHost, ContextMenuImageFormat.ORIGINAL, (Uri imageUri) -> { if (!mShareDelegateSupplier.get().isSharingHubV15Enabled()) { ShareHelper.shareImage(getWindow(), null, imageUri); @@ -831,14 +834,15 @@ ContentResolver contentResolver = ContextUtils.getApplicationContext().getContentResolver(); ShareParams imageShareParams = - new ShareParams.Builder(getWindow(), /*title=*/"", /*url=*/"") + new ShareParams + .Builder(getWindow(), ContextMenuUtils.getTitle(params), /*url=*/"") .setFileUris(new ArrayList<>(Collections.singletonList(imageUri))) .setFileContentType(contentResolver.getType(imageUri)) .build(); mShareDelegateSupplier.get().share(imageShareParams, new ChromeShareExtras.Builder() .setSaveLastUsed(true) - .setImageSrcUrl(srcUrl) + .setImageSrcUrl(params.getSrcUrl()) .build()); }); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuUtils.java new file mode 100644 index 0000000..ac20ff0 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuUtils.java
@@ -0,0 +1,33 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.contextmenu; + +import android.text.TextUtils; +import android.webkit.URLUtil; + +import org.chromium.components.embedder_support.contextmenu.ContextMenuParams; + +/** + * Provides utility methods for generating context menus. + */ +public final class ContextMenuUtils { + private ContextMenuUtils() {} + + /** + * Returns the title for the given {@link ContextMenuParams}. + */ + static String getTitle(ContextMenuParams params) { + if (!TextUtils.isEmpty(params.getTitleText())) { + return params.getTitleText(); + } + if (!TextUtils.isEmpty(params.getLinkText())) { + return params.getLinkText(); + } + if (params.isImage() || params.isVideo() || params.isFile()) { + return URLUtil.guessFileName(params.getSrcUrl(), null, null); + } + return ""; + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuHeaderCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuHeaderCoordinator.java index 9df3f26..b9c61472 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuHeaderCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuHeaderCoordinator.java
@@ -5,11 +5,9 @@ package org.chromium.chrome.browser.contextmenu; import android.app.Activity; -import android.content.Context; import android.graphics.Bitmap; import android.text.SpannableString; import android.text.TextUtils; -import android.webkit.URLUtil; import org.chromium.base.Callback; import org.chromium.chrome.browser.ChromeBaseAppCompatActivity; @@ -26,12 +24,9 @@ private PropertyModel mModel; private RevampedContextMenuHeaderMediator mMediator; - private Context mContext; - RevampedContextMenuHeaderCoordinator(Activity activity, @PerformanceClass int performanceClass, ContextMenuParams params, Profile profile) { - mContext = activity; - mModel = buildModel(getTitle(params), getUrl(activity, params, profile)); + mModel = buildModel(ContextMenuUtils.getTitle(params), getUrl(activity, params, profile)); mMediator = new RevampedContextMenuHeaderMediator( activity, mModel, performanceClass, params, profile); } @@ -51,19 +46,6 @@ .build(); } - private String getTitle(ContextMenuParams params) { - if (!TextUtils.isEmpty(params.getTitleText())) { - return params.getTitleText(); - } - if (!TextUtils.isEmpty(params.getLinkText())) { - return params.getLinkText(); - } - if (params.isImage() || params.isVideo() || params.isFile()) { - return URLUtil.guessFileName(params.getSrcUrl(), null, null); - } - return ""; - } - private CharSequence getUrl(Activity activity, ContextMenuParams params, Profile profile) { CharSequence url = params.getUrl(); if (!TextUtils.isEmpty(url)) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunAppRestrictionInfo.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunAppRestrictionInfo.java index c73583d..040162a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunAppRestrictionInfo.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunAppRestrictionInfo.java
@@ -19,8 +19,8 @@ import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.task.AsyncTask; import org.chromium.base.task.TaskTraits; -import org.chromium.policy.AppRestrictionsProvider; -import org.chromium.policy.PolicySwitches; +import org.chromium.components.policy.AppRestrictionsProvider; +import org.chromium.components.policy.PolicySwitches; import java.util.LinkedList; import java.util.Locale;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/TosAndUmaFirstRunFragmentWithEnterpriseSupport.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/TosAndUmaFirstRunFragmentWithEnterpriseSupport.java index e66dab7f..35c3c3b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/TosAndUmaFirstRunFragmentWithEnterpriseSupport.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/TosAndUmaFirstRunFragmentWithEnterpriseSupport.java
@@ -20,7 +20,7 @@ import org.chromium.chrome.browser.policy.EnterpriseInfo; import org.chromium.chrome.browser.policy.PolicyServiceFactory; import org.chromium.components.browser_ui.widget.LoadingView; -import org.chromium.policy.PolicyService; +import org.chromium.components.policy.PolicyService; /** * Another FirstRunFragment that is only used when running with CCT.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/ChromeBrowserInitializer.java b/chrome/android/java/src/org/chromium/chrome/browser/init/ChromeBrowserInitializer.java index 97c6c6e..2a6a3e3a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/init/ChromeBrowserInitializer.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/init/ChromeBrowserInitializer.java
@@ -41,12 +41,12 @@ import org.chromium.components.crash.browser.ChildProcessCrashObserver; import org.chromium.components.minidump_uploader.CrashFileManager; import org.chromium.components.module_installer.util.ModuleUtil; +import org.chromium.components.policy.CombinedPolicyProvider; import org.chromium.content_public.browser.BrowserStartupController; import org.chromium.content_public.browser.DeviceUtils; import org.chromium.content_public.browser.SpeechRecognition; import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.net.NetworkChangeNotifier; -import org.chromium.policy.CombinedPolicyProvider; import org.chromium.ui.resources.ResourceExtractor; import java.io.File;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteController.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteController.java index bf3760f..2d18938 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteController.java
@@ -10,6 +10,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; +import androidx.collection.ArraySet; import org.chromium.base.Log; import org.chromium.base.annotations.CalledByNative; @@ -29,6 +30,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Set; /** * Bridge to the native AutocompleteControllerAndroid. @@ -327,14 +329,14 @@ } @CalledByNative - private static OmniboxSuggestion buildOmniboxSuggestion(int nativeType, boolean isSearchType, - int relevance, int transition, String contents, int[] contentClassificationOffsets, - int[] contentClassificationStyles, String description, - int[] descriptionClassificationOffsets, int[] descriptionClassificationStyles, - SuggestionAnswer answer, String fillIntoEdit, GURL url, GURL imageUrl, - String imageDominantColor, boolean isStarred, boolean isDeletable, - String postContentType, byte[] postData, int groupId, List<QueryTile> tiles, - byte[] clipboardImageData, boolean hasTabMatch) { + private static OmniboxSuggestion buildOmniboxSuggestion(int nativeType, int[] nativeSubtypes, + boolean isSearchType, int relevance, int transition, String contents, + int[] contentClassificationOffsets, int[] contentClassificationStyles, + String description, int[] descriptionClassificationOffsets, + int[] descriptionClassificationStyles, SuggestionAnswer answer, String fillIntoEdit, + GURL url, GURL imageUrl, String imageDominantColor, boolean isStarred, + boolean isDeletable, String postContentType, byte[] postData, int groupId, + List<QueryTile> tiles, byte[] clipboardImageData, boolean hasTabMatch) { assert contentClassificationOffsets.length == contentClassificationStyles.length; List<MatchClassification> contentClassifications = new ArrayList<>(); for (int i = 0; i < contentClassificationOffsets.length; i++) { @@ -349,8 +351,13 @@ descriptionClassificationOffsets[i], descriptionClassificationStyles[i])); } - return new OmniboxSuggestion(nativeType, isSearchType, relevance, transition, contents, - contentClassifications, description, descriptionClassifications, answer, + Set<Integer> subtypes = new ArraySet(nativeSubtypes.length); + for (int i = 0; i < nativeSubtypes.length; i++) { + subtypes.add(nativeSubtypes[i]); + } + + return new OmniboxSuggestion(nativeType, subtypes, isSearchType, relevance, transition, + contents, contentClassifications, description, descriptionClassifications, answer, fillIntoEdit, url, imageUrl, imageDominantColor, isStarred, isDeletable, postContentType, postData, groupId, tiles, clipboardImageData, hasTabMatch); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/CachedZeroSuggestionsManager.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/CachedZeroSuggestionsManager.java index cc037e2..167d09b8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/CachedZeroSuggestionsManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/CachedZeroSuggestionsManager.java
@@ -14,6 +14,7 @@ import static org.chromium.chrome.browser.preferences.ChromePreferenceKeys.KEY_ZERO_SUGGEST_IS_DELETABLE_PREFIX; import static org.chromium.chrome.browser.preferences.ChromePreferenceKeys.KEY_ZERO_SUGGEST_IS_SEARCH_TYPE_PREFIX; import static org.chromium.chrome.browser.preferences.ChromePreferenceKeys.KEY_ZERO_SUGGEST_IS_STARRED_PREFIX; +import static org.chromium.chrome.browser.preferences.ChromePreferenceKeys.KEY_ZERO_SUGGEST_NATIVE_SUBTYPES_PREFIX; import static org.chromium.chrome.browser.preferences.ChromePreferenceKeys.KEY_ZERO_SUGGEST_NATIVE_TYPE_PREFIX; import static org.chromium.chrome.browser.preferences.ChromePreferenceKeys.KEY_ZERO_SUGGEST_POST_CONTENT_DATA_PREFIX; import static org.chromium.chrome.browser.preferences.ChromePreferenceKeys.KEY_ZERO_SUGGEST_POST_CONTENT_TYPE_PREFIX; @@ -25,7 +26,9 @@ import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; +import androidx.collection.ArraySet; +import org.chromium.base.Function; import org.chromium.chrome.browser.omnibox.MatchClassificationStyle; import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType; import org.chromium.chrome.browser.omnibox.suggestions.AutocompleteResult.GroupDetails; @@ -34,7 +37,9 @@ import org.chromium.url.GURL; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.Set; /** * CachedZeroSuggestionsManager manages caching and restoring zero suggestions. @@ -88,6 +93,9 @@ suggestion.getDescription()); prefs.writeInt(KEY_ZERO_SUGGEST_NATIVE_TYPE_PREFIX.createKey(numCachableSuggestions), suggestion.getType()); + prefs.writeStringSet( + KEY_ZERO_SUGGEST_NATIVE_SUBTYPES_PREFIX.createKey(numCachableSuggestions), + convertSet(suggestion.getSubtypes(), v -> v.toString())); prefs.writeBoolean( KEY_ZERO_SUGGEST_IS_SEARCH_TYPE_PREFIX.createKey(numCachableSuggestions), suggestion.isSearchSuggestion()); @@ -163,9 +171,20 @@ int groupId = prefs.readInt( KEY_ZERO_SUGGEST_GROUP_ID_PREFIX.createKey(i), OmniboxSuggestion.INVALID_GROUP); - OmniboxSuggestion suggestion = new OmniboxSuggestion(nativeType, isSearchType, 0, 0, - displayText, classifications, description, classifications, null, null, url, - GURL.emptyGURL(), null, isStarred, isDeletable, postContentType, postData, + Set<Integer> subtypes = null; + try { + Set<String> subtypeStrings = prefs.readStringSet( + KEY_ZERO_SUGGEST_NATIVE_SUBTYPES_PREFIX.createKey(i), null); + subtypes = convertSet(subtypeStrings, v -> Integer.parseInt(v)); + } catch (NumberFormatException e) { + // Subtype information contains malformed elements, suggesting that the + // entire cache may be damaged. + return Collections.emptyList(); + } + + OmniboxSuggestion suggestion = new OmniboxSuggestion(nativeType, subtypes, isSearchType, + 0, 0, displayText, classifications, description, classifications, null, null, + url, GURL.emptyGURL(), null, isStarred, isDeletable, postContentType, postData, groupId, null, null, false); suggestions.add(suggestion); } @@ -263,4 +282,23 @@ && suggestion.getType() != OmniboxSuggestionType.CLIPBOARD_TEXT && suggestion.getType() != OmniboxSuggestionType.CLIPBOARD_IMAGE; } + + /** + * Convert the set of type T to set of type U objects. + * + * @param <T> Type of data held in the input set (inferred). + * @param <U> Type of data held in the output set (inferred). + * @param input Input set. + * @param converter Function object that converts type T into type U. + * @return A set of input objects converted to string. + */ + private static <T, U> Set<U> convertSet(Set<T> input, Function<T, U> converter) { + if (input == null) return null; + + Set<U> result = new ArraySet<>(input.size()); + for (T item : input) { + result.add(converter.apply(item)); + } + return result; + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestion.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestion.java index eab8852..cded0596 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestion.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestion.java
@@ -6,6 +6,7 @@ import android.text.TextUtils; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.util.ObjectsCompat; @@ -15,7 +16,9 @@ import org.chromium.url.GURL; import java.util.Arrays; +import java.util.Collections; import java.util.List; +import java.util.Set; /** * Container class with information about each omnibox suggestion item. @@ -55,6 +58,7 @@ } private final int mType; + private final @NonNull Set<Integer> mSubtypes; private final boolean mIsSearchType; private final String mDisplayText; private final List<MatchClassification> mDisplayTextClassifications; @@ -76,14 +80,19 @@ private final byte[] mClipboardImageData; private final boolean mHasTabMatch; - public OmniboxSuggestion(int nativeType, boolean isSearchType, int relevance, int transition, - String displayText, List<MatchClassification> displayTextClassifications, - String description, List<MatchClassification> descriptionClassifications, - SuggestionAnswer answer, String fillIntoEdit, GURL url, GURL imageUrl, - String imageDominantColor, boolean isStarred, boolean isDeletable, - String postContentType, byte[] postData, int groupId, List<QueryTile> queryTiles, - byte[] clipboardImageData, boolean hasTabMatch) { + public OmniboxSuggestion(int nativeType, Set<Integer> subtypes, boolean isSearchType, + int relevance, int transition, String displayText, + List<MatchClassification> displayTextClassifications, String description, + List<MatchClassification> descriptionClassifications, SuggestionAnswer answer, + String fillIntoEdit, GURL url, GURL imageUrl, String imageDominantColor, + boolean isStarred, boolean isDeletable, String postContentType, byte[] postData, + int groupId, List<QueryTile> queryTiles, byte[] clipboardImageData, + boolean hasTabMatch) { + if (subtypes == null) { + subtypes = Collections.emptySet(); + } mType = nativeType; + mSubtypes = subtypes; mIsSearchType = isSearchType; mRelevance = relevance; mTransition = transition; @@ -207,6 +216,13 @@ return mRelevance; } + /** + * @return Set of suggestion subtypes. + */ + public @NonNull Set<Integer> getSubtypes() { + return mSubtypes; + } + @Override public int hashCode() { int hash = 37 * mType + mDisplayText.hashCode() + mFillIntoEdit.hashCode() @@ -222,7 +238,7 @@ } OmniboxSuggestion suggestion = (OmniboxSuggestion) obj; - return mType == suggestion.mType + return mType == suggestion.mType && ObjectsCompat.equals(mSubtypes, suggestion.mSubtypes) && TextUtils.equals(mFillIntoEdit, suggestion.mFillIntoEdit) && TextUtils.equals(mDisplayText, suggestion.mDisplayText) && ObjectsCompat.equals( @@ -249,13 +265,14 @@ @Override public String toString() { - List<String> pieces = Arrays.asList("mType=" + mType, "mIsSearchType=" + mIsSearchType, - "mDisplayText=" + mDisplayText, "mDescription=" + mDescription, - "mFillIntoEdit=" + mFillIntoEdit, "mUrl=" + mUrl, "mImageUrl=" + mImageUrl, - "mImageDominatColor=" + mImageDominantColor, "mRelevance=" + mRelevance, - "mTransition=" + mTransition, "mIsStarred=" + mIsStarred, - "mIsDeletable=" + mIsDeletable, "mPostContentType=" + mPostContentType, - "mPostData=" + Arrays.toString(mPostData), "mGroupId=" + mGroupId, + List<String> pieces = Arrays.asList("mType=" + mType, "mSubtypes=" + mSubtypes.toString(), + "mIsSearchType=" + mIsSearchType, "mDisplayText=" + mDisplayText, + "mDescription=" + mDescription, "mFillIntoEdit=" + mFillIntoEdit, "mUrl=" + mUrl, + "mImageUrl=" + mImageUrl, "mImageDominatColor=" + mImageDominantColor, + "mRelevance=" + mRelevance, "mTransition=" + mTransition, + "mIsStarred=" + mIsStarred, "mIsDeletable=" + mIsDeletable, + "mPostContentType=" + mPostContentType, "mPostData=" + Arrays.toString(mPostData), + "mGroupId=" + mGroupId, "mDisplayTextClassifications=" + mDisplayTextClassifications, "mDescriptionClassifications=" + mDescriptionClassifications, "mAnswer=" + mAnswer); return pieces.toString();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/VoiceSuggestionProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/VoiceSuggestionProvider.java index 795a72bf..55845c2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/VoiceSuggestionProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/VoiceSuggestionProvider.java
@@ -121,7 +121,7 @@ TemplateUrlServiceFactory.get().getUrlForVoiceSearchQuery(result.getMatch()); List<MatchClassification> classifications = new ArrayList<>(); classifications.add(new MatchClassification(0, MatchClassificationStyle.NONE)); - suggestions.add(new OmniboxSuggestion(OmniboxSuggestionType.VOICE_SUGGEST, true, 0, 1, + suggestions.add(new OmniboxSuggestion(OmniboxSuggestionType.VOICE_SUGGEST, null, true, 0, 1, result.getMatch(), classifications, null, classifications, null, null, voiceUrl, GURL.emptyGURL(), null, false, false, null, null, OmniboxSuggestion.INVALID_GROUP, null, null, false));
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessor.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessor.java index 99a84750..5c57be1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessor.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessor.java
@@ -91,6 +91,9 @@ return SuggestionIcon.HISTORY; default: + if (suggestion.getSubtypes().contains(/* SUBTYPE_TRENDS = */ 143)) { + return SuggestionIcon.TRENDS; + } return SuggestionIcon.MAGNIFIER; } } else { @@ -129,6 +132,10 @@ icon = R.drawable.btn_mic; break; + case SuggestionIcon.TRENDS: + icon = R.drawable.trending_up_black_24dp; + break; + default: // All other cases are invalid. assert false : "Suggestion type " + type + " is not valid.";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewProperties.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewProperties.java index 38b2e12..9133328 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewProperties.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewProperties.java
@@ -23,7 +23,8 @@ public class SuggestionViewProperties { @IntDef({SuggestionIcon.UNSET, SuggestionIcon.BOOKMARK, SuggestionIcon.HISTORY, SuggestionIcon.GLOBE, SuggestionIcon.MAGNIFIER, SuggestionIcon.VOICE, - SuggestionIcon.CALCULATOR, SuggestionIcon.FAVICON, SuggestionIcon.TOTAL_COUNT}) + SuggestionIcon.CALCULATOR, SuggestionIcon.FAVICON, SuggestionIcon.TRENDS, + SuggestionIcon.TOTAL_COUNT}) @Retention(RetentionPolicy.SOURCE) public @interface SuggestionIcon { // This enum is used to back UMA histograms, and should therefore be treated as append-only. @@ -36,7 +37,8 @@ int VOICE = 5; int CALCULATOR = 6; int FAVICON = 7; - int TOTAL_COUNT = 8; + int TRENDS = 8; + int TOTAL_COUNT = 9; } /** The suggestion icon type shown. @see SuggestionIcon. Used for metric collection purposes. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfShareActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfShareActivity.java index 0d84294..25dca80 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfShareActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfShareActivity.java
@@ -9,6 +9,8 @@ import org.chromium.chrome.browser.ChromeAccessorActivity; import org.chromium.chrome.browser.app.ChromeActivity; import org.chromium.chrome.browser.settings.SettingsLauncherImpl; +import org.chromium.chrome.browser.share.send_tab_to_self.SendTabToSelfAndroidBridge; +import org.chromium.chrome.browser.share.send_tab_to_self.SendTabToSelfCoordinator; import org.chromium.chrome.browser.sync.AndroidSyncSettings; import org.chromium.chrome.browser.tab.Tab; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; @@ -24,7 +26,7 @@ private static AndroidSyncSettings sAndroidSyncSettings; @Override - protected void handleAction(ChromeActivity triggeringActivity) { + public void handleAction(ChromeActivity triggeringActivity) { Tab tab = triggeringActivity.getActivityTabProvider().get(); if (tab == null) return; NavigationEntry entry = tab.getWebContents().getNavigationController().getVisibleEntry();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsCoordinator.java index b59b3b2..0613149 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsCoordinator.java
@@ -111,6 +111,10 @@ } Toast.setGlobalExtraYOffset( root.getResources().getDimensionPixelSize(bottomControlsHeightId)); + + // Set the visibility of BottomControls to false by default. Components within + // BottomControls should update the visibility explicitly if needed. + mMediator.setBottomControlsVisible(false); } /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/app/appmenu/TabbedAppMenuTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/app/appmenu/TabbedAppMenuTest.java index e0293f3..3a75b73c 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/app/appmenu/TabbedAppMenuTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/app/appmenu/TabbedAppMenuTest.java
@@ -45,6 +45,7 @@ import org.chromium.chrome.test.ChromeTabbedActivityTestRule; import org.chromium.chrome.test.util.ChromeRenderTestRule; import org.chromium.chrome.test.util.ChromeTabUtils; +import org.chromium.chrome.test.util.browser.Features.DisableFeatures; import org.chromium.chrome.test.util.browser.Features.EnableFeatures; import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.content_public.browser.test.util.Criteria; @@ -242,8 +243,11 @@ @Test @SmallTest @Feature({"Browser", "Main", "Bookmark", "RenderTest"}) + @DisableFeatures({ChromeFeatureList.TABBED_APP_OVERFLOW_MENU_REGROUP, + ChromeFeatureList.TABBED_APP_OVERFLOW_MENU_ICONS}) @DisableIf.Device(type = {UiDisableIf.TABLET}) // See https://crbug.com/1065043. - public void testBookmarkMenuItem() throws IOException { + public void + testBookmarkMenuItem() throws IOException { MenuItem bookmarkStar = AppMenuTestSupport.getMenu(mActivityTestRule.getAppMenuCoordinator()) .findItem(R.id.bookmark_this_page_id);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuUtilsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuUtilsTest.java new file mode 100644 index 0000000..10cc619 --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuUtilsTest.java
@@ -0,0 +1,65 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.contextmenu; + +import static org.junit.Assert.assertEquals; + +import android.webkit.URLUtil; + +import androidx.test.filters.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.blink_public.common.ContextMenuDataMediaType; +import org.chromium.components.embedder_support.contextmenu.ContextMenuParams; + +/** + * Unit tests for {@link ContextMenuUtils}. + */ +@RunWith(BaseJUnit4ClassRunner.class) +public class ContextMenuUtilsTest { + private static final String sTitleText = "titleText"; + private static final String sLinkText = "linkText"; + private static final String sSrcUrl = "https://www.google.com/"; + + @Test + @SmallTest + public void getTitle_hasTitleText() { + ContextMenuParams params = new ContextMenuParams(0, + org.chromium.blink_public.common.ContextMenuDataMediaType.IMAGE, "", "", sLinkText, + "", sSrcUrl, sTitleText, null, false, 0, 0, 0); + + assertEquals(sTitleText, ContextMenuUtils.getTitle(params)); + } + + @Test + @SmallTest + public void getTitle_noTitleTextHasLinkText() { + ContextMenuParams params = new ContextMenuParams(0, ContextMenuDataMediaType.IMAGE, "", "", + sLinkText, "", sSrcUrl, "", null, false, 0, 0, 0); + + assertEquals(sLinkText, ContextMenuUtils.getTitle(params)); + } + + @Test + @SmallTest + public void getTitle_noTitleTextOrLinkText() { + ContextMenuParams params = new ContextMenuParams(0, ContextMenuDataMediaType.IMAGE, "", "", + "", "", sSrcUrl, "", null, false, 0, 0, 0); + + assertEquals(URLUtil.guessFileName(sSrcUrl, null, null), ContextMenuUtils.getTitle(params)); + } + + @Test + @SmallTest + public void getTitle_noShareParams() { + ContextMenuParams params = new ContextMenuParams( + 0, ContextMenuDataMediaType.NONE, "", "", "", "", "", "", null, false, 0, 0, 0); + + assertEquals("", ContextMenuUtils.getTitle(params)); + } +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuTest.java index 69f6d41..c45c8d0 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuTest.java
@@ -49,13 +49,13 @@ import org.chromium.chrome.test.util.ChromeTabUtils; import org.chromium.chrome.test.util.browser.Features; import org.chromium.chrome.test.util.browser.contextmenu.RevampedContextMenuUtils; +import org.chromium.components.policy.test.annotations.Policies; import org.chromium.content_public.browser.test.util.Criteria; import org.chromium.content_public.browser.test.util.CriteriaHelper; import org.chromium.content_public.browser.test.util.DOMUtils; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.content_public.browser.test.util.TestTouchUtils; import org.chromium.net.test.EmbeddedTestServer; -import org.chromium.policy.test.annotations.Policies; import org.chromium.ui.base.Clipboard; import java.io.IOException;
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 12f15ce..5683993 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
@@ -45,11 +45,11 @@ import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.MultiActivityTestRule; +import org.chromium.components.policy.AbstractAppRestrictionsProvider; import org.chromium.components.search_engines.TemplateUrl; import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.content_public.browser.test.util.Criteria; import org.chromium.content_public.browser.test.util.CriteriaHelper; -import org.chromium.policy.AbstractAppRestrictionsProvider; import java.util.HashMap; import java.util.List;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/TosAndUmaFirstRunFragmentWithEnterpriseSupportTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/TosAndUmaFirstRunFragmentWithEnterpriseSupportTest.java index db37bb7..f43765d 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/TosAndUmaFirstRunFragmentWithEnterpriseSupportTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/TosAndUmaFirstRunFragmentWithEnterpriseSupportTest.java
@@ -38,10 +38,10 @@ import org.chromium.chrome.browser.policy.EnterpriseInfo; import org.chromium.chrome.browser.policy.PolicyServiceFactory; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.components.policy.PolicyService; import org.chromium.content_public.browser.test.util.Criteria; import org.chromium.content_public.browser.test.util.CriteriaHelper; import org.chromium.content_public.browser.test.util.TestThreadUtils; -import org.chromium.policy.PolicyService; import org.chromium.ui.test.util.DisableAnimationsTestRule; import java.lang.annotation.Retention;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/homepage/HomepagePolicyIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/homepage/HomepagePolicyIntegrationTest.java index fab4a56..da2279b 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/homepage/HomepagePolicyIntegrationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/homepage/HomepagePolicyIntegrationTest.java
@@ -43,12 +43,12 @@ import org.chromium.chrome.test.util.browser.Features.DisableFeatures; import org.chromium.chrome.test.util.browser.TabLoadObserver; import org.chromium.components.browser_ui.settings.ChromeSwitchPreference; +import org.chromium.components.policy.test.annotations.Policies; import org.chromium.content_public.browser.test.util.Criteria; import org.chromium.content_public.browser.test.util.CriteriaHelper; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.content_public.browser.test.util.TouchCommon; import org.chromium.net.test.EmbeddedTestServer; -import org.chromium.policy.test.annotations.Policies; /** * Integration test for {@link HomepagePolicyManager}.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/homepage/HomepageTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/homepage/HomepageTestRule.java index cbc2459..191b79f 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/homepage/HomepageTestRule.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/homepage/HomepageTestRule.java
@@ -15,11 +15,11 @@ import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; import org.chromium.chrome.browser.preferences.SharedPreferencesManager; +import org.chromium.components.policy.AbstractAppRestrictionsProvider; +import org.chromium.components.policy.AppRestrictionsProvider; +import org.chromium.components.policy.CombinedPolicyProvider; +import org.chromium.components.policy.test.PolicyData; import org.chromium.content_public.browser.test.util.TestThreadUtils; -import org.chromium.policy.AbstractAppRestrictionsProvider; -import org.chromium.policy.AppRestrictionsProvider; -import org.chromium.policy.CombinedPolicyProvider; -import org.chromium.policy.test.PolicyData; import java.util.Arrays;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/locale/LocaleManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/locale/LocaleManagerTest.java index 7af1760d..28e93b7 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/locale/LocaleManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/locale/LocaleManagerTest.java
@@ -21,8 +21,8 @@ import org.chromium.chrome.browser.searchwidget.SearchActivity; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.util.ActivityUtils; +import org.chromium.components.policy.test.annotations.Policies; import org.chromium.content_public.browser.test.util.TestThreadUtils; -import org.chromium.policy.test.annotations.Policies; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteResultUnitTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteResultUnitTest.java index 5f0b9390..4b6a7518 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteResultUnitTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteResultUnitTest.java
@@ -42,6 +42,17 @@ List<OmniboxSuggestion> list2 = Arrays.asList( buildSuggestionForIndex(1), buildSuggestionForIndex(2), buildSuggestionForIndex(3)); + // Element 0: 2 subtypes + list1.get(0).getSubtypes().add(10); + list1.get(0).getSubtypes().add(17); + list2.get(0).getSubtypes().add(10); + list2.get(0).getSubtypes().add(17); + + // Element 1: 0 subtypes. + // Element 2: 1 subtype. + list1.get(2).getSubtypes().add(4); + list2.get(2).getSubtypes().add(4); + SparseArray<GroupDetails> groupsDetails1 = new SparseArray<>(); SparseArray<GroupDetails> groupsDetails2 = new SparseArray<>(); @@ -199,6 +210,31 @@ @Test @SmallTest + public void autocompleteResult_differentSubtypesAreNotEqual() { + List<OmniboxSuggestion> list1 = Arrays.asList( + OmniboxSuggestionBuilderForTest.searchWithType(OmniboxSuggestionType.SEARCH_SUGGEST) + .addSubtype(10) + .build(), + OmniboxSuggestionBuilderForTest.searchWithType(OmniboxSuggestionType.SEARCH_SUGGEST) + .addSubtype(17) + .build()); + + List<OmniboxSuggestion> list2 = Arrays.asList( + OmniboxSuggestionBuilderForTest.searchWithType(OmniboxSuggestionType.SEARCH_SUGGEST) + .addSubtype(10) + .build(), + OmniboxSuggestionBuilderForTest.searchWithType(OmniboxSuggestionType.SEARCH_SUGGEST) + .addSubtype(4) + .build()); + + AutocompleteResult res1 = new AutocompleteResult(list1, null); + AutocompleteResult res2 = new AutocompleteResult(list2, null); + + Assert.assertNotEquals(res1, res2); + } + + @Test + @SmallTest public void autocompleteResult_newItemsAreNotEqual() { List<OmniboxSuggestion> list1 = Arrays.asList(buildSuggestionForIndex(1), buildSuggestionForIndex(2));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/CachedZeroSuggestionsManagerUnitTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/CachedZeroSuggestionsManagerUnitTest.java index ac0df82c..ffc173be 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/CachedZeroSuggestionsManagerUnitTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/CachedZeroSuggestionsManagerUnitTest.java
@@ -27,6 +27,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Set; /** * Unit tests for {@link CachedZeroSuggestionsManager}. @@ -346,4 +347,78 @@ dataWithInvalidItems.getSuggestionsList(), dataWithInvalidItems.getGroupsDetails()); assertAutocompleteResultEquals(dataWithInvalidItems, dataExpected); } + + @Test + @SmallTest + @UiThreadTest + public void cacheAndRestoreSuggestionSubtypes() { + List<OmniboxSuggestion> list = Arrays.asList( + createSuggestionBuilder(1, OmniboxSuggestionType.SEARCH_SUGGEST_PERSONALIZED) + .addSubtype(1) + .addSubtype(4) + .build(), + createSuggestionBuilder(2, OmniboxSuggestionType.HISTORY_URL) + .addSubtype(17) + .build(), + createSuggestionBuilder(3, OmniboxSuggestionType.SEARCH_SUGGEST_ENTITY) + .addSubtype(2) + .addSubtype(10) + .addSubtype(30) + .build(), + createSuggestionBuilder(4, OmniboxSuggestionType.SEARCH_HISTORY).build()); + + AutocompleteResult dataToCache = new AutocompleteResult(list, null); + CachedZeroSuggestionsManager.saveToCache(dataToCache); + AutocompleteResult dataFromCache = CachedZeroSuggestionsManager.readFromCache(); + assertAutocompleteResultEquals(dataToCache, dataFromCache); + } + + @Test + @SmallTest + @UiThreadTest + public void rejectCacheIfSubtypesAreMalformed() { + List<OmniboxSuggestion> list = Arrays.asList( + createSuggestionBuilder(1, OmniboxSuggestionType.SEARCH_SUGGEST_PERSONALIZED) + .addSubtype(1) + .addSubtype(4) + .build(), + createSuggestionBuilder(2, OmniboxSuggestionType.HISTORY_URL) + .addSubtype(17) + .build()); + + AutocompleteResult dataToCache = new AutocompleteResult(list, null); + CachedZeroSuggestionsManager.saveToCache(dataToCache); + + // Insert garbage for the Suggestion Subtypes. + final SharedPreferencesManager manager = SharedPreferencesManager.getInstance(); + final Set<String> garbageSubtypes = Set.of("invalid"); + manager.writeStringSet( + ChromePreferenceKeys.KEY_ZERO_SUGGEST_NATIVE_SUBTYPES_PREFIX.createKey(1), + garbageSubtypes); + + AutocompleteResult dataFromCache = CachedZeroSuggestionsManager.readFromCache(); + assertAutocompleteResultEquals(new AutocompleteResult(null, null), dataFromCache); + } + + @Test + @SmallTest + @UiThreadTest + public void rejectCacheIfSubtypesIncludeNull() { + List<OmniboxSuggestion> list = Arrays.asList( + createSuggestionBuilder(1, OmniboxSuggestionType.SEARCH_SUGGEST_PERSONALIZED) + .addSubtype(1) + .build()); + + AutocompleteResult dataToCache = new AutocompleteResult(list, null); + CachedZeroSuggestionsManager.saveToCache(dataToCache); + + final SharedPreferencesManager manager = SharedPreferencesManager.getInstance(); + final Set<String> garbageSubtypes = Set.of("null"); + manager.writeStringSet( + ChromePreferenceKeys.KEY_ZERO_SUGGEST_NATIVE_SUBTYPES_PREFIX.createKey(0), + garbageSubtypes); + + AutocompleteResult dataFromCache = CachedZeroSuggestionsManager.readFromCache(); + assertAutocompleteResultEquals(new AutocompleteResult(null, null), dataFromCache); + } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionBuilderForTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionBuilderForTest.java index d5aa6901..afc12a1 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionBuilderForTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionBuilderForTest.java
@@ -4,6 +4,8 @@ package org.chromium.chrome.browser.omnibox.suggestions; +import androidx.collection.ArraySet; + import org.chromium.chrome.browser.omnibox.MatchClassificationStyle; import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType; import org.chromium.components.omnibox.SuggestionAnswer; @@ -12,6 +14,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Set; /** * Utility class for all omnibox suggestions related tests that aids constructing of Omnibox @@ -20,6 +23,7 @@ public class OmniboxSuggestionBuilderForTest { // Fields below directly represent fields used in OmniboxSuggestion.java. private @OmniboxSuggestionType int mType; + private Set<Integer> mSubtypes; private boolean mIsSearchType; private String mDisplayText; private List<OmniboxSuggestion.MatchClassification> mDisplayTextClassifications; @@ -56,6 +60,7 @@ public OmniboxSuggestionBuilderForTest(@OmniboxSuggestionType int type) { mType = type; + mSubtypes = new ArraySet<>(); mDisplayTextClassifications = new ArrayList<>(); mDescriptionClassifications = new ArrayList<>(); mUrl = GURL.emptyGURL(); @@ -79,11 +84,11 @@ * @return New OmniboxSuggestion. */ public OmniboxSuggestion build() { - return new OmniboxSuggestion(mType, mIsSearchType, mRelevance, mTransition, mDisplayText, - mDisplayTextClassifications, mDescription, mDescriptionClassifications, mAnswer, - mFillIntoEdit, mUrl, mImageUrl, mImageDominantColor, mIsStarred, mIsDeletable, - mPostContentType, mPostData, mGroupId, mQueryTiles, mClipboardImageData, - mHasTabMatch); + return new OmniboxSuggestion(mType, mSubtypes, mIsSearchType, mRelevance, mTransition, + mDisplayText, mDisplayTextClassifications, mDescription, + mDescriptionClassifications, mAnswer, mFillIntoEdit, mUrl, mImageUrl, + mImageDominantColor, mIsStarred, mIsDeletable, mPostContentType, mPostData, + mGroupId, mQueryTiles, mClipboardImageData, mHasTabMatch); } /** @@ -220,4 +225,13 @@ mType = type; return this; } + + /** + * @param subtype Suggestion subtype. + * @return Omnibox suggestion builder. + */ + public OmniboxSuggestionBuilderForTest addSubtype(int subtype) { + mSubtypes.add(subtype); + return this; + } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessorUnitTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessorUnitTest.java index fb1d27d..9c8f14f 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessorUnitTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessorUnitTest.java
@@ -124,37 +124,37 @@ * Create Suggestion for test. * Do not use directly; use helper methods to create specific suggestion type instead. */ - private void createSuggestion(int type, boolean isSearch, boolean isBookmark, - boolean hasTabMatch, String title, String description) { - mSuggestion = OmniboxSuggestionBuilderForTest.searchWithType(type) - .setDisplayText(title) - .setDescription(description) - .setIsSearch(isSearch) - .setIsStarred(isBookmark) - .setHasTabMatch(hasTabMatch) - .build(); + private OmniboxSuggestionBuilderForTest createSuggestionBuilder(int type, String title) { + return OmniboxSuggestionBuilderForTest.searchWithType(type).setDisplayText(title); + } + + /** Create bookmark suggestion for test. */ + private void createBookmarkSuggestion(int type, String title) { + mSuggestion = + createSuggestionBuilder(type, title).setIsSearch(false).setIsStarred(true).build(); mModel = mProcessor.createModel(); mProcessor.populateModel(mSuggestion, mModel, 0); } - /** Create bookmark suggestion for test. */ - private void createBookmarkSuggestion(int type, String title, String description) { - createSuggestion(type, false, true, false, title, description); - } - /** Create search suggestion for test. */ - private void createSearchSuggestion(int type, String title, String description) { - createSuggestion(type, true, false, false, title, description); + private void createSearchSuggestion(int type, String title) { + mSuggestion = createSuggestionBuilder(type, title).setIsSearch(true).build(); + mModel = mProcessor.createModel(); + mProcessor.populateModel(mSuggestion, mModel, 0); } /** Create URL suggestion for test. */ - private void createUrlSuggestion(int type, String title, String description) { - createSuggestion(type, false, false, false, title, description); + private void createUrlSuggestion(int type, String title) { + mSuggestion = createSuggestionBuilder(type, title).setIsSearch(false).build(); + mModel = mProcessor.createModel(); + mProcessor.populateModel(mSuggestion, mModel, 0); } /** Create switch to tab suggestion for test. */ - private void createSwitchToTabSuggestion(int type, String title, String description) { - createSuggestion(type, false, false, true, title, description); + private void createSwitchToTabSuggestion(int type, String title) { + mSuggestion = createSuggestionBuilder(type, title).setHasTabMatch(true).build(); + mModel = mProcessor.createModel(); + mProcessor.populateModel(mSuggestion, mModel, 0); } private void assertSuggestionTypeAndIcon( @@ -195,7 +195,7 @@ mProcessor.onNativeInitialized(); for (int[] testCase : testCases) { - createSearchSuggestion(testCase[0], "", ""); + createSearchSuggestion(testCase[0], ""); Assert.assertTrue(mModel.get(SuggestionViewProperties.IS_SEARCH_SUGGESTION)); assertSuggestionTypeAndIcon(testCase[0], testCase[1]); } @@ -230,7 +230,7 @@ mProcessor.onNativeInitialized(); for (int[] testCase : testCases) { - createUrlSuggestion(testCase[0], "", ""); + createUrlSuggestion(testCase[0], ""); Assert.assertFalse(mModel.get(SuggestionViewProperties.IS_SEARCH_SUGGESTION)); assertSuggestionTypeAndIcon(testCase[0], testCase[1]); } @@ -265,7 +265,7 @@ mProcessor.onNativeInitialized(); for (int[] testCase : testCases) { - createBookmarkSuggestion(testCase[0], "", ""); + createBookmarkSuggestion(testCase[0], ""); Assert.assertFalse(mModel.get(SuggestionViewProperties.IS_SEARCH_SUGGESTION)); assertSuggestionTypeAndIcon(testCase[0], testCase[1]); } @@ -274,15 +274,41 @@ @Test @SmallTest @UiThreadTest + @DisableFeatures({ChromeFeatureList.OMNIBOX_COMPACT_SUGGESTIONS, + ChromeFeatureList.OMNIBOX_SUGGESTIONS_WRAP_AROUND}) + public void + getSuggestionIconTypeForTrendingQueries() { + int[][] testCases = { + {OmniboxSuggestionType.URL_WHAT_YOU_TYPED, SuggestionIcon.TRENDS}, + {OmniboxSuggestionType.SEARCH_HISTORY, SuggestionIcon.HISTORY}, + {OmniboxSuggestionType.SEARCH_SUGGEST, SuggestionIcon.TRENDS}, + {OmniboxSuggestionType.SEARCH_SUGGEST_TAIL, SuggestionIcon.TRENDS}, + {OmniboxSuggestionType.SEARCH_SUGGEST_PERSONALIZED, SuggestionIcon.HISTORY}, + {OmniboxSuggestionType.VOICE_SUGGEST, SuggestionIcon.VOICE}, + }; + + mProcessor.onNativeInitialized(); + for (int[] testCase : testCases) { + mSuggestion = createSuggestionBuilder(testCase[0], "").addSubtype(143).build(); + mModel = mProcessor.createModel(); + mProcessor.populateModel(mSuggestion, mModel, 0); + Assert.assertTrue(mModel.get(SuggestionViewProperties.IS_SEARCH_SUGGESTION)); + assertSuggestionTypeAndIcon(testCase[0], testCase[1]); + } + } + + @Test + @SmallTest + @UiThreadTest public void refineIconNotShownForWhatYouTypedSuggestions() { final String typed = "Typed content"; doReturn(typed).when(mUrlBarText).getTextWithoutAutocomplete(); - createSearchSuggestion(OmniboxSuggestionType.URL_WHAT_YOU_TYPED, typed, ""); + createSearchSuggestion(OmniboxSuggestionType.URL_WHAT_YOU_TYPED, typed); PropertyModel model = mProcessor.createModel(); mProcessor.populateModel(mSuggestion, model, 0); Assert.assertNull(mModel.get(BaseSuggestionViewProperties.ACTIONS)); - createUrlSuggestion(OmniboxSuggestionType.URL_WHAT_YOU_TYPED, typed, ""); + createUrlSuggestion(OmniboxSuggestionType.URL_WHAT_YOU_TYPED, typed); mProcessor.populateModel(mSuggestion, model, 0); Assert.assertNull(mModel.get(BaseSuggestionViewProperties.ACTIONS)); } @@ -294,12 +320,12 @@ final String typed = "Typed conte"; final String refined = "Typed content"; doReturn(typed).when(mUrlBarText).getTextWithoutAutocomplete(); - createSearchSuggestion(OmniboxSuggestionType.URL_WHAT_YOU_TYPED, refined, ""); + createSearchSuggestion(OmniboxSuggestionType.URL_WHAT_YOU_TYPED, refined); PropertyModel model = mProcessor.createModel(); mProcessor.populateModel(mSuggestion, model, 0); Assert.assertNotNull(mModel.get(BaseSuggestionViewProperties.ACTIONS)); - createUrlSuggestion(OmniboxSuggestionType.URL_WHAT_YOU_TYPED, refined, ""); + createUrlSuggestion(OmniboxSuggestionType.URL_WHAT_YOU_TYPED, refined); mProcessor.populateModel(mSuggestion, model, 0); Assert.assertNotNull(mModel.get(BaseSuggestionViewProperties.ACTIONS)); @@ -315,7 +341,7 @@ @UiThreadTest public void switchTabIconShownForSwitchToTabSuggestions() { final String tabMatch = "tab match"; - createSwitchToTabSuggestion(OmniboxSuggestionType.URL_WHAT_YOU_TYPED, tabMatch, ""); + createSwitchToTabSuggestion(OmniboxSuggestionType.URL_WHAT_YOU_TYPED, tabMatch); PropertyModel model = mProcessor.createModel(); mProcessor.populateModel(mSuggestion, model, 0); Assert.assertNotNull(mModel.get(BaseSuggestionViewProperties.ACTIONS)); @@ -336,7 +362,7 @@ final ArgumentCaptor<LargeIconCallback> callback = ArgumentCaptor.forClass(LargeIconCallback.class); mProcessor.onNativeInitialized(); - createUrlSuggestion(OmniboxSuggestionType.URL_WHAT_YOU_TYPED, "", ""); + createUrlSuggestion(OmniboxSuggestionType.URL_WHAT_YOU_TYPED, ""); SuggestionDrawableState icon1 = mModel.get(BaseSuggestionViewProperties.ICON); Assert.assertNotNull(icon1); @@ -359,7 +385,7 @@ final ArgumentCaptor<LargeIconCallback> callback = ArgumentCaptor.forClass(LargeIconCallback.class); mProcessor.onNativeInitialized(); - createUrlSuggestion(OmniboxSuggestionType.URL_WHAT_YOU_TYPED, "", ""); + createUrlSuggestion(OmniboxSuggestionType.URL_WHAT_YOU_TYPED, ""); SuggestionDrawableState icon1 = mModel.get(BaseSuggestionViewProperties.ICON); Assert.assertNotNull(icon1); @@ -379,10 +405,10 @@ @EnableFeatures(ChromeFeatureList.OMNIBOX_SUGGESTIONS_WRAP_AROUND) public void searchSuggestions_searchQueriesCanWrapAroundWithFeatureEnabled() { mProcessor.onNativeInitialized(); - createSearchSuggestion(OmniboxSuggestionType.SEARCH_WHAT_YOU_TYPED, "", ""); + createSearchSuggestion(OmniboxSuggestionType.SEARCH_WHAT_YOU_TYPED, ""); Assert.assertEquals(mModel.get(SuggestionViewProperties.ALLOW_WRAP_AROUND), true); - createUrlSuggestion(OmniboxSuggestionType.URL_WHAT_YOU_TYPED, "", ""); + createUrlSuggestion(OmniboxSuggestionType.URL_WHAT_YOU_TYPED, ""); Assert.assertEquals(mModel.get(SuggestionViewProperties.ALLOW_WRAP_AROUND), false); } @@ -393,10 +419,10 @@ ChromeFeatureList.OMNIBOX_SUGGESTIONS_WRAP_AROUND}) public void searchSuggestions_searchQueriesDontWrapAroundWithFeatureDisabled() { mProcessor.onNativeInitialized(); - createSearchSuggestion(OmniboxSuggestionType.SEARCH_WHAT_YOU_TYPED, "", ""); + createSearchSuggestion(OmniboxSuggestionType.SEARCH_WHAT_YOU_TYPED, ""); Assert.assertEquals(mModel.get(SuggestionViewProperties.ALLOW_WRAP_AROUND), false); - createUrlSuggestion(OmniboxSuggestionType.URL_WHAT_YOU_TYPED, "", ""); + createUrlSuggestion(OmniboxSuggestionType.URL_WHAT_YOU_TYPED, ""); Assert.assertEquals(mModel.get(SuggestionViewProperties.ALLOW_WRAP_AROUND), false); } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/policy/CombinedPolicyProviderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/policy/CombinedPolicyProviderTest.java index c08081db1..52308a02 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/policy/CombinedPolicyProviderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/policy/CombinedPolicyProviderTest.java
@@ -19,9 +19,9 @@ import org.chromium.chrome.browser.tabmodel.TabModel; import org.chromium.chrome.test.ChromeActivityTestRule; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.components.policy.CombinedPolicyProvider; +import org.chromium.components.policy.PolicyProvider; import org.chromium.content_public.browser.test.util.TestThreadUtils; -import org.chromium.policy.CombinedPolicyProvider; -import org.chromium.policy.PolicyProvider; /** Instrumentation tests for {@link CombinedPolicyProvider} */ @RunWith(ChromeJUnit4ClassRunner.class)
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/search_engines/settings/SearchEngineSettingsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/search_engines/settings/SearchEngineSettingsTest.java index ad6c47a..d81acad 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/search_engines/settings/SearchEngineSettingsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/search_engines/settings/SearchEngineSettingsTest.java
@@ -31,13 +31,13 @@ import org.chromium.components.browser_ui.site_settings.WebsitePreferenceBridgeJni; import org.chromium.components.content_settings.ContentSettingValues; import org.chromium.components.content_settings.ContentSettingsType; +import org.chromium.components.policy.test.annotations.Policies; import org.chromium.components.search_engines.TemplateUrl; import org.chromium.components.search_engines.TemplateUrlService; import org.chromium.components.search_engines.TemplateUrlService.LoadListener; import org.chromium.content_public.browser.test.util.Criteria; import org.chromium.content_public.browser.test.util.CriteriaHelper; import org.chromium.content_public.browser.test.util.TestThreadUtils; -import org.chromium.policy.test.annotations.Policies; import java.util.List; import java.util.concurrent.ExecutionException;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/settings/SettingsActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/settings/SettingsActivityTest.java index 6ec9f0b5..ae550a7 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/settings/SettingsActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/settings/SettingsActivityTest.java
@@ -21,10 +21,10 @@ import org.chromium.chrome.browser.preferences.Pref; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.components.policy.test.annotations.Policies; import org.chromium.components.user_prefs.UserPrefs; import org.chromium.content_public.browser.test.util.CriteriaHelper; import org.chromium.content_public.browser.test.util.TestThreadUtils; -import org.chromium.policy.test.annotations.Policies; /** * Tests for the Settings menu.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SiteSettingsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SiteSettingsTest.java index 795cc977..2c9d106e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SiteSettingsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SiteSettingsTest.java
@@ -62,12 +62,12 @@ import org.chromium.components.embedder_support.browser_context.BrowserContextHandle; import org.chromium.components.embedder_support.util.Origin; import org.chromium.components.permissions.nfc.NfcSystemLevelSetting; +import org.chromium.components.policy.test.annotations.Policies; import org.chromium.components.user_prefs.UserPrefs; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.content_public.common.ContentSwitches; import org.chromium.device.geolocation.LocationProviderOverrider; import org.chromium.device.geolocation.MockLocationProvider; -import org.chromium.policy.test.annotations.Policies; import java.util.ArrayList; import java.util.Arrays;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/LocationBarModelTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/LocationBarModelTest.java index 4c346c8..ce5239f 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/LocationBarModelTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/LocationBarModelTest.java
@@ -19,6 +19,7 @@ import org.chromium.base.ContextUtils; import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeTabbedActivity; @@ -102,6 +103,7 @@ @Test @MediumTest + @DisabledTest(message = "crbug/1128073") public void testGetProfileOnNullTabInIncognito() { mActivityTestRule.startMainActivityOnBlankPage(); TestThreadUtils.runOnUiThreadBlocking(() -> { @@ -114,6 +116,7 @@ @Test @MediumTest + @DisabledTest(message = "crbug/1128073") public void testGetProfileOnMockTabInIncognito() { mActivityTestRule.startMainActivityOnBlankPage(); TestThreadUtils.runOnUiThreadBlocking(() -> { @@ -149,6 +152,7 @@ @Test @MediumTest + @DisabledTest(message = "crbug/1128073") public void testGetProfileOnMockTabInRegularCCT() { // Create an launch a regular CCT. Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(
diff --git a/chrome/android/junit/DEPS b/chrome/android/junit/DEPS index 03b76af..9f58c24 100644 --- a/chrome/android/junit/DEPS +++ b/chrome/android/junit/DEPS
@@ -7,6 +7,7 @@ "+chrome/android/java/src/org/chromium/chrome/browser/ssl/ChromeSecurityStateModelDelegate.java", "+chrome/browser/performance_hints/android/java", "+chrome/browser/profiles/android", + "+chrome/browser/share", "+chrome/browser/tab", "+chrome/browser/tabmodel", "+chrome/browser/thumbnail/generator/android/java",
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/firstrun/FirstRunAppRestrictionInfoTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/firstrun/FirstRunAppRestrictionInfoTest.java index 9330dd04..2d0a69b 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/firstrun/FirstRunAppRestrictionInfoTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/firstrun/FirstRunAppRestrictionInfoTest.java
@@ -29,8 +29,8 @@ import org.chromium.base.task.test.ShadowPostTask; import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.base.test.util.CallbackHelper; +import org.chromium.components.policy.PolicySwitches; import org.chromium.content_public.browser.test.util.TestThreadUtils; -import org.chromium.policy.PolicySwitches; import org.chromium.testing.local.CustomShadowUserManager; import java.util.Arrays;
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/send_tab_to_self/OWNERS b/chrome/android/junit/src/org/chromium/chrome/browser/send_tab_to_self/OWNERS deleted file mode 100644 index f8e745b..0000000 --- a/chrome/android/junit/src/org/chromium/chrome/browser/send_tab_to_self/OWNERS +++ /dev/null
@@ -1,3 +0,0 @@ -file://components/send_tab_to_self/OWNERS - -# COMPONENT: UI>Browser>Sharing \ No newline at end of file
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfShareActivityTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfShareActivityTest.java index 090e29c..b0292ef7 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfShareActivityTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfShareActivityTest.java
@@ -26,6 +26,9 @@ import org.chromium.chrome.browser.app.ChromeActivity; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.profiles.ProfileJni; +import org.chromium.chrome.browser.share.send_tab_to_self.SendTabToSelfAndroidBridge; +import org.chromium.chrome.browser.share.send_tab_to_self.SendTabToSelfAndroidBridgeJni; +import org.chromium.chrome.browser.share.send_tab_to_self.SendTabToSelfCoordinator; import org.chromium.chrome.browser.sync.AndroidSyncSettings; import org.chromium.chrome.browser.tab.Tab; import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent;
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt index a51c978e..acadc5c 100644 --- a/chrome/android/profiles/newest.txt +++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-87.0.4261.0_rc-r1-merged.afdo.bz2 +chromeos-chrome-amd64-87.0.4262.0_rc-r1-merged.afdo.bz2
diff --git a/chrome/app/android/chrome_main_delegate_android.cc b/chrome/app/android/chrome_main_delegate_android.cc index 7af2f11..6943ab4 100644 --- a/chrome/app/android/chrome_main_delegate_android.cc +++ b/chrome/app/android/chrome_main_delegate_android.cc
@@ -14,7 +14,7 @@ #include "chrome/browser/android/chrome_startup_flags.h" #include "chrome/browser/android/metrics/uma_utils.h" #include "chrome/common/profiler/main_thread_stack_sampling_profiler.h" -#include "components/policy/core/browser/android/android_combined_policy_provider.h" +#include "components/policy/core/common/android/android_combined_policy_provider.h" #include "components/safe_browsing/buildflags.h" #include "components/startup_metric_utils/browser/startup_metric_utils.h" #include "content/public/browser/browser_main_runner.h"
diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc index 5780f0b3..ea8e1d4 100644 --- a/chrome/app/chrome_main_delegate.cc +++ b/chrome/app/chrome_main_delegate.cc
@@ -268,7 +268,6 @@ } else if (process_type == switches::kUtilityProcess || process_type == switches::kGpuProcess || process_type == switches::kCloudPrintServiceProcess || - process_type == service_manager::switches::kProcessTypeService || process_type == switches::kPpapiBrokerProcess) { score = content::kMiscOomScore; #if BUILDFLAG(ENABLE_NACL) @@ -277,8 +276,6 @@ score = content::kPluginOomScore; #endif } else if (process_type == service_manager::switches::kZygoteProcess || - process_type == - service_manager::switches::kProcessTypeServiceManager || process_type.empty()) { // For zygotes and unlabeled process types, we want to still make // them killable by the OOM killer. @@ -1238,16 +1235,6 @@ return g_chrome_content_utility_client.Pointer(); } -service_manager::ProcessType ChromeMainDelegate::OverrideProcessType() { - const auto& command_line = *base::CommandLine::ForCurrentProcess(); - if (command_line.GetSwitchValueASCII(switches::kProcessType) == - service_manager::switches::kProcessTypeService) { - // Don't mess with embedded service command lines. - return service_manager::ProcessType::kDefault; - } - return service_manager::ProcessType::kDefault; -} - void ChromeMainDelegate::PreCreateMainMessageLoop() { #if defined(OS_MAC) // Tell Cocoa to finish its initialization, which we want to do manually
diff --git a/chrome/app/chrome_main_delegate.h b/chrome/app/chrome_main_delegate.h index c32e99ab..1056536 100644 --- a/chrome/app/chrome_main_delegate.h +++ b/chrome/app/chrome_main_delegate.h
@@ -58,7 +58,6 @@ delegates) override; void ZygoteForked() override; #endif - service_manager::ProcessType OverrideProcessType() override; void PreCreateMainMessageLoop() override; void PostEarlyInitialization(bool is_running_tests) override; bool ShouldCreateFeatureList() override;
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index 2846051..8853fad8 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -4573,9 +4573,6 @@ <message name="IDS_CROSTINI_TERMINAL_STATUS_INSTALL_IMAGE_LOADER" desc="Text shown in the crostini terminal when it is checking whether the virtual machine component is installed"> Checking the virtual machine </message> - <message name="IDS_CROSTINI_TERMINAL_STATUS_START_CONCIERGE" desc="Text shown in the crostini terminal when it is starting the VM controller"> - Starting the virtual machine controller - </message> <message name="IDS_CROSTINI_TERMINAL_STATUS_CREATE_DISK_IMAGE" desc="Text shown in the crostini terminal when it is checking whether the VM image is installed"> Checking the virtual machine image </message>
diff --git a/chrome/app/chromeos_strings_grdp/IDS_CROSTINI_TERMINAL_STATUS_START_CONCIERGE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_CROSTINI_TERMINAL_STATUS_START_CONCIERGE.png.sha1 deleted file mode 100644 index c2dd105..0000000 --- a/chrome/app/chromeos_strings_grdp/IDS_CROSTINI_TERMINAL_STATUS_START_CONCIERGE.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -d5dfef986211c69d831ac4515dd9defdc772cfc3 \ No newline at end of file
diff --git a/chrome/app/vector_icons/BUILD.gn b/chrome/app/vector_icons/BUILD.gn index efe3364..e10625e8 100644 --- a/chrome/app/vector_icons/BUILD.gn +++ b/chrome/app/vector_icons/BUILD.gn
@@ -190,6 +190,7 @@ "notification_vpn.icon", "notification_wifi_off.icon", "notification_wifi.icon", + "person_add.icon", "shutdown_guest_os.icon", "warning_badge_circle.icon", ]
diff --git a/chrome/app/vector_icons/person_add.icon b/chrome/app/vector_icons/person_add.icon new file mode 100644 index 0000000..e6efbd4 --- /dev/null +++ b/chrome/app/vector_icons/person_add.icon
@@ -0,0 +1,32 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +CANVAS_DIMENSIONS, 24, +MOVE_TO, 15, 12, +R_CUBIC_TO, 2.21f, 0, 4, -1.79f, 4, -4, +R_CUBIC_TO, 0, -2.21f, -1.79f, -4, -4, -4, +R_CUBIC_TO, -2.21f, 0, -4, 1.79f, -4, 4, +R_CUBIC_TO, 0, 2.21f, 1.79f, 4, 4, 4, +CLOSE, +R_MOVE_TO, -9, -2, +V_LINE_TO, 7, +H_LINE_TO, 4, +R_V_LINE_TO, 3, +H_LINE_TO, 1, +R_V_LINE_TO, 2, +R_H_LINE_TO, 3, +R_V_LINE_TO, 3, +R_H_LINE_TO, 2, +R_V_LINE_TO, -3, +R_H_LINE_TO, 3, +R_V_LINE_TO, -2, +H_LINE_TO, 6, +CLOSE, +R_MOVE_TO, 9, 4, +R_CUBIC_TO, -2.67f, 0, -8, 1.34f, -8, 4, +R_V_LINE_TO, 2, +R_H_LINE_TO, 16, +R_V_LINE_TO, -2, +R_CUBIC_TO, 0, -2.66f, -5.33f, -4, -8, -4, +CLOSE
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index a1fd5cd..f110408 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -1695,6 +1695,8 @@ "storage/appcache_feature_prefs.h", "storage/durable_storage_permission_context.cc", "storage/durable_storage_permission_context.h", + "subresource_filter/ads_intervention_manager.cc", + "subresource_filter/ads_intervention_manager.h", "subresource_filter/chrome_subresource_filter_client.cc", "subresource_filter/chrome_subresource_filter_client.h", "subresource_filter/subresource_filter_content_settings_manager.cc", @@ -6029,7 +6031,6 @@ "//chrome/browser/ui/webui/chromeos/add_supervision:mojo_bindings_js", "//chrome/browser/ui/webui/chromeos/crostini_installer:mojo_bindings_js", "//chrome/browser/ui/webui/chromeos/crostini_upgrader:mojo_bindings_js", - "//chrome/browser/ui/webui/chromeos/file_manager:mojo_bindings_js", "//chrome/browser/ui/webui/chromeos/machine_learning:mojo_bindings_js", "//chrome/browser/ui/webui/settings/chromeos:mojom_js", ]
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 5fc83de..bbf4ef1 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -1351,55 +1351,88 @@ {"6 matches", kOmniboxMaxURLMatches6, base::size(kOmniboxMaxURLMatches6), nullptr}}; -const FeatureEntry::FeatureVariation kDynamicMaxAutocompleteVariations[] = { - { - "9 suggestions if 0 or less URLs", - (FeatureEntry::FeatureParam[]){ - {"OmniboxDynamicMaxAutocompleteUrlCutoff", "0"}, - {"OmniboxDynamicMaxAutocompleteIncreasedLimit", "9"}}, - 2, - nullptr, - }, - { - "9 suggestions if 1 or less URLs", - (FeatureEntry::FeatureParam[]){ - {"OmniboxDynamicMaxAutocompleteUrlCutoff", "1"}, - {"OmniboxDynamicMaxAutocompleteIncreasedLimit", "9"}}, - 2, - nullptr, - }, - { - "9 suggestions if 2 or less URLs", - (FeatureEntry::FeatureParam[]){ - {"OmniboxDynamicMaxAutocompleteUrlCutoff", "2"}, - {"OmniboxDynamicMaxAutocompleteIncreasedLimit", "9"}}, - 2, - nullptr, - }, - { - "10 suggestions if 0 or less URLs", - (FeatureEntry::FeatureParam[]){ - {"OmniboxDynamicMaxAutocompleteUrlCutoff", "0"}, - {"OmniboxDynamicMaxAutocompleteIncreasedLimit", "10"}}, - 2, - nullptr, - }, - { - "10 suggestions if 1 or less URLs", - (FeatureEntry::FeatureParam[]){ - {"OmniboxDynamicMaxAutocompleteUrlCutoff", "1"}, - {"OmniboxDynamicMaxAutocompleteIncreasedLimit", "10"}}, - 2, - nullptr, - }, - { - "10 suggestions if 2 or less URLs", - (FeatureEntry::FeatureParam[]){ - {"OmniboxDynamicMaxAutocompleteUrlCutoff", "2"}, - {"OmniboxDynamicMaxAutocompleteIncreasedLimit", "10"}}, - 2, - nullptr, - }}; +const FeatureEntry::FeatureVariation + kOmniboxDynamicMaxAutocompleteVariations[] = { + { + "9 suggestions if 0 or less URLs", + (FeatureEntry::FeatureParam[]){ + {"OmniboxDynamicMaxAutocompleteUrlCutoff", "0"}, + {"OmniboxDynamicMaxAutocompleteIncreasedLimit", "9"}}, + 2, + nullptr, + }, + { + "9 suggestions if 1 or less URLs", + (FeatureEntry::FeatureParam[]){ + {"OmniboxDynamicMaxAutocompleteUrlCutoff", "1"}, + {"OmniboxDynamicMaxAutocompleteIncreasedLimit", "9"}}, + 2, + nullptr, + }, + { + "9 suggestions if 2 or less URLs", + (FeatureEntry::FeatureParam[]){ + {"OmniboxDynamicMaxAutocompleteUrlCutoff", "2"}, + {"OmniboxDynamicMaxAutocompleteIncreasedLimit", "9"}}, + 2, + nullptr, + }, + { + "10 suggestions if 0 or less URLs", + (FeatureEntry::FeatureParam[]){ + {"OmniboxDynamicMaxAutocompleteUrlCutoff", "0"}, + {"OmniboxDynamicMaxAutocompleteIncreasedLimit", "10"}}, + 2, + nullptr, + }, + { + "10 suggestions if 1 or less URLs", + (FeatureEntry::FeatureParam[]){ + {"OmniboxDynamicMaxAutocompleteUrlCutoff", "1"}, + {"OmniboxDynamicMaxAutocompleteIncreasedLimit", "10"}}, + 2, + nullptr, + }, + { + "10 suggestions if 2 or less URLs", + (FeatureEntry::FeatureParam[]){ + {"OmniboxDynamicMaxAutocompleteUrlCutoff", "2"}, + {"OmniboxDynamicMaxAutocompleteIncreasedLimit", "10"}}, + 2, + nullptr, + }}; + +const FeatureEntry::FeatureVariation kOmniboxBubbleUrlSuggestionsVariations[] = + {{ + "Gap 200, Buffer 100", + (FeatureEntry::FeatureParam[]){ + {"OmniboxBubbleUrlSuggestionsAbsoluteGap", "200"}, + {"OmniboxBubbleUrlSuggestionsRelativeGap", "1"}, + {"OmniboxBubbleUrlSuggestionsAbsoluteBuffer", "100"}, + {"OmniboxBubbleUrlSuggestionsRelativeBuffer", "1"}}, + 4, + nullptr, + }, + { + "Gap 200, Buffer 200", + (FeatureEntry::FeatureParam[]){ + {"OmniboxBubbleUrlSuggestionsAbsoluteGap", "200"}, + {"OmniboxBubbleUrlSuggestionsRelativeGap", "1"}, + {"OmniboxBubbleUrlSuggestionsAbsoluteBuffer", "200"}, + {"OmniboxBubbleUrlSuggestionsRelativeBuffer", "1"}}, + 4, + nullptr, + }, + { + "Gap 400, Buffer 200", + (FeatureEntry::FeatureParam[]){ + {"OmniboxBubbleUrlSuggestionsAbsoluteGap", "400"}, + {"OmniboxBubbleUrlSuggestionsRelativeGap", "1"}, + {"OmniboxBubbleUrlSuggestionsAbsoluteBuffer", "200"}, + {"OmniboxBubbleUrlSuggestionsRelativeBuffer", "1"}}, + 4, + nullptr, + }}; const FeatureEntry::FeatureParam kMarkHttpAsDangerous[] = { {security_state::features::kMarkHttpAsFeatureParameterName, @@ -2547,6 +2580,10 @@ flag_descriptions::kAshEnableUnifiedDesktopName, flag_descriptions::kAshEnableUnifiedDesktopDescription, kOsCrOS, SINGLE_VALUE_TYPE(switches::kEnableUnifiedDesktop)}, + {"ash-enable-interactive-window-cycle-list", + flag_descriptions::kInteractiveWindowCycleList, + flag_descriptions::kInteractiveWindowCycleListDescription, kOsCrOS, + FEATURE_VALUE_TYPE(ash::features::kInteractiveWindowCycleList)}, {"bluetooth-aggressive-appearance-filter", flag_descriptions::kBluetoothAggressiveAppearanceFilterName, flag_descriptions::kBluetoothAggressiveAppearanceFilterDescription, @@ -3957,7 +3994,14 @@ flag_descriptions::kOmniboxDynamicMaxAutocompleteName, flag_descriptions::kOmniboxDynamicMaxAutocompleteDescription, kOsAll, FEATURE_WITH_PARAMS_VALUE_TYPE(omnibox::kDynamicMaxAutocomplete, - kDynamicMaxAutocompleteVariations, + kOmniboxDynamicMaxAutocompleteVariations, + "OmniboxBundledExperimentV1")}, + + {"omnibox-bubble-url-suggestions", + flag_descriptions::kOmniboxBubbleUrlSuggestionsName, + flag_descriptions::kOmniboxBubbleUrlSuggestionsDescription, kOsAll, + FEATURE_WITH_PARAMS_VALUE_TYPE(omnibox::kBubbleUrlSuggestions, + kOmniboxBubbleUrlSuggestionsVariations, "OmniboxBundledExperimentV1")}, {"omnibox-ui-swap-title-and-url", @@ -5884,11 +5928,6 @@ FEATURE_VALUE_TYPE(chromeos::features::kUseWallpaperStagingUrl)}, #endif // defined(OS_CHROMEOS) - {"passive-mixed-content-warning", - flag_descriptions::kPassiveMixedContentWarningName, - flag_descriptions::kPassiveMixedContentWarningDescription, kOsAll, - FEATURE_VALUE_TYPE(security_state::features::kPassiveMixedContentWarning)}, - {"autofill-enable-virtual-card", flag_descriptions::kAutofillEnableVirtualCardName, flag_descriptions::kAutofillEnableVirtualCardDescription, kOsDesktop, @@ -6325,6 +6364,11 @@ {"enable-tab-search", flag_descriptions::kEnableTabSearchName, flag_descriptions::kEnableTabSearchDescription, kOsCrOS, FEATURE_VALUE_TYPE(features::kTabSearch)}, + + {"enable-tab-search-fixed-entrypoint", + flag_descriptions::kEnableTabSearchFixedEntrypointName, + flag_descriptions::kEnableTabSearchFixedEntrypointDescription, kOsCrOS, + FEATURE_VALUE_TYPE(features::kTabSearchFixedEntrypoint)}, #endif // BUILDFLAG(ENABLE_TAB_SEARCH) #if defined(OS_ANDROID) @@ -6409,6 +6453,17 @@ FEATURE_VALUE_TYPE(language::kDetailedLanguageSettings)}, #endif + {"sync-autofill-wallet-offer-data", + flag_descriptions::kSyncAutofillWalletOfferDataName, + flag_descriptions::kSyncAutofillWalletOfferDataDescription, kOsAll, + FEATURE_VALUE_TYPE(switches::kSyncAutofillWalletOfferData)}, + +#if defined(OS_CHROMEOS) + {"enable-holding-space", flag_descriptions::kHoldingSpaceName, + flag_descriptions::kHoldingSpaceDescription, kOsCrOS, + FEATURE_VALUE_TYPE(ash::features::kTemporaryHoldingSpace)}, +#endif + // NOTE: Adding a new flag requires adding a corresponding entry to enum // "LoginCustomFlags" in tools/metrics/histograms/enums.xml. See "Flag // Histograms" in tools/metrics/histograms/README.md (run the
diff --git a/chrome/browser/android/feed/v2/feed_image_fetch_client.cc b/chrome/browser/android/feed/v2/feed_image_fetch_client.cc index 906cad70..4e9b520e 100644 --- a/chrome/browser/android/feed/v2/feed_image_fetch_client.cc +++ b/chrome/browser/android/feed/v2/feed_image_fetch_client.cc
@@ -11,6 +11,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" #include "components/feed/core/v2/public/feed_service.h" +#include "components/feed/core/v2/public/feed_stream_api.h" #include "components/feed/core/v2/public/types.h" using base::android::JavaParamRef; @@ -26,9 +27,21 @@ base::android::ToJavaByteArray(env, response.response_bytes)); } +FeedStreamApi* GetFeedStream() { + Profile* profile = ProfileManager::GetLastUsedProfile(); + if (!profile) + return nullptr; + + FeedService* feed_service = FeedServiceFactory::GetForBrowserContext(profile); + if (!feed_service) + return nullptr; + + return feed_service->GetStream(); +} + } // namespace -void JNI_FeedImageFetchClient_SendRequest( +jint JNI_FeedImageFetchClient_SendRequest( JNIEnv* env, const JavaParamRef<jstring>& j_url, const JavaParamRef<jobject>& j_response_callback) { @@ -36,17 +49,24 @@ // with OnFetchFinished. base::android::ScopedJavaGlobalRef<jobject> callback(j_response_callback); - Profile* profile = ProfileManager::GetLastUsedProfile(); - if (!profile) - return OnFetchFinished(env, std::move(callback), {}); + FeedStreamApi* stream = GetFeedStream(); + if (!stream) { + OnFetchFinished(env, std::move(callback), {}); + return 0; + } - FeedService* feed_service = FeedServiceFactory::GetForBrowserContext(profile); - if (!feed_service || !feed_service->GetStream()) - return OnFetchFinished(env, std::move(callback), {}); + return stream + ->FetchImage(GURL(base::android::ConvertJavaStringToUTF8(env, j_url)), + base::BindOnce(&OnFetchFinished, env, std::move(callback))) + .GetUnsafeValue(); +} - feed_service->GetStream()->FetchImage( - GURL(base::android::ConvertJavaStringToUTF8(env, j_url)), - base::BindOnce(&OnFetchFinished, env, std::move(callback))); +void JNI_FeedImageFetchClient_Cancel(JNIEnv* env, jint j_request_id) { + FeedStreamApi* stream = GetFeedStream(); + if (!stream) + return; + + stream->CancelImageFetch(ImageFetchId::FromUnsafeValue(j_request_id)); } } // namespace feed
diff --git a/chrome/browser/android/omnibox/autocomplete_controller_android.cc b/chrome/browser/android/omnibox/autocomplete_controller_android.cc index 4a03f01..c38f57b7 100644 --- a/chrome/browser/android/omnibox/autocomplete_controller_android.cc +++ b/chrome/browser/android/omnibox/autocomplete_controller_android.cc
@@ -541,7 +541,7 @@ for (size_t i = match.contents_class.size(); i > 0; --i) { ACMatchClassification classification(match.contents_class[i - 1]); int updated_offset = std::max( - 0 , static_cast<int>(classification.offset) - match_offset_delta); + 0, static_cast<int>(classification.offset) - match_offset_delta); out_classifications->insert( out_classifications->begin(), ACMatchClassification(updated_offset, classification.style)); @@ -618,10 +618,11 @@ BookmarkModel* bookmark_model = BookmarkModelFactory::GetForBrowserContext(profile_); + const std::vector<int> subtypes(match.subtypes.begin(), match.subtypes.end()); return Java_AutocompleteController_buildOmniboxSuggestion( - env, match.type, AutocompleteMatch::IsSearchType(match.type), - match.relevance, match.transition, jcontents, - ToJavaIntArray(env, contents_class_offsets), + env, match.type, ToJavaIntArray(env, subtypes), + AutocompleteMatch::IsSearchType(match.type), match.relevance, + match.transition, jcontents, ToJavaIntArray(env, contents_class_offsets), ToJavaIntArray(env, contents_class_styles), description, ToJavaIntArray(env, description_class_offsets), ToJavaIntArray(env, description_class_styles), janswer, fill_into_edit,
diff --git a/chrome/browser/android/send_tab_to_self/android_notification_handler.cc b/chrome/browser/android/send_tab_to_self/android_notification_handler.cc index b4f3a2c7..ad0bcd4 100644 --- a/chrome/browser/android/send_tab_to_self/android_notification_handler.cc +++ b/chrome/browser/android/send_tab_to_self/android_notification_handler.cc
@@ -10,8 +10,8 @@ #include "base/android/jni_string.h" #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" -#include "chrome/android/chrome_jni_headers/NotificationManager_jni.h" #include "chrome/android/chrome_jni_headers/SendTabToSelfNotificationReceiver_jni.h" +#include "chrome/browser/share/android/jni_headers/NotificationManager_jni.h" #include "components/send_tab_to_self/send_tab_to_self_entry.h" using base::android::AttachCurrentThread;
diff --git a/chrome/browser/android/send_tab_to_self/send_tab_to_self_android_bridge.cc b/chrome/browser/android/send_tab_to_self/send_tab_to_self_android_bridge.cc index bdeede8b..65d75f9 100644 --- a/chrome/browser/android/send_tab_to_self/send_tab_to_self_android_bridge.cc +++ b/chrome/browser/android/send_tab_to_self/send_tab_to_self_android_bridge.cc
@@ -9,14 +9,14 @@ #include "base/android/jni_string.h" #include "base/metrics/histogram_macros.h" #include "base/time/time.h" -#include "chrome/android/chrome_jni_headers/SendTabToSelfAndroidBridge_jni.h" -#include "chrome/android/chrome_jni_headers/TargetDeviceInfo_jni.h" #include "chrome/browser/android/send_tab_to_self/send_tab_to_self_entry_bridge.h" #include "chrome/browser/android/send_tab_to_self/send_tab_to_self_infobar.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_android.h" #include "chrome/browser/send_tab_to_self/send_tab_to_self_client_service_factory.h" #include "chrome/browser/send_tab_to_self/send_tab_to_self_util.h" +#include "chrome/browser/share/android/jni_headers/SendTabToSelfAndroidBridge_jni.h" +#include "chrome/browser/share/android/jni_headers/TargetDeviceInfo_jni.h" #include "chrome/browser/sync/send_tab_to_self_sync_service_factory.h" #include "components/send_tab_to_self/send_tab_to_self_entry.h" #include "components/send_tab_to_self/send_tab_to_self_infobar_delegate.h"
diff --git a/chrome/browser/android/send_tab_to_self/send_tab_to_self_entry_bridge.cc b/chrome/browser/android/send_tab_to_self/send_tab_to_self_entry_bridge.cc index c393a239..2e3f69a3 100644 --- a/chrome/browser/android/send_tab_to_self/send_tab_to_self_entry_bridge.cc +++ b/chrome/browser/android/send_tab_to_self/send_tab_to_self_entry_bridge.cc
@@ -6,7 +6,7 @@ #include "base/android/jni_array.h" #include "base/android/jni_string.h" -#include "chrome/android/chrome_jni_headers/SendTabToSelfEntry_jni.h" +#include "chrome/browser/share/android/jni_headers/SendTabToSelfEntry_jni.h" #include "components/send_tab_to_self/send_tab_to_self_entry.h" using base::android::AttachCurrentThread;
diff --git a/chrome/browser/android/send_tab_to_self/send_tab_to_self_infobar.cc b/chrome/browser/android/send_tab_to_self/send_tab_to_self_infobar.cc index 1d9c74f..1fb2f11 100644 --- a/chrome/browser/android/send_tab_to_self/send_tab_to_self_infobar.cc +++ b/chrome/browser/android/send_tab_to_self/send_tab_to_self_infobar.cc
@@ -12,10 +12,10 @@ #include "base/callback.h" #include "base/callback_helpers.h" #include "base/memory/ptr_util.h" -#include "chrome/android/chrome_jni_headers/SendTabToSelfInfoBar_jni.h" #include "chrome/browser/android/resource_mapper.h" #include "chrome/browser/android/tab_android.h" #include "chrome/browser/infobars/infobar_service.h" +#include "chrome/browser/share/android/jni_headers/SendTabToSelfInfoBar_jni.h" #include "components/infobars/android/infobar_android.h" #include "components/infobars/core/infobar_delegate.h" #include "content/public/browser/web_contents.h"
diff --git a/chrome/browser/android/send_tab_to_self/send_tab_to_self_model_observer_bridge.cc b/chrome/browser/android/send_tab_to_self/send_tab_to_self_model_observer_bridge.cc index a4af1dd8..2250342 100644 --- a/chrome/browser/android/send_tab_to_self/send_tab_to_self_model_observer_bridge.cc +++ b/chrome/browser/android/send_tab_to_self/send_tab_to_self_model_observer_bridge.cc
@@ -10,10 +10,10 @@ #include "base/android/jni_array.h" #include "base/android/jni_string.h" #include "base/time/time.h" -#include "chrome/android/chrome_jni_headers/SendTabToSelfModelObserverBridge_jni.h" #include "chrome/browser/android/send_tab_to_self/send_tab_to_self_entry_bridge.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_android.h" +#include "chrome/browser/share/android/jni_headers/SendTabToSelfModelObserverBridge_jni.h" #include "chrome/browser/sync/send_tab_to_self_sync_service_factory.h" #include "components/send_tab_to_self/send_tab_to_self_entry.h" #include "components/send_tab_to_self/send_tab_to_self_model.h"
diff --git a/chrome/browser/apps/app_service/app_icon_factory.cc b/chrome/browser/apps/app_service/app_icon_factory.cc index fbd423e2b..0ee32277 100644 --- a/chrome/browser/apps/app_service/app_icon_factory.cc +++ b/chrome/browser/apps/app_service/app_icon_factory.cc
@@ -4,7 +4,6 @@ #include "chrome/browser/apps/app_service/app_icon_factory.h" -#include <map> #include <memory> #include <utility> @@ -76,7 +75,6 @@ using SizeToImageSkiaRep = std::map<int, gfx::ImageSkiaRep>; using ScaleToImageSkiaReps = std::map<float, SizeToImageSkiaRep>; using MaskImageSkiaReps = std::pair<SkBitmap, ScaleToImageSkiaReps>; -using ScaleToSize = std::map<float, int>; MaskImageSkiaReps& GetMaskResourceIconCache() { static base::NoDestructor<MaskImageSkiaReps> mask_cache; @@ -119,8 +117,8 @@ return image_rep; } -ScaleToSize GetScaleToSize(const gfx::ImageSkia& image_skia) { - ScaleToSize scale_to_size; +apps::ScaleToSize GetScaleToSize(const gfx::ImageSkia& image_skia) { + apps::ScaleToSize scale_to_size; if (image_skia.image_reps().empty()) { scale_to_size[1.0f] = image_skia.size().width(); } else { @@ -131,18 +129,6 @@ return scale_to_size; } -gfx::ImageSkia LoadMaskImage(const ScaleToSize& scale_to_size) { - gfx::ImageSkia mask_image; - for (const auto& it : scale_to_size) { - float scale = it.first; - int size_hint_in_dip = it.second; - mask_image.AddRepresentation( - GetMaskAsImageSkiaRep(scale, size_hint_in_dip)); - } - - return mask_image; -} - bool IsConsistentPixelSize(const gfx::ImageSkiaRep& rep, const gfx::ImageSkia& image_skia) { // The pixel size calculation method must be consistent with @@ -1105,6 +1091,18 @@ #if defined(OS_CHROMEOS) +gfx::ImageSkia LoadMaskImage(const ScaleToSize& scale_to_size) { + gfx::ImageSkia mask_image; + for (const auto& it : scale_to_size) { + float scale = it.first; + int size_hint_in_dip = it.second; + mask_image.AddRepresentation( + GetMaskAsImageSkiaRep(scale, size_hint_in_dip)); + } + + return mask_image; +} + gfx::ImageSkia ApplyBackgroundAndMask(const gfx::ImageSkia& image) { return gfx::ImageSkiaOperations::CreateButtonBackground( SK_ColorWHITE, image, LoadMaskImage(GetScaleToSize(image)));
diff --git a/chrome/browser/apps/app_service/app_icon_factory.h b/chrome/browser/apps/app_service/app_icon_factory.h index c22c656..5aae37c 100644 --- a/chrome/browser/apps/app_service/app_icon_factory.h +++ b/chrome/browser/apps/app_service/app_icon_factory.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_APPS_APP_SERVICE_APP_ICON_FACTORY_H_ #define CHROME_BROWSER_APPS_APP_SERVICE_APP_ICON_FACTORY_H_ +#include <map> #include <string> #include <vector> @@ -26,6 +27,8 @@ namespace apps { +using ScaleToSize = std::map<float, int>; + // A bitwise-or of icon post-processing effects. // // It derives from a uint32_t because it needs to be the same size as the @@ -88,6 +91,8 @@ float rep_icon_scale); #if defined(OS_CHROMEOS) +gfx::ImageSkia LoadMaskImage(const ScaleToSize& scale_to_size); + gfx::ImageSkia ApplyBackgroundAndMask(const gfx::ImageSkia& image); gfx::ImageSkia CompositeImagesAndApplyMask(
diff --git a/chrome/browser/apps/app_service/arc_apps.cc b/chrome/browser/apps/app_service/arc_apps.cc index c109b726..da866a0f 100644 --- a/chrome/browser/apps/app_service/arc_apps.cc +++ b/chrome/browser/apps/app_service/arc_apps.cc
@@ -213,7 +213,7 @@ arc::mojom::IntentInfoPtr CreateArcIntent(apps::mojom::IntentPtr intent) { arc::mojom::IntentInfoPtr arc_intent; - if (!intent->url.has_value()) { + if (!intent->url.has_value() && !intent->share_text.has_value()) { return arc_intent; } arc_intent = arc::mojom::IntentInfo::New(); @@ -230,7 +230,14 @@ } else { arc_intent->action = arc::kIntentActionView; } - arc_intent->data = intent->url->spec(); + if (intent->url.has_value()) { + arc_intent->data = intent->url->spec(); + } + if (intent->share_text.has_value()) { + arc_intent->extras = base::flat_map<std::string, std::string>(); + arc_intent->extras.value().insert(std::make_pair( + "android.intent.extra.TEXT", intent->share_text.value())); + } return arc_intent; } @@ -761,14 +768,8 @@ !intent->activity_name.value().empty()) { activity->activity_name = intent->activity_name.value(); } - // At the moment, the only case we have mime_type field set is to share - // files, in this case, convert the file urls to content urls and use - // arc file system instance to launch the app with files. - if (intent->mime_type.has_value()) { - if (!intent->file_urls.has_value()) { - LOG(ERROR) << "Share files failed, share intent is not valid"; - return; - } + + if (intent->mime_type.has_value() && intent->file_urls.has_value()) { file_manager::util::ConvertToContentUrls( apps::GetFileSystemURL(profile_, intent->file_urls.value()), base::BindOnce(&OnContentUrlResolved, std::move(intent),
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index 189ac6ad..bec641be 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd
@@ -279,12 +279,6 @@ <include name="IDR_DRIVE_INTERNALS_HTML" file="resources\chromeos\drive_internals.html" flattenhtml="true" type="BINDATA" /> <include name="IDR_DRIVE_INTERNALS_JS" file="resources\chromeos\drive_internals.js" type="BINDATA" /> - <include name="IDR_FILE_MANAGER_CSS" file="resources\chromeos\file_manager\file_manager.css" type="BINDATA" /> - <include name="IDR_FILE_MANAGER_HTML" file="resources\chromeos\file_manager\file_manager.html" flattenhtml="true" type="BINDATA" /> - <include name="IDR_FILE_MANAGER_JS" file="resources\chromeos\file_manager\file_manager.js" type="BINDATA" /> - <include name="IDR_FILE_MANAGER_MOJO_LITE_JS" file="${root_gen_dir}\chrome\browser\ui\webui\chromeos\file_manager\file_manager.mojom-lite.js" use_base_dir="false" type="BINDATA" /> - <include name="IDR_FILE_MANAGER_PROXY_JS" file="resources\chromeos\file_manager\browser_proxy.js" type="BINDATA" /> - <include name="IDR_GUEST_SESSION_TAB_HTML" file="resources\chromeos\guest_session_tab.html" flattenhtml="true" type="BINDATA" /> <!-- Note: mobile_setup_ui.cc does not support compressed resources. -->
diff --git a/chrome/browser/chrome_browser_interface_binders.cc b/chrome/browser/chrome_browser_interface_binders.cc index 9b4140a..5f41a86 100644 --- a/chrome/browser/chrome_browser_interface_binders.cc +++ b/chrome/browser/chrome_browser_interface_binders.cc
@@ -154,8 +154,6 @@ #include "chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_ui.h" #include "chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader.mojom.h" #include "chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_ui.h" -#include "chrome/browser/ui/webui/chromeos/file_manager/file_manager.mojom.h" -#include "chrome/browser/ui/webui/chromeos/file_manager/file_manager_ui.h" #include "chrome/browser/ui/webui/chromeos/internet_config_dialog.h" #include "chrome/browser/ui/webui/chromeos/internet_detail_dialog.h" #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h" @@ -169,6 +167,8 @@ #include "chrome/browser/ui/webui/settings/chromeos/search/user_action_recorder.mojom.h" #include "chromeos/components/camera_app_ui/camera_app_helper.mojom.h" #include "chromeos/components/camera_app_ui/camera_app_ui.h" +#include "chromeos/components/file_manager/file_manager.mojom.h" +#include "chromeos/components/file_manager/file_manager_ui.h" #include "chromeos/components/help_app_ui/help_app_ui.h" #include "chromeos/components/help_app_ui/help_app_ui.mojom.h" #include "chromeos/components/media_app_ui/media_app_ui.h"
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index d50d68cf..ab7b345 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -2839,12 +2839,16 @@ if (!is_official_build) { deps += [ + "//chromeos/components/file_manager:file_manager_ui", "//chromeos/components/sample_system_web_app_ui", "//chromeos/components/telemetry_extension_ui", + "//chromeos/resources:file_manager_resources_grit", "//chromeos/resources:sample_system_web_app_resources_grit", "//chromeos/resources:telemetry_extension_resources", ] sources += [ + "web_applications/file_manager_web_app_info.cc", + "web_applications/file_manager_web_app_info.h", "web_applications/sample_system_web_app_info.cc", "web_applications/sample_system_web_app_info.h", "web_applications/telemetry_extension_web_app_info.cc", @@ -3873,7 +3877,9 @@ "//chrome/browser/chromeos", "//chromeos/dbus:dbus", "//chromeos/tpm", + "//components:components_tests_pak", "//third_party/libprotobuf-mutator", + "//ui/resources:ui_test_pak", ] }
diff --git a/chrome/browser/chromeos/arc/accessibility/accessibility_node_info_data_wrapper.cc b/chrome/browser/chromeos/arc/accessibility/accessibility_node_info_data_wrapper.cc index 77ed102..c24fff50 100644 --- a/chrome/browser/chromeos/arc/accessibility/accessibility_node_info_data_wrapper.cc +++ b/chrome/browser/chromeos/arc/accessibility/accessibility_node_info_data_wrapper.cc
@@ -70,7 +70,7 @@ } bool AccessibilityNodeInfoDataWrapper::IsIgnored() const { - if (!tree_source_->IsScreenReaderMode()) + if (!tree_source_->UseFullFocusMode()) return !IsImportantInAndroid(); if (!IsImportantInAndroid() || !HasImportantProperty()) @@ -294,7 +294,7 @@ #undef MAP_STATE - const bool focusable = tree_source_->IsScreenReaderMode() + const bool focusable = tree_source_->UseFullFocusMode() ? IsAccessibilityFocusableContainer() : GetProperty(AXBooleanProperty::FOCUSABLE); if (focusable) @@ -537,7 +537,7 @@ // If a node is accessibility focusable, but has no name, the name should be // computed from its descendants. - if (names.empty() && tree_source_->IsScreenReaderMode() && + if (names.empty() && tree_source_->UseFullFocusMode() && IsAccessibilityFocusableContainer()) ComputeNameFromContents(&names);
diff --git a/chrome/browser/chromeos/arc/accessibility/accessibility_node_info_data_wrapper_unittest.cc b/chrome/browser/chromeos/arc/accessibility/accessibility_node_info_data_wrapper_unittest.cc index 0429686e..1bca8b8 100644 --- a/chrome/browser/chromeos/arc/accessibility/accessibility_node_info_data_wrapper_unittest.cc +++ b/chrome/browser/chromeos/arc/accessibility/accessibility_node_info_data_wrapper_unittest.cc
@@ -119,18 +119,16 @@ } // AXTreeSourceArc::Delegate overrides. - bool IsScreenReaderEnabled() const override { return screen_reader_enabled_; } + bool UseFullFocusMode() const override { return full_focus_mode_; } void OnAction(const ui::AXActionData& data) const override {} - void set_screen_reader_mode(bool enabled) { - screen_reader_enabled_ = enabled; - } + void set_full_focus_mode(bool enabled) { full_focus_mode_ = enabled; } AXTreeSourceArc* tree_source() { return tree_source_.get(); } private: const std::unique_ptr<TestAXTreeSourceArc> tree_source_; - bool screen_reader_enabled_ = true; + bool full_focus_mode_ = true; }; TEST_F(AccessibilityNodeInfoDataWrapperTest, Name) { @@ -219,7 +217,7 @@ SetProperty(&child2, AXStringProperty::TEXT, "child2 label text"); // If the screen reader mode is off, do not compute from descendants. - set_screen_reader_mode(false); + set_full_focus_mode(false); ui::AXNodeData data = CallSerialize(root_wrapper); std::string name; @@ -240,7 +238,7 @@ // Enable screen reader. // Compute the name of the clickable node from descendants, and ignore them. - set_screen_reader_mode(true); + set_full_focus_mode(true); data = CallSerialize(root_wrapper); ASSERT_TRUE(
diff --git a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.cc b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.cc index 6025368..5e36c31 100644 --- a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.cc +++ b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.cc
@@ -517,8 +517,8 @@ base::Unretained(this), data)); } -bool ArcAccessibilityHelperBridge::IsScreenReaderEnabled() const { - return is_screen_reader_enabled_; +bool ArcAccessibilityHelperBridge::UseFullFocusMode() const { + return use_full_focus_mode_; } void ArcAccessibilityHelperBridge::OnTaskDestroyed(int32_t task_id) { @@ -729,8 +729,8 @@ is_focus_highlight_enabled_ = accessibility_manager->IsFocusHighlightEnabled(); - is_screen_reader_enabled_ = accessibility_manager->IsSwitchAccessEnabled() || - accessibility_manager->IsSpokenFeedbackEnabled(); + use_full_focus_mode_ = accessibility_manager->IsSwitchAccessEnabled() || + accessibility_manager->IsSpokenFeedbackEnabled(); bool add_activation_observer = filter_type_ == arc::mojom::AccessibilityFilterType::ALL;
diff --git a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.h b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.h index e32059f..4f7d49b 100644 --- a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.h +++ b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.h
@@ -98,7 +98,7 @@ // AXTreeSourceArc::Delegate overrides. void OnAction(const ui::AXActionData& data) const override; - bool IsScreenReaderEnabled() const override; + bool UseFullFocusMode() const override; // ArcAppListPrefs::Observer overrides. void OnTaskDestroyed(int32_t task_id) override; @@ -178,7 +178,7 @@ bool activation_observer_added_ = false; bool is_focus_highlight_enabled_ = false; - bool is_screen_reader_enabled_ = false; + bool use_full_focus_mode_ = false; Profile* const profile_; ArcBridgeService* const arc_bridge_service_; TreeMap trees_;
diff --git a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_util.cc b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_util.cc index bd9556cc..3f735624 100644 --- a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_util.cc +++ b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_util.cc
@@ -121,6 +121,8 @@ case ax::mojom::Action::kDoDefault: return arc::mojom::AccessibilityActionType::CLICK; case ax::mojom::Action::kFocus: + // Fallthrough + case ax::mojom::Action::kSetSequentialFocusNavigationStartingPoint: return arc::mojom::AccessibilityActionType::ACCESSIBILITY_FOCUS; case ax::mojom::Action::kScrollToMakeVisible: return arc::mojom::AccessibilityActionType::SHOW_ON_SCREEN;
diff --git a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc index 96831b3..f2237a6 100644 --- a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc +++ b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc
@@ -81,8 +81,8 @@ GetAutomationEventRouter()->DispatchGetTextLocationDataResult(data, rect); } -bool AXTreeSourceArc::IsScreenReaderMode() const { - return delegate_->IsScreenReaderEnabled(); +bool AXTreeSourceArc::UseFullFocusMode() const { + return delegate_->UseFullFocusMode(); } void AXTreeSourceArc::InvalidateTree() { @@ -376,6 +376,7 @@ } bool AXTreeSourceArc::UpdateAndroidFocusedId(const AXEventData& event_data) { + // TODO(hirokisato): Handle CLEAR_ACCESSIBILITY_FOCUS event. if (event_data.event_type == AXEventType::VIEW_FOCUSED) { AccessibilityInfoDataWrapper* source_node = GetFromId(event_data.source_id); if (source_node && source_node->IsVisibleToUser()) { @@ -385,6 +386,11 @@ if (IsValid(adjusted_node)) android_focused_id_ = adjusted_node->GetId(); } + } else if (event_data.event_type == AXEventType::VIEW_ACCESSIBILITY_FOCUSED && + UseFullFocusMode()) { + AccessibilityInfoDataWrapper* source_node = GetFromId(event_data.source_id); + if (source_node && source_node->IsVisibleToUser()) + android_focused_id_ = source_node->GetId(); } else if (event_data.event_type == AXEventType::VIEW_SELECTED) { // In Android, VIEW_SELECTED event is dispatched in the two cases below: // 1. Changing a value in ProgressBar or TimePicker in ARC P. @@ -411,8 +417,23 @@ // The event of WINDOW_STATE_CHANGED is fired only once for each window // change and use it as a trigger to move the a11y focus to the first node. AccessibilityInfoDataWrapper* source_node = GetFromId(event_data.source_id); - AccessibilityInfoDataWrapper* new_focus = - FindFirstFocusableNode(source_node); + AccessibilityInfoDataWrapper* new_focus = nullptr; + + // If the current window has ever been visited in the current task, try + // focus on the last focus node in this window. + // We do it for WINDOW_STATE_CHANGED event from a window or a root node. + bool from_root_or_window = (source_node && !source_node->IsNode()) || + IsRootOfNodeTree(event_data.source_id); + auto itr = root_window_id_to_last_focus_node_id_.find(*root_id_); + if (from_root_or_window && + itr != root_window_id_to_last_focus_node_id_.end()) { + new_focus = GetFromId(itr->second); + } + + // Otherwise, try focus on the first focusable node. + if (!IsValid(new_focus)) + new_focus = FindFirstFocusableNode(GetFromId(event_data.source_id)); + if (IsValid(new_focus)) android_focused_id_ = new_focus->GetId(); } @@ -423,6 +444,12 @@ android_focused_id_ = root_id_; } + if (android_focused_id_.has_value()) { + root_window_id_to_last_focus_node_id_[*root_id_] = *android_focused_id_; + } else { + root_window_id_to_last_focus_node_id_.erase(*root_id_); + } + AccessibilityInfoDataWrapper* focused_node = android_focused_id_.has_value() ? GetFromId(*android_focused_id_) : nullptr;
diff --git a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.h b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.h index 61338ad..7c76dc52 100644 --- a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.h +++ b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.h
@@ -42,7 +42,7 @@ class Delegate { public: virtual void OnAction(const ui::AXActionData& data) const = 0; - virtual bool IsScreenReaderEnabled() const = 0; + virtual bool UseFullFocusMode() const = 0; }; AXTreeSourceArc(Delegate* delegate, float device_scale_factor); @@ -64,7 +64,9 @@ // When it is enabled, this class exposes an accessibility tree optimized for // screen readers such as ChromeVox and SwitchAccess. This intends to have the // navigation order and focusabilities similar to TalkBack. - bool IsScreenReaderMode() const; + // Also, when it is enabled, the accessibility focus in Android is exposed as + // the focus of this tree. + bool UseFullFocusMode() const; // Returns true if the node id is the root of the node tree (which can have a // parent window). @@ -121,10 +123,14 @@ AccessibilityInfoDataWrapper* GetSelectedNodeInfoFromAdapterView( const mojom::AccessibilityEventData& event_data) const; - // Update android_focused_id_ from given AccessibilityEventData. - // Returns true if it is successfully updated to existing node. - // Returns false if we don't dispatch the processing event to chrome - // automation. + // Updates android_focused_id_ from given AccessibilityEventData. + // Having this method, |android_focused_id_| is one of these: + // - input focus in Android + // - accessibility focus in Android + // - the chrome automation client's internal focus (via set sequential focus + // action and replying accessibility focus event from Android). + // This returns false if we don't want to dispatch the processing + // event to chrome automation. Otherwise, this returns true. bool UpdateAndroidFocusedId(const mojom::AccessibilityEventData& event_data); void UpdateAXNameCache(AccessibilityInfoDataWrapper* source_node, @@ -173,6 +179,9 @@ std::map<int32_t, std::string> cached_names_; std::map<int32_t, ax::mojom::Role> cached_roles_; + // Cache of mapping from the root window id to the last focused node id. + std::map<int32_t, int32_t> root_window_id_to_last_focus_node_id_; + // Mapping from Chrome node ID to its cached computed bounds. // This simplifies bounds calculations. std::map<int32_t, gfx::Rect> computed_bounds_;
diff --git a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc_unittest.cc b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc_unittest.cc index b9f9eca..6c0b73e2 100644 --- a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc_unittest.cc +++ b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc_unittest.cc
@@ -198,11 +198,9 @@ EXPECT_EQ(expected, tree_text.substr(first_new_line)); } - void set_screen_reader_mode(bool enabled) { - screen_reader_enabled_ = enabled; - } + void set_full_focus_mode(bool enabled) { full_focus_mode_ = enabled; } - bool IsScreenReaderEnabled() const override { return screen_reader_enabled_; } + bool UseFullFocusMode() const override { return full_focus_mode_; } private: void OnAction(const ui::AXActionData& data) const override {} @@ -210,7 +208,7 @@ const std::unique_ptr<MockAutomationEventRouter> router_; const std::unique_ptr<AXTreeSourceArc> tree_source_; - bool screen_reader_enabled_ = false; + bool full_focus_mode_ = false; DISALLOW_COPY_AND_ASSIGN(AXTreeSourceArcTest); }; @@ -715,9 +713,7 @@ TEST_F(AXTreeSourceArcTest, OnWindowStateChangedEvent) { auto event = AXEventData::New(); - event->source_id = 1; // node1. event->task_id = 1; - event->event_type = AXEventType::WINDOW_STATE_CHANGED; event->window_data = std::vector<mojom::AccessibilityWindowInfoDataPtr>(); event->window_data->push_back(AXWindowInfoData::New()); @@ -735,7 +731,8 @@ event->node_data.push_back(AXNodeInfoData::New()); AXNodeInfoData* node1 = event->node_data.back().get(); node1->id = 1; - SetProperty(node1, AXIntListProperty::CHILD_NODE_IDS, std::vector<int>({2})); + SetProperty(node1, AXIntListProperty::CHILD_NODE_IDS, + std::vector<int>({2, 3})); SetProperty(node1, AXBooleanProperty::IMPORTANCE, true); SetProperty(node1, AXBooleanProperty::VISIBLE_TO_USER, true); @@ -744,16 +741,63 @@ node2->id = 2; SetProperty(node2, AXBooleanProperty::IMPORTANCE, true); SetProperty(node2, AXBooleanProperty::VISIBLE_TO_USER, true); - SetProperty(node2, AXStringProperty::TEXT, "sample string."); + SetProperty(node2, AXStringProperty::TEXT, "sample string node2."); + event->node_data.push_back(AXNodeInfoData::New()); + AXNodeInfoData* node3 = event->node_data.back().get(); + node3->id = 3; + SetProperty(node3, AXBooleanProperty::IMPORTANCE, true); + SetProperty(node3, AXBooleanProperty::VISIBLE_TO_USER, true); + SetProperty(node3, AXStringProperty::TEXT, "sample string node3."); + + // Focus will be on the first accessible node (node2). + event->event_type = AXEventType::WINDOW_STATE_CHANGED; + event->source_id = root->id; CallNotifyAccessibilityEvent(event.get()); ui::AXTreeData data; - // Focus is now at the first accessible node (node2). EXPECT_TRUE(CallGetTreeData(&data)); EXPECT_EQ(node2->id, data.focus_id); - EXPECT_EQ(1, GetDispatchedEventCount(ax::mojom::Event::kFocus)); + // focus moved to node3 for some reason. + event->event_type = AXEventType::VIEW_FOCUSED; + event->source_id = node3->id; + CallNotifyAccessibilityEvent(event.get()); + + EXPECT_TRUE(CallGetTreeData(&data)); + EXPECT_EQ(node3->id, data.focus_id); + + // after moved the focus on the window, keep the same focus on + // WINDOW_STATE_CHANGED event. + event->event_type = AXEventType::WINDOW_STATE_CHANGED; + event->source_id = root->id; + CallNotifyAccessibilityEvent(event.get()); + + EXPECT_TRUE(CallGetTreeData(&data)); + EXPECT_EQ(node3->id, data.focus_id); + + // Simulate opening another window in this task. + // This is the same as new WINDOW_STATE_CHANGED event, so focus is at the + // first accessible node (node2). + root_window->window_id = 200; + event->event_type = AXEventType::WINDOW_STATE_CHANGED; + event->source_id = node1->id; + CallNotifyAccessibilityEvent(event.get()); + + EXPECT_TRUE(CallGetTreeData(&data)); + EXPECT_EQ(node2->id, data.focus_id); + + // Simulate closing the second window and coming back to the first window. + // The focus back to the last focus node, which is node3. + root_window->window_id = 100; + event->event_type = AXEventType::WINDOW_STATE_CHANGED; + event->source_id = root->id; + CallNotifyAccessibilityEvent(event.get()); + + EXPECT_TRUE(CallGetTreeData(&data)); + EXPECT_EQ(node3->id, data.focus_id); + + EXPECT_EQ(5, GetDispatchedEventCount(ax::mojom::Event::kFocus)); } TEST_F(AXTreeSourceArcTest, OnFocusEvent) { @@ -801,14 +845,26 @@ EXPECT_TRUE(CallGetTreeData(&data)); EXPECT_EQ(node2->id, data.focus_id); - // Chrome should focus to node2, even if Android sends focus on List. + // Chrome should focus to node1, even if Android sends focus on List. event->source_id = root->id; CallNotifyAccessibilityEvent(event.get()); EXPECT_TRUE(CallGetTreeData(&data)); EXPECT_EQ(node1->id, data.focus_id); - EXPECT_EQ(2, GetDispatchedEventCount(ax::mojom::Event::kFocus)); + // VIEW_ACCESSIBILITY_FOCUSED event also updates the focus in screen reader + // mode. + set_full_focus_mode(true); + SetProperty(node1, AXBooleanProperty::ACCESSIBILITY_FOCUSED, false); + SetProperty(node2, AXBooleanProperty::ACCESSIBILITY_FOCUSED, true); + event->event_type = AXEventType::VIEW_ACCESSIBILITY_FOCUSED; + event->source_id = node2->id; + CallNotifyAccessibilityEvent(event.get()); + + EXPECT_TRUE(CallGetTreeData(&data)); + EXPECT_EQ(node2->id, data.focus_id); + + EXPECT_EQ(3, GetDispatchedEventCount(ax::mojom::Event::kFocus)); } TEST_F(AXTreeSourceArcTest, OnDrawerOpened) { @@ -912,7 +968,7 @@ // |node2| is ignored by default because // AXBooleanProperty::IMPORTANCE has a default false value. - set_screen_reader_mode(true); + set_full_focus_mode(true); CallNotifyAccessibilityEvent(event.get()); EXPECT_EQ(1, GetDispatchedEventCount(ax::mojom::Event::kFocus));
diff --git a/chrome/browser/chromeos/concierge_helper_service.cc b/chrome/browser/chromeos/concierge_helper_service.cc index 38b98eb..8abed5d 100644 --- a/chrome/browser/chromeos/concierge_helper_service.cc +++ b/chrome/browser/chromeos/concierge_helper_service.cc
@@ -18,13 +18,6 @@ namespace chromeos { namespace { -void OnStartConcierge(bool started) { - if (started) - VLOG(1) << "Concierge D-Bus service successfully started"; - else - LOG(ERROR) << "Unable to start Concierge D-Bus service"; -} - void OnSetVmCpuRestriction( base::Optional<vm_tools::concierge::SetVmCpuRestrictionResponse> response) { if (!response || !response->success()) { @@ -33,18 +26,6 @@ } } -// Starts Concierge DBus service through debugd. If the service is already -// running, this request will be ignored. -void StartConcierge() { - auto* client = DBusThreadManager::Get()->GetDebugDaemonClient(); - if (!client) { - LOG(WARNING) << "DebugDaemonClient is not available"; - OnStartConcierge(false); - return; - } - client->StartConcierge(base::BindOnce(&OnStartConcierge)); -} - // Adds a callback to be run when Concierge DBus service becomes available. // If the service is already available, runs the callback immediately. void WaitForConciergeToBeAvailable( @@ -103,9 +84,7 @@ return ConciergeHelperServiceFactory::GetForBrowserContext(context); } -ConciergeHelperService::ConciergeHelperService() { - StartConcierge(); -} +ConciergeHelperService::ConciergeHelperService() = default; void ConciergeHelperService::SetArcVmCpuRestriction(bool do_restrict) { MakeRestrictionRequest(vm_tools::concierge::CPU_CGROUP_ARCVM, do_restrict);
diff --git a/chrome/browser/chromeos/concierge_helper_service_unittest.cc b/chrome/browser/chromeos/concierge_helper_service_unittest.cc index 9d5f2a9e..fac19b2e 100644 --- a/chrome/browser/chromeos/concierge_helper_service_unittest.cc +++ b/chrome/browser/chromeos/concierge_helper_service_unittest.cc
@@ -11,7 +11,6 @@ #include "chrome/test/base/testing_profile.h" #include "chromeos/dbus/concierge/concierge_service.pb.h" #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/debug_daemon/fake_debug_daemon_client.h" #include "chromeos/dbus/fake_concierge_client.h" #include "content/public/test/browser_task_environment.h" #include "dbus/bus.h" @@ -20,24 +19,6 @@ namespace chromeos { -class TestDebugDaemonClient : public FakeDebugDaemonClient { - public: - TestDebugDaemonClient() = default; - ~TestDebugDaemonClient() override = default; - - void StartConcierge(ConciergeCallback callback) override { - ++start_concierge_called_; - FakeDebugDaemonClient::StartConcierge(std::move(callback)); - } - - size_t start_concierge_called() const { return start_concierge_called_; } - - private: - size_t start_concierge_called_{0}; - - DISALLOW_COPY_AND_ASSIGN(TestDebugDaemonClient); -}; - class TestConciergeClient : public FakeConciergeClient { public: TestConciergeClient() = default; @@ -96,7 +77,6 @@ // testing::Test: void SetUp() override { auto setter = DBusThreadManager::GetSetterForTesting(); - setter->SetDebugDaemonClient(std::make_unique<TestDebugDaemonClient>()); setter->SetConciergeClient(std::make_unique<TestConciergeClient>()); service_ = ConciergeHelperService::GetForBrowserContext(&profile_); } @@ -111,11 +91,6 @@ DBusThreadManager::Get()->GetConciergeClient()); } - TestDebugDaemonClient* fake_debug_client() { - return static_cast<TestDebugDaemonClient*>( - DBusThreadManager::Get()->GetDebugDaemonClient()); - } - content::BrowserTaskEnvironment* task_environment() { return &task_environment_; } @@ -128,12 +103,6 @@ DISALLOW_COPY_AND_ASSIGN(ConciergeHelperServiceTest); }; -// Tests that ConciergeHelperService can be constructed and destructed. Also, -// check that ConciergeHelperService starts Concierge on construction. -TEST_F(ConciergeHelperServiceTest, TestConstructDestruct) { - EXPECT_EQ(1U, fake_debug_client()->start_concierge_called()); -} - // Tests that ConciergeHelperService makes cpu restriction requests correctly. TEST_F(ConciergeHelperServiceTest, TestSetVmCpuRestriction) { vm_tools::concierge::SetVmCpuRestrictionResponse response;
diff --git a/chrome/browser/chromeos/crostini/crostini_disk.cc b/chrome/browser/chromeos/crostini/crostini_disk.cc index 225174f..8ea4a8c6 100644 --- a/chrome/browser/chromeos/crostini/crostini_disk.cc +++ b/chrome/browser/chromeos/crostini/crostini_disk.cc
@@ -73,26 +73,15 @@ base::BindOnce(&OnAmountOfFreeDiskSpace, std::move(callback), profile, std::move(vm_name))); } else { - VLOG(1) << "Starting concierge"; // Since we only care about the disk's current size and whether it's a // sparse disk, we claim there's plenty of free space available to prevent // error conditions in |OnCrostiniSufficientlyRunning|. constexpr int64_t kFakeAvailableDiskBytes = kDiskHeadroomBytes + kRecommendedDiskSizeBytes; - CrostiniManager::GetForProfile(profile)->StartConcierge(base::BindOnce( - [](OnceDiskInfoCallback callback, Profile* profile, std::string vm_name, - bool success) { - if (!success) { - LOG(ERROR) << "Failed to start concierge"; - std::move(callback).Run(nullptr); - return; - } - OnCrostiniSufficientlyRunning( - std::move(callback), profile, std::move(vm_name), - kFakeAvailableDiskBytes, CrostiniResult::SUCCESS); - }, - std::move(callback), profile, std::move(vm_name))); + OnCrostiniSufficientlyRunning(std::move(callback), profile, + std::move(vm_name), kFakeAvailableDiskBytes, + CrostiniResult::SUCCESS); } }
diff --git a/chrome/browser/chromeos/crostini/crostini_installer.cc b/chrome/browser/chromeos/crostini/crostini_installer.cc index 8de0de66..9faad08a 100644 --- a/chrome/browser/chromeos/crostini/crostini_installer.cc +++ b/chrome/browser/chromeos/crostini/crostini_installer.cc
@@ -113,8 +113,6 @@ return SetupResult::kSuccess; case InstallerError::kErrorLoadingTermina: return SetupResult::kErrorLoadingTermina; - case InstallerError::kErrorStartingConcierge: - return SetupResult::kErrorStartingConcierge; case InstallerError::kErrorCreatingDiskImage: return SetupResult::kErrorCreatingDiskImage; case InstallerError::kErrorStartingTermina: @@ -149,8 +147,6 @@ return SetupResult::kUserCancelledStart; case InstallerState::kInstallImageLoader: return SetupResult::kUserCancelledInstallImageLoader; - case InstallerState::kStartConcierge: - return SetupResult::kUserCancelledStartConcierge; case InstallerState::kCreateDiskImage: return SetupResult::kUserCancelledCreateDiskImage; case InstallerState::kStartTerminaVm: @@ -326,15 +322,6 @@ } return; } - UpdateInstallingState(InstallerState::kStartConcierge); -} - -void CrostiniInstaller::OnConciergeStarted(bool success) { - DCHECK_EQ(installing_state_, InstallerState::kStartConcierge); - if (!success) { - HandleError(InstallerError::kErrorStartingConcierge); - return; - } UpdateInstallingState(InstallerState::kCreateDiskImage); } @@ -499,12 +486,8 @@ state_end_mark = 0.20; state_max_time = base::TimeDelta::FromSeconds(30); break; - case InstallerState::kStartConcierge: - state_start_mark = 0.20; - state_end_mark = 0.21; - break; case InstallerState::kCreateDiskImage: - state_start_mark = 0.21; + state_start_mark = 0.20; state_end_mark = 0.22; break; case InstallerState::kStartTerminaVm:
diff --git a/chrome/browser/chromeos/crostini/crostini_installer.h b/chrome/browser/chromeos/crostini/crostini_installer.h index ce26ed5..ce38ef5f 100644 --- a/chrome/browser/chromeos/crostini/crostini_installer.h +++ b/chrome/browser/chromeos/crostini/crostini_installer.h
@@ -37,7 +37,7 @@ // kUserCancelled = 1, kSuccess = 2, kErrorLoadingTermina = 3, - kErrorStartingConcierge = 4, + // kErrorStartingConcierge = 4, kErrorCreatingDiskImage = 5, kErrorStartingTermina = 6, kErrorStartingContainer = 7, @@ -48,7 +48,7 @@ kUserCancelledStart = 12, kUserCancelledInstallImageLoader = 13, - kUserCancelledStartConcierge = 14, + // kUserCancelledStartConcierge = 14, kUserCancelledCreateDiskImage = 15, kUserCancelledStartTerminaVm = 16, kUserCancelledCreateContainer = 17, @@ -88,7 +88,6 @@ // CrostiniManager::RestartObserver: void OnStageStarted(crostini::mojom::InstallerState stage) override; void OnComponentLoaded(crostini::CrostiniResult result) override; - void OnConciergeStarted(bool success) override; void OnDiskImageCreated(bool success, vm_tools::concierge::DiskImageStatus status, int64_t disk_size_available) override;
diff --git a/chrome/browser/chromeos/crostini/crostini_manager.cc b/chrome/browser/chromeos/crostini/crostini_manager.cc index 903c98f..7a7fce0 100644 --- a/chrome/browser/chromeos/crostini/crostini_manager.cc +++ b/chrome/browser/chromeos/crostini/crostini_manager.cc
@@ -333,23 +333,6 @@ } // Set the pref here, after we first successfully install something profile_->GetPrefs()->SetBoolean(crostini::prefs::kCrostiniEnabled, true); - StartStage(mojom::InstallerState::kStartConcierge); - crostini_manager_->StartConcierge(base::BindOnce( - &CrostiniRestarter::ConciergeStarted, weak_ptr_factory_.GetWeakPtr())); - } - - void ConciergeStarted(bool is_started) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - for (auto& observer : observer_list_) { - observer.OnConciergeStarted(is_started); - } - if (ReturnEarlyIfAborted()) { - return; - } - if (!is_started) { - FinishRestart(CrostiniResult::CONCIERGE_START_FAILED); - return; - } // Allow concierge to choose an appropriate disk image size. int64_t disk_size_bytes = options_.disk_size_bytes.value_or(0); @@ -1044,34 +1027,6 @@ termina_installer_.Uninstall(std::move(callback)); } -void CrostiniManager::StartConcierge(BoolCallback callback) { - VLOG(1) << "Starting Concierge service"; - chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()->StartConcierge( - base::BindOnce(&CrostiniManager::OnStartConcierge, - weak_ptr_factory_.GetWeakPtr(), std::move(callback))); -} - -void CrostiniManager::OnStartConcierge(BoolCallback callback, bool success) { - if (!success) { - LOG(ERROR) << "Failed to start Concierge service"; - std::move(callback).Run(success); - return; - } - VLOG(1) << "Concierge service started"; - VLOG(1) << "Waiting for Cicerone to announce availability."; - - GetCiceroneClient()->WaitForServiceToBeAvailable(std::move(callback)); -} - -void CrostiniManager::OnStopConcierge(BoolCallback callback, bool success) { - if (!success) { - LOG(ERROR) << "Failed to stop Concierge service"; - } else { - VLOG(1) << "Concierge service stopped"; - } - std::move(callback).Run(success); -} - void CrostiniManager::CreateDiskImage( const base::FilePath& disk_path, vm_tools::concierge::StorageLocation storage_location,
diff --git a/chrome/browser/chromeos/crostini/crostini_manager.h b/chrome/browser/chromeos/crostini/crostini_manager.h index 459f9c816..1ff400d 100644 --- a/chrome/browser/chromeos/crostini/crostini_manager.h +++ b/chrome/browser/chromeos/crostini/crostini_manager.h
@@ -189,7 +189,6 @@ virtual ~RestartObserver() {} virtual void OnStageStarted(mojom::InstallerState stage) {} virtual void OnComponentLoaded(CrostiniResult result) {} - virtual void OnConciergeStarted(bool success) {} virtual void OnDiskImageCreated(bool success, vm_tools::concierge::DiskImageStatus status, int64_t disk_size_bytes) {} @@ -243,10 +242,6 @@ // Unloads and removes termina. void UninstallTermina(BoolCallback callback); - // Starts the Concierge service. |callback| is called after the method call - // finishes. - void StartConcierge(BoolCallback callback); - // Checks the arguments for creating a new Termina VM disk image. Creates a // disk image for a Termina VM via ConciergeClient::CreateDiskImage. // |callback| is called if the arguments are bad, or after the method call @@ -703,14 +698,6 @@ base::Optional<vm_tools::concierge::GetVmEnterpriseReportingInfoResponse> response); - // Callback for CrostiniClient::StartConcierge. Called after the - // DebugDaemon service method finishes. - void OnStartConcierge(BoolCallback callback, bool success); - - // Callback for CrostiniClient::StopConcierge. Called after the - // DebugDaemon service method finishes. - void OnStopConcierge(BoolCallback callback, bool success); - // Callback for CiceroneClient::StartLxd. May indicate that LXD is still being // started in which case we will wait for OnStartLxdProgress events. void OnStartLxd(
diff --git a/chrome/browser/chromeos/crostini/crostini_manager_unittest.cc b/chrome/browser/chromeos/crostini/crostini_manager_unittest.cc index c80358bec..d694b35 100644 --- a/chrome/browser/chromeos/crostini/crostini_manager_unittest.cc +++ b/chrome/browser/chromeos/crostini/crostini_manager_unittest.cc
@@ -645,12 +645,6 @@ } } - void OnConciergeStarted(bool success) override { - if (abort_on_concierge_started_) { - Abort(); - } - } - void OnDiskImageCreated(bool success, vm_tools::concierge::DiskImageStatus status, int64_t disk_size_available) override { @@ -753,7 +747,6 @@ const CrostiniManager::RestartId uninitialized_id_ = CrostiniManager::kUninitializedRestartId; bool abort_on_component_loaded_ = false; - bool abort_on_concierge_started_ = false; bool abort_on_disk_image_created_ = false; bool abort_on_vm_started_ = false; bool abort_on_container_created_ = false; @@ -864,21 +857,6 @@ ExpectRestarterUmaCount(1); } -TEST_F(CrostiniManagerRestartTest, AbortOnConciergeStarted) { - abort_on_concierge_started_ = true; - restart_id_ = crostini_manager()->RestartCrostini( - container_id(), - base::BindOnce(&CrostiniManagerRestartTest::RestartCrostiniCallback, - base::Unretained(this), run_loop()->QuitClosure()), - this); - run_loop()->Run(); - EXPECT_FALSE(fake_concierge_client_->create_disk_image_called()); - EXPECT_FALSE(fake_concierge_client_->start_termina_vm_called()); - EXPECT_FALSE(fake_concierge_client_->get_container_ssh_keys_called()); - ExpectCrostiniRestartResult(CrostiniResult::RESTART_ABORTED); - ExpectRestarterUmaCount(1); -} - TEST_F(CrostiniManagerRestartTest, AbortOnDiskImageCreated) { abort_on_disk_image_created_ = true; restart_id_ = crostini_manager()->RestartCrostini(
diff --git a/chrome/browser/chromeos/crostini/crostini_remover.cc b/chrome/browser/chromeos/crostini/crostini_remover.cc index e3133ab..ed92fb8 100644 --- a/chrome/browser/chromeos/crostini/crostini_remover.cc +++ b/chrome/browser/chromeos/crostini/crostini_remover.cc
@@ -34,15 +34,6 @@ void CrostiniRemover::RemoveCrostini() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - CrostiniManager::GetForProfile(profile_)->StartConcierge( - base::BindOnce(&CrostiniRemover::OnConciergeStarted, this)); -} - -void CrostiniRemover::OnConciergeStarted(bool is_successful) { - if (!is_successful) { - std::move(callback_).Run(CrostiniResult::UNKNOWN_ERROR); - return; - } CrostiniManager::GetForProfile(profile_)->StopVm( vm_name_, base::BindOnce(&CrostiniRemover::StopVmFinished, this)); }
diff --git a/chrome/browser/chromeos/crostini/crostini_remover.h b/chrome/browser/chromeos/crostini/crostini_remover.h index afc43327..89c92c5 100644 --- a/chrome/browser/chromeos/crostini/crostini_remover.h +++ b/chrome/browser/chromeos/crostini/crostini_remover.h
@@ -22,7 +22,6 @@ ~CrostiniRemover(); - void OnConciergeStarted(bool is_successful); void StopVmFinished(crostini::CrostiniResult result); void DestroyDiskImageFinished(bool success); void UninstallTerminaFinished(bool success);
diff --git a/chrome/browser/chromeos/crostini/crostini_types.mojom b/chrome/browser/chromeos/crostini/crostini_types.mojom index 65efb5c..56420cda 100644 --- a/chrome/browser/chromeos/crostini/crostini_types.mojom +++ b/chrome/browser/chromeos/crostini/crostini_types.mojom
@@ -7,7 +7,6 @@ enum InstallerState { kStart, // Just started installation kInstallImageLoader, // Loading the Termina VM component. - kStartConcierge, // Starting the Concierge D-Bus client. kCreateDiskImage, // Creating the image for the Termina VM. kStartTerminaVm, // Starting the Termina VM. kCreateContainer, // Creating the container inside the Termina VM. @@ -21,7 +20,6 @@ enum InstallerError { kNone, kErrorLoadingTermina, - kErrorStartingConcierge, kErrorCreatingDiskImage, kErrorStartingTermina, kErrorStartingContainer,
diff --git a/chrome/browser/chromeos/policy/fuzzer/policy_fuzzer.cc b/chrome/browser/chromeos/policy/fuzzer/policy_fuzzer.cc index 000fc14..fab9677 100644 --- a/chrome/browser/chromeos/policy/fuzzer/policy_fuzzer.cc +++ b/chrome/browser/chromeos/policy/fuzzer/policy_fuzzer.cc
@@ -4,14 +4,17 @@ #include <string> +#include "base/at_exit.h" #include "base/check_op.h" #include "base/command_line.h" +#include "base/files/file_path.h" #include "base/files/scoped_temp_dir.h" #include "base/i18n/icu_util.h" #include "base/logging.h" #include "base/memory/weak_ptr.h" #include "base/path_service.h" #include "base/test/task_environment.h" +#include "build/build_config.h" #include "chrome/browser/chromeos/dbus/dbus_helper.h" #include "chrome/browser/chromeos/policy/device_policy_decoder_chromeos.h" #include "chrome/browser/chromeos/policy/fuzzer/policy_fuzzer.pb.h" @@ -31,6 +34,8 @@ #include "components/policy/core/common/policy_types.h" #include "components/prefs/pref_value_map.h" #include "testing/libfuzzer/proto/lpm_interface.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/base/ui_base_paths.h" namespace policy { @@ -44,9 +49,23 @@ CHECK(base::PathService::Override(chrome::DIR_USER_DATA, scoped_temp_dir.GetPath())); CHECK(base::i18n::InitializeICU()); + + ui::RegisterPathProvider(); + + base::FilePath ui_test_pak_path = + base::PathService::CheckedGet(ui::UI_TEST_PAK); + ui::ResourceBundle::InitSharedInstanceWithPakPath(ui_test_pak_path); + + base::FilePath pak_path = base::PathService::CheckedGet(base::DIR_MODULE); + ui::ResourceBundle::GetSharedInstance().AddDataPackFromPath( + pak_path.AppendASCII("components_tests_resources.pak"), + ui::SCALE_FACTOR_NONE); } + ~Environment() { ui::ResourceBundle::CleanupSharedInstance(); } + base::ScopedTempDir scoped_temp_dir; + base::AtExitManager exit_manager; }; struct PerInputEnvironment {
diff --git a/chrome/browser/chromeos/web_applications/file_manager_web_app_info.cc b/chrome/browser/chromeos/web_applications/file_manager_web_app_info.cc new file mode 100644 index 0000000..a19d544 --- /dev/null +++ b/chrome/browser/chromeos/web_applications/file_manager_web_app_info.cc
@@ -0,0 +1,30 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/web_applications/file_manager_web_app_info.h" + +#include "base/strings/string16.h" +#include "base/strings/utf_string_conversions.h" +#include "chrome/browser/chromeos/web_applications/system_web_app_install_utils.h" +#include "chrome/browser/web_applications/components/web_app_constants.h" +#include "chrome/common/web_application_info.h" +#include "chromeos/components/file_manager/url_constants.h" +#include "chromeos/grit/chromeos_file_manager_resources.h" +#include "third_party/blink/public/mojom/manifest/display_mode.mojom.h" + +std::unique_ptr<WebApplicationInfo> CreateWebAppInfoForFileManager() { + auto info = std::make_unique<WebApplicationInfo>(); + info->app_url = GURL(chromeos::file_manager::kChromeUIFileManagerURL); + info->scope = GURL(chromeos::file_manager::kChromeUIFileManagerURL); + // TODO(majewski): Fetch from a resource. + info->title = base::UTF8ToUTF16("File Manager"); + web_app::CreateIconInfoForSystemWebApp( + info->app_url, {{"icon192.png", 192, IDR_FILE_MANAGER_ICON_192}}, *info); + info->theme_color = 0xFF4285F4; + info->background_color = 0xFFFFFFFF; + info->display_mode = blink::mojom::DisplayMode::kStandalone; + info->open_as_window = true; + + return info; +}
diff --git a/chrome/browser/chromeos/web_applications/file_manager_web_app_info.h b/chrome/browser/chromeos/web_applications/file_manager_web_app_info.h new file mode 100644 index 0000000..4431b20 --- /dev/null +++ b/chrome/browser/chromeos/web_applications/file_manager_web_app_info.h
@@ -0,0 +1,19 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_WEB_APPLICATIONS_FILE_MANAGER_WEB_APP_INFO_H_ +#define CHROME_BROWSER_CHROMEOS_WEB_APPLICATIONS_FILE_MANAGER_WEB_APP_INFO_H_ + +#include <memory> + +#if defined(OFFICIAL_BUILD) +#error File Manager should only be included in unofficial builds. +#endif + +struct WebApplicationInfo; + +// Return a WebApplicationInfo used to install the app. +std::unique_ptr<WebApplicationInfo> CreateWebAppInfoForFileManager(); + +#endif // CHROME_BROWSER_CHROMEOS_WEB_APPLICATIONS_FILE_MANAGER_WEB_APP_INFO_H_
diff --git a/chrome/browser/chromeos/web_applications/media_app_integration_browsertest.cc b/chrome/browser/chromeos/web_applications/media_app_integration_browsertest.cc index b88f14c..aaca4c39 100644 --- a/chrome/browser/chromeos/web_applications/media_app_integration_browsertest.cc +++ b/chrome/browser/chromeos/web_applications/media_app_integration_browsertest.cc
@@ -21,9 +21,9 @@ #include "chromeos/components/media_app_ui/test/media_app_ui_browsertest.h" #include "chromeos/components/media_app_ui/url_constants.h" #include "chromeos/constants/chromeos_features.h" +#include "components/crash/content/browser/error_reporting/mock_crash_endpoint.h" #include "content/public/test/browser_test.h" #include "content/public/test/test_utils.h" -#include "extensions/browser/api/crash_report_private/mock_crash_endpoint.h" #include "extensions/browser/entry_info.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/common/features.h"
diff --git a/chrome/browser/extensions/api/terminal/crostini_startup_status.cc b/chrome/browser/extensions/api/terminal/crostini_startup_status.cc index 46b9d08..ccdbe0e7 100644 --- a/chrome/browser/extensions/api/terminal/crostini_startup_status.cc +++ b/chrome/browser/extensions/api/terminal/crostini_startup_status.cc
@@ -100,9 +100,6 @@ {InstallerState::kInstallImageLoader, l10n_util::GetStringUTF8( IDS_CROSTINI_TERMINAL_STATUS_INSTALL_IMAGE_LOADER)}, - {InstallerState::kStartConcierge, - l10n_util::GetStringUTF8( - IDS_CROSTINI_TERMINAL_STATUS_START_CONCIERGE)}, {InstallerState::kCreateDiskImage, l10n_util::GetStringUTF8( IDS_CROSTINI_TERMINAL_STATUS_CREATE_DISK_IMAGE)},
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index a22459e..4b61ffa 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -200,6 +200,11 @@ "expiry_milestone": -1 }, { + "name": "ash-enable-interactive-window-cycle-list", + "owners": [ "chinsenj", "tclaiborne" ], + "expiry_milestone": 91 + }, + { "name": "ash-enable-pip-rounded-corners", "owners": [ "edcourtney" ], "expiry_milestone": 90 @@ -1649,6 +1654,11 @@ "expiry_milestone": 76 }, { + "name": "enable-holding-space", + "owners": [ "//ash/public/cpp/holding_space/OWNERS" ], + "expiry_milestone": 90 + }, + { "name": "enable-home-page-location-policy", "owners": [ "wenyufu", "chrome-android-app@chromium.org" ], "expiry_milestone": 83 @@ -2189,6 +2199,11 @@ "expiry_milestone": 90 }, { + "name": "enable-tab-search-fixed-entrypoint", + "owners": [ "tluk@google.com", "robliao@google.com" ], + "expiry_milestone": 90 + }, + { "name": "enable-tab-switcher-on-return", "owners": [ "memex-team@google.com" ], "expiry_milestone": 90 @@ -3326,6 +3341,11 @@ "expiry_milestone": 95 }, { + "name": "omnibox-bubble-url-suggestions", + "owners": [ "manukh", "chrome-omnibox-team@google.com" ], + "expiry_milestone": 95 + }, + { "name": "omnibox-clobber-triggers-contextual-web-zero-suggest", "owners": [ "tommycli", "chrome-omnibox-team@google.com" ], "expiry_milestone": 95 @@ -4289,6 +4309,11 @@ "expiry_milestone": 88 }, { + "name": "sync-autofill-wallet-offer-data", + "owners": ["siyua", "treib"], + "expiry_milestone": 90 + }, + { "name": "sync-setup-friendly-settings", "owners": [ "msalama" ], "expiry_milestone": 84
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index ff5c05c..7fc0c82 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -1008,8 +1008,14 @@ #if BUILDFLAG(ENABLE_TAB_SEARCH) const char kEnableTabSearchName[] = "Enable Tab Search"; const char kEnableTabSearchDescription[] = - "Enable the Tab Search feature in Top Chrome UI, which will show a popup" + "Enable the Tab Search feature in Top Chrome UI, which will show a popup " "bubble that allows users to search over their currently open tabs."; +const char kEnableTabSearchFixedEntrypointName[] = + "Enable Tab Search fixed " + "entrypoint"; +const char kEnableTabSearchFixedEntrypointDescription[] = + "Enable the Tab " + "Search feature in Top Chrome UI having a fixed button position."; #endif // BUILDFLAG(ENABLE_TAB_SEARCH)"; const char kEnableTextFragmentAnchorName[] = "Enable Text Fragment Anchor."; @@ -1701,6 +1707,12 @@ "Configures the maximum number of autocomplete matches displayed in the " "Omnibox UI dynamically based on the number of URL matches."; +const char kOmniboxBubbleUrlSuggestionsName[] = + "Omnibox Bubble URL Suggestions"; +const char kOmniboxBubbleUrlSuggestionsDescription[] = + "Configures the bubbling of URL suggestions after grouping searches " + "above URLs."; + const char kOmniboxOnDeviceHeadSuggestionsIncognitoName[] = "Omnibox on device head suggestions (incognito only)"; const char kOmniboxOnDeviceHeadSuggestionsIncognitoDescription[] = @@ -1851,12 +1863,6 @@ "Forces wheel, and mousewheel event listeners on document level targets " "(which haven't requested otherwise) to be treated as passive."; -const char kPassiveMixedContentWarningName[] = - "Warning for Passive Mixed Content"; -const char kPassiveMixedContentWarningDescription[] = - "Causes a 'Not Secure' chip to be shown in the omnibox if a site contains " - "passive (aka optionally blockable) mixed content."; - const char kPasswordChangeInSettingsName[] = "Rework password change flow from settings"; const char kPasswordChangeInSettingsDescription[] = @@ -2241,6 +2247,11 @@ "Match Autofill suggestions based on substrings (token prefixes) rather " "than just prefixes."; +const char kSyncAutofillWalletOfferDataName[] = + "Enable syncing autofill offer data"; +const char kSyncAutofillWalletOfferDataDescription[] = + "When enabled, allows syncing autofill wallet offer data type."; + const char kSyncDeviceInfoInTransportModeName[] = "Enable syncing DeviceInfo in transport-only sync mode."; const char kSyncDeviceInfoInTransportModeDescription[] = @@ -4133,6 +4144,14 @@ "Hides media notifications for ARC apps. Requires " "#enable-media-session-notifications to be enabled."; +const char kHoldingSpaceName[] = + "Quick access to screenshots, downloads, and files test"; +const char kHoldingSpaceDescription[] = + "Enables quick access to screenshots, downloads, and important files which " + "aims to increase productivity by saving time. When enabled, access recent " + "screenshots and downloads from the shelf. Pin important files with the " + "Files App context menu to keep them one click away."; + const char kImeAssistAutocorrectName[] = "Enable assistive autocorrect"; const char kImeAssistAutocorrectDescription[] = "Enable assistive auto-correct features for native IME"; @@ -4175,6 +4194,12 @@ const char kIntentPickerPWAPersistenceDescription[] = "Allow user to always open with PWA in intent picker."; +const char kInteractiveWindowCycleList[] = + "Enable Alt-Tab interactivity improvements."; +const char kInteractiveWindowCycleListDescription[] = + "Adds mouse behavior, three-finger touchpad swipe, left/right " + "arrow navigation, and space/enter confirmation to Alt-Tab."; + const char kLacrosSupportName[] = "LaCrOS support"; const char kLacrosSupportDescription[] = "Support for the experimental lacros-chrome browser.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 7624291..a1bf42f 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -585,6 +585,8 @@ #if BUILDFLAG(ENABLE_TAB_SEARCH) extern const char kEnableTabSearchName[]; extern const char kEnableTabSearchDescription[]; +extern const char kEnableTabSearchFixedEntrypointName[]; +extern const char kEnableTabSearchFixedEntrypointDescription[]; #endif // BUILDFLAG(ENABLE_TAB_SEARCH) extern const char kEnableTextFragmentAnchorName[]; @@ -981,6 +983,9 @@ extern const char kOmniboxDynamicMaxAutocompleteName[]; extern const char kOmniboxDynamicMaxAutocompleteDescription[]; +extern const char kOmniboxBubbleUrlSuggestionsName[]; +extern const char kOmniboxBubbleUrlSuggestionsDescription[]; + extern const char kOmniboxOnDeviceHeadSuggestionsIncognitoName[]; extern const char kOmniboxOnDeviceHeadSuggestionsIncognitoDescription[]; @@ -1072,9 +1077,6 @@ extern const char kPassiveDocumentWheelEventListenersName[]; extern const char kPassiveDocumentWheelEventListenersDescription[]; -extern const char kPassiveMixedContentWarningName[]; -extern const char kPassiveMixedContentWarningDescription[]; - extern const char kPasswordImportName[]; extern const char kPasswordImportDescription[]; @@ -1288,6 +1290,9 @@ extern const char kSuggestionsWithSubStringMatchName[]; extern const char kSuggestionsWithSubStringMatchDescription[]; +extern const char kSyncAutofillWalletOfferDataName[]; +extern const char kSyncAutofillWalletOfferDataDescription[]; + extern const char kSyncDeviceInfoInTransportModeName[]; extern const char kSyncDeviceInfoInTransportModeDescription[]; @@ -2398,6 +2403,9 @@ extern const char kHideArcMediaNotificationsName[]; extern const char kHideArcMediaNotificationsDescription[]; +extern const char kHoldingSpaceName[]; +extern const char kHoldingSpaceDescription[]; + extern const char kImeAssistAutocorrectName[]; extern const char kImeAssistAutocorrectDescription[]; @@ -2428,6 +2436,9 @@ extern const char kIntentPickerPWAPersistenceName[]; extern const char kIntentPickerPWAPersistenceDescription[]; +extern const char kInteractiveWindowCycleList[]; +extern const char kInteractiveWindowCycleListDescription[]; + extern const char kLacrosSupportName[]; extern const char kLacrosSupportDescription[];
diff --git a/chrome/browser/metrics/family_user_metrics_provider.cc b/chrome/browser/metrics/family_user_metrics_provider.cc index 82e2516..1804dc1c 100644 --- a/chrome/browser/metrics/family_user_metrics_provider.cc +++ b/chrome/browser/metrics/family_user_metrics_provider.cc
@@ -31,6 +31,12 @@ g_browser_process->platform_part() ->GetAccountManagerFactory() ->GetAccountManager(profile->GetPath().value()); + DCHECK(account_manager); + if (!account_manager->IsInitialized()) { + base::UmaHistogramEnumeration(kFamilyUserLogSegmentHistogramName, + LogSegment::kOther); + return; + } // Calls the callback immediately and not asynchronously. account_manager->GetAccounts(base::BindOnce( &FamilyUserMetricsProvider::CheckSecondaryAccountsAndLogSegment,
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc index 7c285c8..c8813ed 100644 --- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc +++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc
@@ -6,6 +6,7 @@ #include <utility> +#include "ash/public/cpp/session/session_controller.h" #include "base/barrier_closure.h" #include "base/bind.h" #include "base/files/file.h" @@ -43,7 +44,6 @@ #include "crypto/random.h" #include "device/bluetooth/bluetooth_adapter_factory.h" #include "services/network/public/cpp/shared_url_loader_factory.h" -#include "ui/base/idle/idle.h" #include "url/gurl.h" namespace { @@ -230,6 +230,14 @@ DCHECK(profile_); DCHECK(nearby_connections_manager_); +#if defined(OS_CHROMEOS) + auto* session_controller = ash::SessionController::Get(); + if (session_controller) { + is_screen_locked_ = session_controller->IsScreenLocked(); + session_controller->AddObserver(this); + } +#endif // OS_CHROMEOS + nearby_process_observer_.Add(process_manager_); settings_.AddSettingsObserver(settings_receiver_.BindNewPipeAndPassRemote()); @@ -282,6 +290,12 @@ if (bluetooth_adapter_) bluetooth_adapter_->RemoveObserver(this); +#if defined(OS_CHROMEOS) + auto* session_controller = ash::SessionController::Get(); + if (session_controller) + session_controller->RemoveObserver(this); +#endif // OS_CHROMEOS + foreground_receive_callbacks_.Clear(); background_receive_callbacks_.Clear(); foreground_send_transfer_callbacks_.Clear(); @@ -820,6 +834,13 @@ NS_LOG(VERBOSE) << __func__ << ": Reported onShareTargetLost"; } +void NearbySharingServiceImpl::OnLockStateChanged(bool locked) { + NS_LOG(VERBOSE) << __func__ << ": Screen lock state changed. (" << locked + << ")"; + is_screen_locked_ = locked; + InvalidateSurfaceState(); +} + void NearbySharingServiceImpl::OnEnabledChanged(bool enabled) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (enabled) { @@ -1120,7 +1141,7 @@ } // Screen is off. Do no work. - if (ui::CheckIdleStateIsLocked()) { + if (is_screen_locked_) { StopAdvertising(); NS_LOG(VERBOSE) << __func__ << ": Stopping advertising because the screen is locked."; @@ -1289,7 +1310,7 @@ } // Screen is off. Do no work. - if (ui::CheckIdleStateIsLocked()) { + if (is_screen_locked_) { StopScanning(); NS_LOG(VERBOSE) << __func__ << ": Stopping discovery because the screen is locked."; @@ -1346,7 +1367,7 @@ return; } - if (ui::CheckIdleStateIsLocked()) { + if (is_screen_locked_) { NS_LOG(VERBOSE) << __func__ << ": Failed to scan because the user's screen is locked."; return;
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h index be22bcb..b25b3bf 100644 --- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h +++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h
@@ -11,6 +11,7 @@ #include <utility> #include <vector> +#include "ash/public/cpp/session/session_observer.h" #include "base/cancelable_callback.h" #include "base/containers/flat_map.h" #include "base/memory/ptr_util.h" @@ -57,7 +58,8 @@ public NearbyProcessManager::Observer, public device::BluetoothAdapter::Observer, public NearbyConnectionsManager::IncomingConnectionListener, - public NearbyConnectionsManager::DiscoveryListener { + public NearbyConnectionsManager::DiscoveryListener, + public ash::SessionObserver { public: explicit NearbySharingServiceImpl( PrefService* prefs, @@ -132,6 +134,9 @@ void OnEndpointLost(const std::string& endpoint_id) override; private: + // ash::SessionObserver: + void OnLockStateChanged(bool locked) override; + base::ObserverList<TransferUpdateCallback>& GetReceiveCallbacksFromState( ReceiveSurfaceState state); bool IsVisibleInBackground(Visibility visibility); @@ -316,6 +321,7 @@ std::unique_ptr<NearbyShareCertificateManager> certificate_manager_; NearbyShareSettings settings_; NearbyFileHandler file_handler_; + bool is_screen_locked_ = false; // A list of service observers. base::ObserverList<NearbySharingService::Observer> observers_;
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc b/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc index b034476..1f6f1863 100644 --- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc +++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc
@@ -59,9 +59,10 @@ #include "net/base/mock_network_change_notifier.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/idle/scoped_set_idle_state.h" + #if defined(OS_CHROMEOS) #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h" +#include "chrome/browser/ui/ash/test_session_controller.h" #include "components/user_manager/scoped_user_manager.h" #endif // defined(OS_CHROMEOS) @@ -364,6 +365,10 @@ device::BluetoothAdapterFactory::SetAdapterForTesting( mock_bluetooth_adapter_); +#if defined(OS_CHROMEOS) + session_controller_ = std::make_unique<TestSessionController>(); +#endif // OS_CHROMEOS + service_ = CreateService(); SetFakeFastInitiationManagerFactory(/*should_succeed_on_start=*/true); @@ -617,7 +622,6 @@ SetUpIntroductionFrameDecoder(/*return_empty_introduction_frame=*/false); ShareTarget share_target; - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); base::RunLoop run_loop; EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_)) @@ -661,7 +665,6 @@ ShareTarget DiscoverShareTarget( MockTransferUpdateCallback& transfer_callback, MockShareTargetDiscoveredCallback& discovery_callback) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); // Ensure decoder parses a valid endpoint advertisement. @@ -859,7 +862,6 @@ // ChromeDownloadManagerDelegate. std::unique_ptr<net::test::MockNetworkChangeNotifier> network_notifier_; content::BrowserTaskEnvironment task_environment_; - ui::ScopedSetIdleState idle_state_{ui::IDLE_STATE_IDLE}; TestingProfileManager profile_manager_{TestingBrowserProcess::GetGlobal()}; Profile* profile_ = nullptr; #if defined(OS_CHROMEOS) @@ -873,6 +875,9 @@ FakeNearbyShareCertificateManager::Factory certificate_manager_factory_; std::unique_ptr<NotificationDisplayServiceTester> notification_tester_; NiceMock<MockNearbyProcessManager> mock_nearby_process_manager_; +#if defined(OS_CHROMEOS) + std::unique_ptr<TestSessionController> session_controller_; +#endif // OS_CHROMEOS std::unique_ptr<NearbySharingServiceImpl> service_; std::unique_ptr<base::ScopedDisallowBlocking> disallow_blocking_; std::unique_ptr<FakeFastInitiationManagerFactory> @@ -886,40 +891,40 @@ }; struct ValidSendSurfaceTestData { - ui::IdleState idle_state; bool bluetooth_enabled; net::NetworkChangeNotifier::ConnectionType connection_type; } kValidSendSurfaceTestData[] = { // No network connection, only bluetooth available - {ui::IDLE_STATE_IDLE, true, net::NetworkChangeNotifier::CONNECTION_NONE}, + {true, net::NetworkChangeNotifier::CONNECTION_NONE}, // Wifi available - {ui::IDLE_STATE_IDLE, true, net::NetworkChangeNotifier::CONNECTION_WIFI}, + {true, net::NetworkChangeNotifier::CONNECTION_WIFI}, // Ethernet available - {ui::IDLE_STATE_IDLE, true, - net::NetworkChangeNotifier::CONNECTION_ETHERNET}, + {true, net::NetworkChangeNotifier::CONNECTION_ETHERNET}, // 3G available - {ui::IDLE_STATE_IDLE, true, net::NetworkChangeNotifier::CONNECTION_3G}, + {true, net::NetworkChangeNotifier::CONNECTION_3G}, // Wifi available and no bluetooth - {ui::IDLE_STATE_IDLE, false, net::NetworkChangeNotifier::CONNECTION_WIFI}, + {false, net::NetworkChangeNotifier::CONNECTION_WIFI}, // Ethernet available and no bluetooth - {ui::IDLE_STATE_IDLE, false, - net::NetworkChangeNotifier::CONNECTION_ETHERNET}}; + {false, net::NetworkChangeNotifier::CONNECTION_ETHERNET}}; class NearbySharingServiceImplValidSendTest : public NearbySharingServiceImplTest, public testing::WithParamInterface<ValidSendSurfaceTestData> {}; struct InvalidSendSurfaceTestData { - ui::IdleState idle_state; + bool screen_locked; bool bluetooth_enabled; net::NetworkChangeNotifier::ConnectionType connection_type; } kInvalidSendSurfaceTestData[] = { +#if defined(OS_CHROMEOS) // Screen locked - {ui::IDLE_STATE_LOCKED, true, net::NetworkChangeNotifier::CONNECTION_WIFI}, + {/*screen_locked=*/true, true, net::NetworkChangeNotifier::CONNECTION_WIFI}, +#endif // OS_CHROMEOS // No network connection and no bluetooth - {ui::IDLE_STATE_IDLE, false, net::NetworkChangeNotifier::CONNECTION_NONE}, + {/*screen_locked=*/false, false, + net::NetworkChangeNotifier::CONNECTION_NONE}, // 3G available and no bluetooth - {ui::IDLE_STATE_IDLE, false, net::NetworkChangeNotifier::CONNECTION_3G}, + {/*screen_locked=*/false, false, net::NetworkChangeNotifier::CONNECTION_3G}, }; class NearbySharingServiceImplInvalidSendTest @@ -979,7 +984,6 @@ } TEST_F(NearbySharingServiceImplTest, DisableNearbyShutdownConnections) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); prefs_.SetBoolean(prefs::kNearbySharingEnabledPrefName, false); service_->FlushMojoForTesting(); @@ -987,7 +991,6 @@ } TEST_F(NearbySharingServiceImplTest, StartFastInitiationAdvertising) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; @@ -1007,7 +1010,6 @@ } TEST_F(NearbySharingServiceImplTest, StartFastInitiationAdvertisingError) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); SetFakeFastInitiationManagerFactory(/*should_succeed_on_start=*/false); MockTransferUpdateCallback transfer_callback; @@ -1020,7 +1022,6 @@ TEST_F(NearbySharingServiceImplTest, BackgroundStartFastInitiationAdvertisingError) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; @@ -1033,7 +1034,6 @@ TEST_F(NearbySharingServiceImplTest, StartFastInitiationAdvertising_BluetoothNotPresent) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); is_bluetooth_present_ = false; MockTransferUpdateCallback transfer_callback; @@ -1046,7 +1046,6 @@ TEST_F(NearbySharingServiceImplTest, StartFastInitiationAdvertising_BluetoothNotPowered) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); is_bluetooth_powered_ = false; MockTransferUpdateCallback transfer_callback; @@ -1058,7 +1057,6 @@ } TEST_F(NearbySharingServiceImplTest, StopFastInitiationAdvertising) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; @@ -1076,7 +1074,6 @@ TEST_F(NearbySharingServiceImplTest, StopFastInitiationAdvertising_BluetoothBecomesNotPresent) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; @@ -1092,7 +1089,6 @@ TEST_F(NearbySharingServiceImplTest, StopFastInitiationAdvertising_BluetoothBecomesNotPowered) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; @@ -1108,7 +1104,6 @@ TEST_F(NearbySharingServiceImplTest, RegisterSendSurfaceNoActiveProfilesNotDiscovering) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); ON_CALL(mock_nearby_process_manager_, IsActiveProfile(_)) .WillByDefault(Return(false)); @@ -1148,7 +1143,6 @@ TEST_F(NearbySharingServiceImplTest, ForegroundRegisterSendSurfaceStartsDiscovering) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; @@ -1161,7 +1155,6 @@ TEST_F(NearbySharingServiceImplTest, ForegroundRegisterSendSurfaceTwiceKeepsDiscovering) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; @@ -1232,7 +1225,6 @@ TEST_F(NearbySharingServiceImplTest, BackgroundRegisterSendSurfaceNotDiscovering) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; @@ -1246,7 +1238,6 @@ TEST_F(NearbySharingServiceImplTest, DifferentSurfaceRegisterSendSurfaceTwiceKeepsDiscovering) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; @@ -1265,7 +1256,6 @@ TEST_F(NearbySharingServiceImplTest, RegisterSendSurfaceEndpointFoundDiscoveryCallbackNotified) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); // Ensure decoder parses a valid endpoint advertisement. @@ -1323,7 +1313,6 @@ } TEST_F(NearbySharingServiceImplTest, RegisterSendSurfaceEmptyCertificate) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); // Ensure decoder parses a valid endpoint advertisement. @@ -1382,7 +1371,6 @@ TEST_P(NearbySharingServiceImplValidSendTest, RegisterSendSurfaceIsDiscovering) { - ui::ScopedSetIdleState idle_state(GetParam().idle_state); is_bluetooth_present_ = GetParam().bluetooth_enabled; SetConnectionType(GetParam().connection_type); MockTransferUpdateCallback transfer_callback; @@ -1400,7 +1388,9 @@ TEST_P(NearbySharingServiceImplInvalidSendTest, RegisterSendSurfaceNotDiscovering) { - ui::ScopedSetIdleState idle_state(GetParam().idle_state); +#if defined(OS_CHROMEOS) + session_controller_->SetScreenLocked(GetParam().screen_locked); +#endif // OS_CHROMEOS is_bluetooth_present_ = GetParam().bluetooth_enabled; SetConnectionType(GetParam().connection_type); MockTransferUpdateCallback transfer_callback; @@ -1419,7 +1409,6 @@ testing::ValuesIn(kInvalidSendSurfaceTestData)); TEST_F(NearbySharingServiceImplTest, DisableFeatureSendSurfaceNotDiscovering) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); prefs_.SetBoolean(prefs::kNearbySharingEnabledPrefName, false); service_->FlushMojoForTesting(); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); @@ -1435,7 +1424,6 @@ TEST_F(NearbySharingServiceImplTest, DisableFeatureSendSurfaceStopsDiscovering) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; @@ -1452,7 +1440,6 @@ } TEST_F(NearbySharingServiceImplTest, UnregisterSendSurfaceStopsDiscovering) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; @@ -1473,7 +1460,6 @@ TEST_F(NearbySharingServiceImplTest, UnregisterSendSurfaceDifferentCallbackKeepDiscovering) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; @@ -1492,7 +1478,6 @@ } TEST_F(NearbySharingServiceImplTest, UnregisterSendSurfaceNeverRegistered) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); EXPECT_CALL(mock_nearby_process_manager(), StopProcess(profile_)) @@ -1507,7 +1492,6 @@ TEST_F(NearbySharingServiceImplTest, ForegroundRegisterReceiveSurfaceIsAdvertisingAllContacts) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); SetVisibility(nearby_share::mojom::Visibility::kAllContacts); local_device_data_manager()->SetDeviceName(kDeviceName); @@ -1534,7 +1518,6 @@ TEST_F(NearbySharingServiceImplTest, ForegroundRegisterReceiveSurfaceIsAdvertisingNoOne) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); SetVisibility(nearby_share::mojom::Visibility::kNoOne); local_device_data_manager()->SetDeviceName(kDeviceName); @@ -1563,7 +1546,6 @@ TEST_F(NearbySharingServiceImplTest, BackgroundRegisterReceiveSurfaceIsAdvertisingSelectedContacts) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); SetVisibility(nearby_share::mojom::Visibility::kSelectedContacts); prefs_.SetInteger(prefs::kNearbySharingBackgroundVisibilityName, @@ -1591,7 +1573,6 @@ TEST_F(NearbySharingServiceImplTest, RegisterReceiveSurfaceTwiceSameCallbackKeepAdvertising) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( @@ -1607,7 +1588,6 @@ TEST_F(NearbySharingServiceImplTest, RegisterReceiveSurfaceTwiceKeepAdvertising) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( @@ -1622,9 +1602,10 @@ EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); } +#if defined(OS_CHROMEOS) TEST_F(NearbySharingServiceImplTest, ScreenLockedRegisterReceiveSurfaceNotAdvertising) { - ui::ScopedSetIdleState locked(ui::IDLE_STATE_LOCKED); + session_controller_->SetScreenLocked(true); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( @@ -1634,9 +1615,25 @@ EXPECT_FALSE(fake_nearby_connections_manager_->is_shutdown()); } +TEST_F(NearbySharingServiceImplTest, ScreenLocksDuringAdvertising) { + SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); + MockTransferUpdateCallback transfer_callback; + MockShareTargetDiscoveredCallback discovery_callback; + EXPECT_EQ( + NearbySharingService::StatusCodes::kOk, + service_->RegisterSendSurface(&transfer_callback, &discovery_callback, + SendSurfaceState::kForeground)); + EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); + + session_controller_->SetScreenLocked(true); + EXPECT_FALSE(fake_nearby_connections_manager_->IsDiscovering()); + session_controller_->SetScreenLocked(false); + EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); +} +#endif // OS_CHROMEOS + TEST_F(NearbySharingServiceImplTest, DataUsageChangedRegisterReceiveSurfaceRestartsAdvertising) { - ui::ScopedSetIdleState locked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); prefs_.SetInteger(prefs::kNearbySharingDataUsageName, @@ -1660,7 +1657,6 @@ TEST_F(NearbySharingServiceImplTest, NoNetworkRegisterReceiveSurfaceIsAdvertising) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); @@ -1671,7 +1667,6 @@ TEST_F(NearbySharingServiceImplTest, NoBluetoothNoNetworkRegisterReceiveSurfaceNotAdvertising) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); is_bluetooth_present_ = false; MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( @@ -1682,7 +1677,6 @@ } TEST_F(NearbySharingServiceImplTest, WifiRegisterReceiveSurfaceIsAdvertising) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( @@ -1693,7 +1687,6 @@ TEST_F(NearbySharingServiceImplTest, EthernetRegisterReceiveSurfaceIsAdvertising) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_ETHERNET); MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( @@ -1704,7 +1697,6 @@ TEST_F(NearbySharingServiceImplTest, ThreeGRegisterReceiveSurfaceIsAdvertising) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_3G); MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( @@ -1716,7 +1708,6 @@ TEST_F(NearbySharingServiceImplTest, NoBluetoothWifiReceiveSurfaceIsAdvertising) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); is_bluetooth_present_ = false; SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); MockTransferUpdateCallback callback; @@ -1728,7 +1719,6 @@ TEST_F(NearbySharingServiceImplTest, NoBluetoothEthernetReceiveSurfaceIsAdvertising) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); is_bluetooth_present_ = false; SetConnectionType(net::NetworkChangeNotifier::CONNECTION_ETHERNET); MockTransferUpdateCallback callback; @@ -1740,7 +1730,6 @@ TEST_F(NearbySharingServiceImplTest, NoBluetoothThreeGReceiveSurfaceNotAdvertising) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); is_bluetooth_present_ = false; SetConnectionType(net::NetworkChangeNotifier::CONNECTION_3G); MockTransferUpdateCallback callback; @@ -1753,7 +1742,6 @@ TEST_F(NearbySharingServiceImplTest, DisableFeatureReceiveSurfaceNotAdvertising) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); prefs_.SetBoolean(prefs::kNearbySharingEnabledPrefName, false); service_->FlushMojoForTesting(); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); @@ -1767,7 +1755,6 @@ TEST_F(NearbySharingServiceImplTest, DisableFeatureReceiveSurfaceStopsAdvertising) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( @@ -1783,7 +1770,6 @@ TEST_F(NearbySharingServiceImplTest, ForegroundReceiveSurfaceNoOneVisibilityIsAdvertising) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); prefs_.SetInteger(prefs::kNearbySharingBackgroundVisibilityName, static_cast<int>(Visibility::kNoOne)); @@ -1796,7 +1782,6 @@ TEST_F(NearbySharingServiceImplTest, BackgroundReceiveSurfaceNoOneVisibilityNotAdvertising) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); prefs_.SetInteger(prefs::kNearbySharingBackgroundVisibilityName, static_cast<int>(Visibility::kNoOne)); @@ -1811,7 +1796,6 @@ TEST_F(NearbySharingServiceImplTest, BackgroundReceiveSurfaceVisibilityToNoOneStopsAdvertising) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); prefs_.SetInteger(prefs::kNearbySharingBackgroundVisibilityName, static_cast<int>(Visibility::kSelectedContacts)); @@ -1831,7 +1815,6 @@ TEST_F(NearbySharingServiceImplTest, BackgroundReceiveSurfaceVisibilityToSelectedStartsAdvertising) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); prefs_.SetInteger(prefs::kNearbySharingBackgroundVisibilityName, static_cast<int>(Visibility::kNoOne)); @@ -1851,7 +1834,6 @@ TEST_F(NearbySharingServiceImplTest, ForegroundReceiveSurfaceSelectedContactsVisibilityIsAdvertising) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); prefs_.SetInteger(prefs::kNearbySharingBackgroundVisibilityName, static_cast<int>(Visibility::kSelectedContacts)); @@ -1864,7 +1846,6 @@ TEST_F(NearbySharingServiceImplTest, BackgroundReceiveSurfaceSelectedContactsVisibilityIsAdvertising) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); prefs_.SetInteger(prefs::kNearbySharingBackgroundVisibilityName, static_cast<int>(Visibility::kSelectedContacts)); @@ -1877,7 +1858,6 @@ TEST_F(NearbySharingServiceImplTest, ForegroundReceiveSurfaceAllContactsVisibilityIsAdvertising) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); prefs_.SetInteger(prefs::kNearbySharingBackgroundVisibilityName, static_cast<int>(Visibility::kAllContacts)); @@ -1890,7 +1870,6 @@ TEST_F(NearbySharingServiceImplTest, BackgroundReceiveSurfaceAllContactsVisibilityNotAdvertising) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); prefs_.SetInteger(prefs::kNearbySharingBackgroundVisibilityName, static_cast<int>(Visibility::kAllContacts)); @@ -1902,7 +1881,6 @@ } TEST_F(NearbySharingServiceImplTest, UnregisterReceiveSurfaceStopsAdvertising) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( @@ -1921,7 +1899,6 @@ TEST_F(NearbySharingServiceImplTest, UnregisterReceiveSurfaceDifferentCallbackKeepAdvertising) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( @@ -1937,7 +1914,6 @@ } TEST_F(NearbySharingServiceImplTest, UnregisterReceiveSurfaceNeverRegistered) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); EXPECT_CALL(mock_nearby_process_manager(), StopProcess(profile_)) @@ -1957,7 +1933,6 @@ SetUpAdvertisementDecoder(kValidV1EndpointInfo, /*return_empty_advertisement=*/false); - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); NiceMock<MockTransferUpdateCallback> callback; EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_)).Times(0); @@ -1985,7 +1960,6 @@ /*return_empty_advertisement=*/false); SetUpIntroductionFrameDecoder(/*return_empty_introduction_frame=*/true); - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); NiceMock<MockTransferUpdateCallback> callback; base::RunLoop run_loop; @@ -2034,7 +2008,6 @@ /*return_empty_advertisement=*/false); SetUpIntroductionFrameDecoder(/*return_empty_introduction_frame=*/false); - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); NiceMock<MockTransferUpdateCallback> callback; base::RunLoop run_loop; @@ -2145,7 +2118,6 @@ })); connection_.AppendReadableData(std::move(bytes)); - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); NiceMock<MockTransferUpdateCallback> callback; base::RunLoop run_loop; @@ -2221,7 +2193,6 @@ })); connection_.AppendReadableData(std::move(bytes)); - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); NiceMock<MockTransferUpdateCallback> callback; base::RunLoop run_loop; @@ -2262,7 +2233,6 @@ /*return_empty_advertisement=*/false); SetUpIntroductionFrameDecoder(/*return_empty_introduction_frame=*/false); - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); NiceMock<MockTransferUpdateCallback> callback; base::RunLoop run_loop; @@ -2844,7 +2814,6 @@ /*return_empty_advertisement=*/false); SetUpIntroductionFrameDecoder(/*return_empty_introduction_frame=*/false); - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); NiceMock<MockTransferUpdateCallback> callback; base::RunLoop run_loop; @@ -2897,7 +2866,6 @@ /*return_empty_advertisement=*/false); SetUpIntroductionFrameDecoder(/*return_empty_introduction_frame=*/false); - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); NiceMock<MockTransferUpdateCallback> callback; base::RunLoop run_loop; @@ -2953,7 +2921,6 @@ SetUpAdvertisementDecoder(kValidV1EndpointInfo, /*return_empty_advertisement=*/false); - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); NiceMock<MockTransferUpdateCallback> callback; @@ -2984,7 +2951,6 @@ SetUpAdvertisementDecoder(kValidV1EndpointInfo, /*return_empty_advertisement=*/false); - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); NiceMock<MockTransferUpdateCallback> callback; @@ -3423,7 +3389,6 @@ } TEST_F(NearbySharingServiceImplTest, ProfileChangedControlsDiscovery) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); MockTransferUpdateCallback transfer_callback; MockShareTargetDiscoveredCallback discovery_callback; @@ -3446,7 +3411,6 @@ } TEST_F(NearbySharingServiceImplTest, ProfileChangedControlsAdvertising) { - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); MockTransferUpdateCallback callback; NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( @@ -3470,7 +3434,6 @@ RegisterForegroundReceiveSurfaceEntersHighVisibility) { TestObserver observer(service_.get()); NiceMock<MockTransferUpdateCallback> callback; - ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); SetVisibility(nearby_share::mojom::Visibility::kAllContacts);
diff --git a/chrome/browser/page_load_metrics/observers/security_state_page_load_metrics_observer_browsertest.cc b/chrome/browser/page_load_metrics/observers/security_state_page_load_metrics_observer_browsertest.cc index c181d3fd..28103ac 100644 --- a/chrome/browser/page_load_metrics/observers/security_state_page_load_metrics_observer_browsertest.cc +++ b/chrome/browser/page_load_metrics/observers/security_state_page_load_metrics_observer_browsertest.cc
@@ -396,10 +396,7 @@ CloseAllTabs(); security_state::SecurityLevel mixed_content_security_level = - base::FeatureList::IsEnabled( - security_state::features::kPassiveMixedContentWarning) - ? security_state::WARNING - : security_state::NONE; + security_state::WARNING; histogram_tester()->ExpectTotalCount( SecurityStatePageLoadMetricsObserver::
diff --git a/chrome/browser/policy/android/java/src/org/chromium/chrome/browser/policy/PolicyServiceFactory.java b/chrome/browser/policy/android/java/src/org/chromium/chrome/browser/policy/PolicyServiceFactory.java index 8884526..a1b6233 100644 --- a/chrome/browser/policy/android/java/src/org/chromium/chrome/browser/policy/PolicyServiceFactory.java +++ b/chrome/browser/policy/android/java/src/org/chromium/chrome/browser/policy/PolicyServiceFactory.java
@@ -9,7 +9,7 @@ import org.chromium.base.annotations.JNINamespace; import org.chromium.base.annotations.NativeMethods; import org.chromium.chrome.browser.profiles.Profile; -import org.chromium.policy.PolicyService; +import org.chromium.components.policy.PolicyService; /** * Get the PolicyService instance. Note that the associated C++ instance won't
diff --git a/chrome/browser/policy/chrome_browser_policy_connector.cc b/chrome/browser/policy/chrome_browser_policy_connector.cc index f359971c..bc07603c 100644 --- a/chrome/browser/policy/chrome_browser_policy_connector.cc +++ b/chrome/browser/policy/chrome_browser_policy_connector.cc
@@ -48,7 +48,7 @@ #elif defined(OS_POSIX) && !defined(OS_ANDROID) #include "components/policy/core/common/config_dir_policy_loader.h" #elif defined(OS_ANDROID) -#include "components/policy/core/browser/android/android_combined_policy_provider.h" +#include "components/policy/core/common/android/android_combined_policy_provider.h" #endif #if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
diff --git a/chrome/browser/policy/messaging_layer/storage/storage_queue.cc b/chrome/browser/policy/messaging_layer/storage/storage_queue.cc index 9b254f1..1caf13a 100644 --- a/chrome/browser/policy/messaging_layer/storage/storage_queue.cc +++ b/chrome/browser/policy/messaging_layer/storage/storage_queue.cc
@@ -920,9 +920,7 @@ } scoped_refptr<SingleFile> last_file = assign_result.ValueOrDie(); - // Prepare and initiate writing generation into to a new file. - // Pick up when both WriteMetadata and WriteHeaderAndBlock - // have finished. + // Writing metadata ahead of the data write. Status write_result = storage_queue_->WriteMetadata(); if (!write_result.ok()) { Response(write_result);
diff --git a/chrome/browser/policy/messaging_layer/storage/storage_queue_unittest.cc b/chrome/browser/policy/messaging_layer/storage/storage_queue_unittest.cc index 0dbfc0d..512e99c7 100644 --- a/chrome/browser/policy/messaging_layer/storage/storage_queue_unittest.cc +++ b/chrome/browser/policy/messaging_layer/storage/storage_queue_unittest.cc
@@ -76,7 +76,16 @@ class MockUploadClient : public StorageQueue::UploaderInterface { public: - MockUploadClient() = default; + // Mapping of (generation, seq number) to matching record digest. Whenever a + // record is uploaded and includes last record digest, this map should have + // that digest already recorded. Only the first record in a generation is + // uploaded without last record digest. + using LastRecordDigestMap = std::map< + std::pair<uint64_t /*generation */, uint64_t /*sequencing number*/>, + std::string /*digest*/>; + + explicit MockUploadClient(LastRecordDigestMap* last_record_digest_map) + : last_record_digest_map_(last_record_digest_map) {} void ProcessRecord(StatusOr<EncryptedRecord> encrypted_record, base::OnceCallback<void(bool)> processed_cb) override { @@ -89,25 +98,22 @@ ASSERT_TRUE(wrapped_record.ParseFromString( encrypted_record.ValueOrDie().encrypted_wrapped_record())); // Verify generation match. + const auto& sequencing_information = + encrypted_record.ValueOrDie().sequencing_information(); if (generation_id_.has_value() && - generation_id_.value() != encrypted_record.ValueOrDie() - .sequencing_information() - .generation_id()) { + generation_id_.value() != sequencing_information.generation_id()) { std::move(processed_cb) .Run(UploadRecordFailure(Status( error::DATA_LOSS, base::StrCat({"Generation id mismatch, expected=", base::NumberToString(generation_id_.value()), " actual=", - base::NumberToString(encrypted_record.ValueOrDie() - .sequencing_information() - .generation_id())})))); + base::NumberToString( + sequencing_information.generation_id())})))); return; } if (!generation_id_.has_value()) { - generation_id_ = encrypted_record.ValueOrDie() - .sequencing_information() - .generation_id(); + generation_id_ = sequencing_information.generation_id(); } // Verify digest and its match. @@ -124,12 +130,26 @@ Status(error::DATA_LOSS, "Record digest mismatch"))); return; } + if (wrapped_record.has_last_record_digest()) { + auto it = last_record_digest_map_->find( + std::make_pair(sequencing_information.sequencing_id() - 1, + sequencing_information.generation_id())); + if (it == last_record_digest_map_->end() || + it->second != wrapped_record.last_record_digest()) { + std::move(processed_cb) + .Run(UploadRecordFailure( + Status(error::DATA_LOSS, "Last record digest mismatch"))); + return; + } + } + last_record_digest_map_->emplace( + std::make_pair(sequencing_information.sequencing_id(), + sequencing_information.generation_id()), + record_digest); } std::move(processed_cb) - .Run(UploadRecord(encrypted_record.ValueOrDie() - .sequencing_information() - .sequencing_id(), + .Run(UploadRecord(sequencing_information.sequencing_id(), wrapped_record.record().data())); } @@ -176,6 +196,8 @@ private: base::Optional<uint64_t> generation_id_; + LastRecordDigestMap* const last_record_digest_map_; + Sequence test_upload_sequence_; }; @@ -218,7 +240,8 @@ StatusOr<std::unique_ptr<StorageQueue::UploaderInterface>> BuildMockUploader() { - auto uploader = std::make_unique<MockUploadClient>(); + auto uploader = + std::make_unique<MockUploadClient>(&last_record_digest_map_); set_mock_uploader_expectations_.Call(uploader.get()); return uploader; } @@ -250,6 +273,10 @@ scoped_refptr<test::TestEncryptionModule> test_encryption_module_; scoped_refptr<StorageQueue> storage_queue_; + // Test-wide global mapping of seq number to record digest. + // Serves all MockUploadClients created by test fixture. + MockUploadClient::LastRecordDigestMap last_record_digest_map_; + ::testing::MockFunction<void(MockUploadClient*)> set_mock_uploader_expectations_;
diff --git a/chrome/browser/policy/messaging_layer/storage/storage_unittest.cc b/chrome/browser/policy/messaging_layer/storage/storage_unittest.cc index e63c4b7..f4033abd 100644 --- a/chrome/browser/policy/messaging_layer/storage/storage_unittest.cc +++ b/chrome/browser/policy/messaging_layer/storage/storage_unittest.cc
@@ -5,8 +5,8 @@ #include "chrome/browser/policy/messaging_layer/storage/storage.h" #include <cstdint> +#include <tuple> #include <utility> -#include <vector> #include "base/files/scoped_temp_dir.h" #include "base/optional.h" @@ -78,7 +78,18 @@ class MockUploadClient : public Storage::UploaderInterface { public: - MockUploadClient() = default; + // Mapping of (generation, seq number) to matching record digest. Whenever a + // record is uploaded and includes last record digest, this map should have + // that digest already recorded. Only the first record in a generation is + // uploaded without last record digest. + using LastRecordDigestMap = + std::map<std::tuple<Priority, + uint64_t /*generation */, + uint64_t /*sequencing number*/>, + std::string /*digest*/>; + + explicit MockUploadClient(LastRecordDigestMap* last_record_digest_map) + : last_record_digest_map_(last_record_digest_map) {} void ProcessRecord(StatusOr<EncryptedRecord> encrypted_record, base::OnceCallback<void(bool)> processed_cb) override { @@ -91,25 +102,22 @@ ASSERT_TRUE(wrapped_record.ParseFromString( encrypted_record.ValueOrDie().encrypted_wrapped_record())); // Verify generation match. + const auto& sequencing_information = + encrypted_record.ValueOrDie().sequencing_information(); if (generation_id_.has_value() && - generation_id_.value() != encrypted_record.ValueOrDie() - .sequencing_information() - .generation_id()) { + generation_id_.value() != sequencing_information.generation_id()) { std::move(processed_cb) .Run(UploadRecordFailure(Status( error::DATA_LOSS, base::StrCat({"Generation id mismatch, expected=", base::NumberToString(generation_id_.value()), " actual=", - base::NumberToString(encrypted_record.ValueOrDie() - .sequencing_information() - .generation_id())})))); + base::NumberToString( + sequencing_information.generation_id())})))); return; } if (!generation_id_.has_value()) { - generation_id_ = encrypted_record.ValueOrDie() - .sequencing_information() - .generation_id(); + generation_id_ = sequencing_information.generation_id(); } // Verify digest and its match. @@ -126,15 +134,30 @@ Status(error::DATA_LOSS, "Record digest mismatch"))); return; } + if (wrapped_record.has_last_record_digest()) { + auto it = last_record_digest_map_->find( + std::make_tuple(sequencing_information.priority(), + sequencing_information.sequencing_id() - 1, + sequencing_information.generation_id())); + if (it == last_record_digest_map_->end() || + it->second != wrapped_record.last_record_digest()) { + std::move(processed_cb) + .Run(UploadRecordFailure( + Status(error::DATA_LOSS, "Last record digest mismatch"))); + return; + } + } + last_record_digest_map_->emplace( + std::make_tuple(sequencing_information.priority(), + sequencing_information.sequencing_id(), + sequencing_information.generation_id()), + record_digest); } std::move(processed_cb) - .Run(UploadRecord( - encrypted_record.ValueOrDie().sequencing_information().priority(), - encrypted_record.ValueOrDie() - .sequencing_information() - .sequencing_id(), - wrapped_record.record().data())); + .Run(UploadRecord(sequencing_information.priority(), + sequencing_information.sequencing_id(), + wrapped_record.record().data())); } void Completed(Status status) override { UploadComplete(status); } @@ -205,6 +228,8 @@ private: base::Optional<uint64_t> generation_id_; + LastRecordDigestMap* const last_record_digest_map_; + Sequence test_upload_sequence_; }; @@ -234,14 +259,15 @@ StatusOr<std::unique_ptr<Storage::UploaderInterface>> BuildMockUploader( Priority priority) { - auto uploader = std::make_unique<MockUploadClient>(); + auto uploader = + std::make_unique<MockUploadClient>(&last_record_digest_map_); set_mock_uploader_expectations_.Call(priority, uploader.get()); return uploader; } Status WriteString(Priority priority, base::StringPiece data) { - TestEvent<Status> w; EXPECT_TRUE(storage_) << "Storage not created yet"; + TestEvent<Status> w; Record record; record.set_data(std::string(data)); record.set_destination(UPLOAD_EVENTS); @@ -266,6 +292,10 @@ scoped_refptr<test::TestEncryptionModule> test_encryption_module_; scoped_refptr<Storage> storage_; + // Test-wide global mapping of seq number to record digest. + // Serves all MockUploadClients created by test fixture. + MockUploadClient::LastRecordDigestMap last_record_digest_map_; + ::testing::MockFunction<void(Priority, MockUploadClient*)> set_mock_uploader_expectations_;
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 ea76986..5477a32b 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
@@ -737,6 +737,8 @@ new KeyPrefix("zero_suggest_description*"); public static final KeyPrefix KEY_ZERO_SUGGEST_NATIVE_TYPE_PREFIX = new KeyPrefix("zero_suggest_native_type*"); + public static final KeyPrefix KEY_ZERO_SUGGEST_NATIVE_SUBTYPES_PREFIX = + new KeyPrefix("zero_suggest_native_subtypes*"); public static final KeyPrefix KEY_ZERO_SUGGEST_IS_SEARCH_TYPE_PREFIX = new KeyPrefix("zero_suggest_is_search*"); public static final KeyPrefix KEY_ZERO_SUGGEST_ANSWER_TEXT_PREFIX =
diff --git a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/GrandfatheredChromePreferenceKeys.java b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/GrandfatheredChromePreferenceKeys.java index eef9918a..90fc777 100644 --- a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/GrandfatheredChromePreferenceKeys.java +++ b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/GrandfatheredChromePreferenceKeys.java
@@ -209,6 +209,7 @@ ChromePreferenceKeys.KEY_ZERO_SUGGEST_DISPLAY_TEXT_PREFIX, ChromePreferenceKeys.KEY_ZERO_SUGGEST_DESCRIPTION_PREFIX, ChromePreferenceKeys.KEY_ZERO_SUGGEST_NATIVE_TYPE_PREFIX, + ChromePreferenceKeys.KEY_ZERO_SUGGEST_NATIVE_SUBTYPES_PREFIX, ChromePreferenceKeys.KEY_ZERO_SUGGEST_IS_SEARCH_TYPE_PREFIX, ChromePreferenceKeys.KEY_ZERO_SUGGEST_ANSWER_TEXT_PREFIX, ChromePreferenceKeys.KEY_ZERO_SUGGEST_GROUP_ID_PREFIX,
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index 016d4c9..c5734a3 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc
@@ -76,6 +76,7 @@ #include "chrome/browser/tracing/chrome_tracing_delegate.h" #include "chrome/browser/ui/browser_ui_prefs.h" #include "chrome/browser/ui/hats/hats_service.h" +#include "chrome/browser/ui/in_product_help/feature_promo_snooze_service.h" #include "chrome/browser/ui/network_profile_bubble.h" #include "chrome/browser/ui/prefs/prefs_tab_helper.h" #include "chrome/browser/ui/search_engines/keyword_editor_controller.h" @@ -893,6 +894,7 @@ enterprise_reporting::RegisterProfilePrefs(registry); extensions::CommandService::RegisterProfilePrefs(registry); extensions::TabsCaptureVisibleTabFunction::RegisterProfilePrefs(registry); + FeaturePromoSnoozeService::RegisterProfilePrefs(registry); first_run::RegisterProfilePrefs(registry); gcm::RegisterProfilePrefs(registry); HatsService::RegisterProfilePrefs(registry);
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn index 5e46e55..4b9842b 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn
@@ -474,6 +474,7 @@ "options/options_test.js", "panel/i_search_test.js", "panel/panel_test.js", + "panel/tutorial_test.js", ] gen_include_files = [ "../common/testing/assert_additions.js",
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/tutorial_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/tutorial_test.js new file mode 100644 index 0000000..47b67630 --- /dev/null +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/tutorial_test.js
@@ -0,0 +1,119 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Include test fixture. +GEN_INCLUDE(['../testing/chromevox_next_e2e_test_base.js']); +GEN_INCLUDE(['../testing/mock_feedback.js']); + +/** + * Test fixture for the interactive tutorial. + */ +ChromeVoxTutorialTest = class extends ChromeVoxNextE2ETest { + /** @override */ + testGenCppIncludes() { + super.testGenCppIncludes(); + GEN(` + #include "base/command_line.h" + #include "ui/accessibility/accessibility_switches.h" + `); + } + + /** @override */ + testGenPreamble() { + GEN(` + base::CommandLine::ForCurrentProcess()->AppendSwitch( + ::switches::kEnableExperimentalAccessibilityChromeVoxTutorial); + `); + super.testGenPreamble(); + } + + /** @override */ + setUp() { + window.doCmd = this.doCmd; + } + + /** + * @return {!MockFeedback} + */ + createMockFeedback() { + const mockFeedback = + new MockFeedback(this.newCallback(), this.newCallback.bind(this)); + mockFeedback.install(); + return mockFeedback; + } + + getPanelWindow() { + let panelWindow = null; + while (!panelWindow) { + panelWindow = chrome.extension.getViews().find(function(view) { + return view.location.href.indexOf('chromevox/panel/panel.html') > 0; + }); + } + return panelWindow; + } + + getPanel() { + return this.getPanelWindow().Panel; + } + + /** + * Waits for the interactive tutorial to load. + */ + async waitForTutorial() { + return new Promise(resolve => { + const doc = this.getPanelWindow().document; + if (doc.getElementById('i-tutorial-container')) { + resolve(); + } else { + /** + * @param {Array<MutationRecord>} mutationsList + * @param {MutationObserver} observer + */ + const onMutation = (mutationsList, observer) => { + for (const mutation of mutationsList) { + if (mutation.type === 'childList') { + for (const node of mutation.addedNodes) { + if (node.id === 'i-tutorial-container') { + // Resolve once the tutorial has been added to the document. + resolve(); + observer.disconnect(); + } + } + } + } + }; + + const observer = new MutationObserver(onMutation); + observer.observe( + doc.body /* target */, {childList: true} /* options */); + } + }); + } + + get simpleDoc() { + return ` + <p>Simple</p> + `; + } +}; + +TEST_F('ChromeVoxTutorialTest', 'BasicTest', function() { + const mockFeedback = this.createMockFeedback(); + this.runWithLoadedTree(this.simpleDoc, async function(root) { + const Panel = this.getPanel(); + assertTrue(Panel.iTutorialEnabled_); + new PanelCommand(PanelCommandType.TUTORIAL).send(); + await this.waitForTutorial(); + mockFeedback.expectSpeech('Choose your tutorial experience') + .call(doCmd('nextObject')) + .expectSpeech('New user', 'Button') + .call(doCmd('nextObject')) + .expectSpeech('Experienced user', 'Button') + .call(doCmd('nextObject')) + .expectSpeech('Developer', 'Button') + .call(doCmd('nextObject')) + .expectSpeech('Exit tutorial', 'Button') + .replay(); + }); +}); \ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/switch_access/BUILD.gn index da3c78e..59d61e3 100644 --- a/chrome/browser/resources/chromeos/accessibility/switch_access/BUILD.gn +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/BUILD.gn
@@ -105,6 +105,7 @@ "navigation_manager_test.js", "nodes/basic_node_test.js", "nodes/desktop_node_test.js", + "nodes/group_node_test.js", "nodes/tab_node_test.js", "switch_access_predicate_test.js", "text_navigation_manager_test.js",
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/navigation_manager_test.js b/chrome/browser/resources/chromeos/accessibility/switch_access/navigation_manager_test.js index 2e82b479..cd1c62d 100644 --- a/chrome/browser/resources/chromeos/accessibility/switch_access/navigation_manager_test.js +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/navigation_manager_test.js
@@ -303,3 +303,32 @@ 'button1 should come before button2'); }); }); + +TEST_F( + 'SwitchAccessNavigationManagerTest', 'NodeUndefinedBeforeTreeChangeRemoved', + function() { + const website = `<div> + <button id="button1"></button> + </div>`; + this.runWithLoadedTree(website, (desktop) => { + this.navigator.moveTo_(this.findNodeById('button1')); + const button1 = this.navigator.node_; + assertFalse( + button1 instanceof BackButtonNode, + 'button1 should not be a BackButtonNode'); + assertEquals( + 'button1', button1.automationNode.htmlAttributes.id, + 'Current node is not button1'); + + // Simulate the underlying node's deletion. Note that this is different + // than an orphaned node (which can have a valid AutomationNode + // instance, but no backing C++ object, so attributes returned like role + // are undefined). + NavigationManager.instance.node_.baseNode_ = undefined; + + // Tree change removed gets sent by C++ after the tree has already + // applied changes (so this comes after the above clearing). + NavigationManager.instance.onTreeChange_( + {type: chrome.automation.TreeChangeType.NODE_REMOVED}); + }); + });
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/basic_node.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/basic_node.js index 84a58494..3c2aedb 100644 --- a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/basic_node.js +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/basic_node.js
@@ -108,8 +108,8 @@ /** @override */ isValidAndVisible() { - // Nodes without a role are not valid. - if (!this.baseNode_.role) { + // Nodes may have been deleted or orphaned. + if (!this.baseNode_ || !this.baseNode_.role) { return false; } return SwitchAccessPredicate.isVisible(this.baseNode_) &&
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/group_node.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/group_node.js index a9126ae..98a4d54 100644 --- a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/group_node.js +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/group_node.js
@@ -35,7 +35,8 @@ /** @override */ get location() { - const childLocations = this.children_.map(c => c.location); + const childLocations = + this.children_.filter(c => c.isValidAndVisible()).map(c => c.location); return RectUtil.unionAll(childLocations); }
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/group_node_test.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/group_node_test.js new file mode 100644 index 0000000..76fa76f --- /dev/null +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/group_node_test.js
@@ -0,0 +1,33 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +GEN_INCLUDE(['../switch_access_e2e_test_base.js']); + +/** Test fixture for the node wrapper type. */ +SwitchAccessGroupNodeTest = class extends SwitchAccessE2ETest {}; + +TEST_F('SwitchAccessGroupNodeTest', 'NodesRemoved', function() { + const website = `<button></button>`; + this.runWithLoadedTree(website, (desktop) => { + const button = desktop.find({role: chrome.automation.RoleType.BUTTON}); + assertNotEquals(undefined, button); + + const root = new BasicRootNode(desktop); + assertEquals(0, root.children_.length); + + // Add a group child which has two buttons (same underlying automation + // node). + const buttonNode = new BasicNode(button, root); + const otherButtonNode = new BasicNode(button, root); + const groupNode = new GroupNode([buttonNode, otherButtonNode]); + root.children_ = [groupNode]; + + // Try asking for the location of the group. + assertTrue(!!groupNode.location); + + // Try again after clearing one of the button's underlying node. + buttonNode.baseNode_ = undefined; + assertTrue(!!groupNode.location); + }); +});
diff --git a/chrome/browser/resources/chromeos/crostini_installer/app.js b/chrome/browser/resources/chromeos/crostini_installer/app.js index ff3c5108..c92b178f 100644 --- a/chrome/browser/resources/chromeos/crostini_installer/app.js +++ b/chrome/browser/resources/chromeos/crostini_installer/app.js
@@ -412,9 +412,6 @@ case InstallerState.kInstallImageLoader: messageId = 'loadTerminaMessage'; break; - case InstallerState.kStartConcierge: - messageId = 'startConciergeMessage'; - break; case InstallerState.kCreateDiskImage: messageId = 'createDiskImageMessage'; break; @@ -461,9 +458,6 @@ case InstallerError.kErrorLoadingTermina: messageId = 'loadTerminaError'; break; - case InstallerError.kErrorStartingConcierge: - messageId = 'startConciergeError'; - break; case InstallerError.kErrorCreatingDiskImage: messageId = 'createDiskImageError'; break;
diff --git a/chrome/browser/resources/chromeos/file_manager/OWNERS b/chrome/browser/resources/chromeos/file_manager/OWNERS deleted file mode 100644 index 7d236cb..0000000 --- a/chrome/browser/resources/chromeos/file_manager/OWNERS +++ /dev/null
@@ -1,2 +0,0 @@ -file://ui/file_manager/OWNERS -# COMPONENT: Platform>Apps>FileManager
diff --git a/chrome/browser/resources/new_tab_page/app.html b/chrome/browser/resources/new_tab_page/app.html index fc569cf..48fab7e 100644 --- a/chrome/browser/resources/new_tab_page/app.html +++ b/chrome/browser/resources/new_tab_page/app.html
@@ -279,7 +279,8 @@ <ntp-middle-slot-promo on-ntp-middle-slot-promo-loaded="onMiddleSlotPromoLoaded_"> </ntp-middle-slot-promo> - <template is="dom-repeat" items="[[moduleDescriptors_]]" id="modules"> + <template is="dom-repeat" items="[[moduleDescriptors_]]" id="modules" + on-dom-change="onModulesRendered_"> <ntp-module-wrapper descriptor="[[item]]"></ntp-module-wrapper> </template> <a id="backgroundImageAttribution"
diff --git a/chrome/browser/resources/new_tab_page/app.js b/chrome/browser/resources/new_tab_page/app.js index 68ea6ff..cb34994 100644 --- a/chrome/browser/resources/new_tab_page/app.js +++ b/chrome/browser/resources/new_tab_page/app.js
@@ -742,6 +742,11 @@ onResize(); } + /** @private */ + onModulesRendered_() { + this.pageHandler_.onModulesRendered(BrowserProxy.getInstance().now()); + } + /** * During a shortcut drag, an iframe behind ntp-most-visited will prevent * 'dragover' events from firing. To workaround this, 'pointer-events: none'
diff --git a/chrome/browser/resources/optimize_webui.py b/chrome/browser/resources/optimize_webui.py index 5b3b9aa..094b7b3 100755 --- a/chrome/browser/resources/optimize_webui.py +++ b/chrome/browser/resources/optimize_webui.py
@@ -73,6 +73,7 @@ 'resources/css/text_defaults_md.css', 'resources/mojo/mojo/public/js/mojo_bindings_lite.html', 'resources/mojo/mojo/public/mojom/base/time.mojom.html', + 'resources/mojo/mojo/public/mojom/base/time.mojom-lite.js', 'resources/mojo/chromeos/services/network_config/public/mojom/network_types.mojom.html', 'resources/mojo/services/network/public/mojom/ip_address.mojom.html',
diff --git a/chrome/browser/resources/pdf/BUILD.gn b/chrome/browser/resources/pdf/BUILD.gn index 1cbb07a1..19b8a43 100644 --- a/chrome/browser/resources/pdf/BUILD.gn +++ b/chrome/browser/resources/pdf/BUILD.gn
@@ -163,6 +163,7 @@ ":toolbar_manager", "elements:viewer-error-screen", "elements:viewer-password-screen", + "elements:viewer-pdf-sidenav", "elements:viewer-pdf-toolbar", "elements:viewer-pdf-toolbar-new", "elements:viewer-zoom-toolbar",
diff --git a/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.html b/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.html index ad0db9f..b81eeb0 100644 --- a/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.html +++ b/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.html
@@ -1,10 +1,13 @@ <style include="pdf-shared"> :host { + --viewer-pdf-toolbar-height: 56px; box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.09), 0 4px 8px rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.3), 0 2px 6px rgba(0, 0, 0, 0.15); + height: var(--viewer-pdf-toolbar-height); + position: relative; } #toolbar { @@ -12,7 +15,7 @@ background-color: var(--viewer-pdf-toolbar-background-color); color: white; display: flex; - height: 56px; + height: var(--viewer-pdf-toolbar-height); padding: 0 16px; } @@ -164,7 +167,7 @@ <div id="toolbar"> <div id="start"> <cr-icon-button id="sidenavToggle" iron-icon="cr20:menu" - on-click="onSidenavToggleClick_"> + disabled="[[annotationMode]]" on-click="onSidenavToggleClick_"> </cr-icon-button> <span id="title">[[docTitle]]</span> </div>
diff --git a/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.js b/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.js index 28d2c71..20ffefc 100644 --- a/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.js +++ b/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.js
@@ -40,7 +40,6 @@ // </if> annotationMode: { type: Boolean, - notify: true, value: false, reflectToAttribute: true, }, @@ -324,11 +323,11 @@ // <if expr="chromeos"> toggleAnnotation() { - this.annotationMode = !this.annotationMode; + const newAnnotationMode = !this.annotationMode; this.dispatchEvent(new CustomEvent( - 'annotation-mode-toggled', {detail: this.annotationMode})); + 'annotation-mode-toggled', {detail: newAnnotationMode})); - if (this.annotationMode && !this.displayAnnotations_) { + if (newAnnotationMode && !this.displayAnnotations_) { this.toggleDisplayAnnotations_(); } }
diff --git a/chrome/browser/resources/pdf/pdf_viewer.html b/chrome/browser/resources/pdf/pdf_viewer.html index 95044f9..f051b41 100644 --- a/chrome/browser/resources/pdf/pdf_viewer.html +++ b/chrome/browser/resources/pdf/pdf_viewer.html
@@ -142,6 +142,7 @@ </template> <template is="dom-if" if="[[pdfViewerUpdateEnabled_]]"> <viewer-pdf-toolbar-new id="toolbar" + annotation-mode="[[annotationMode_]]" doc-title="[[title_]]" doc-length="[[docLength_]]" page-no="[[pageNo_]]" load-progress="[[loadProgress_]]" has-edits="[[hasEdits_]]" has-entered-annotation-mode="[[hasEnteredAnnotationMode_]]"
diff --git a/chrome/browser/resources/pdf/pdf_viewer.js b/chrome/browser/resources/pdf/pdf_viewer.js index a003c97c..67d1d27c 100644 --- a/chrome/browser/resources/pdf/pdf_viewer.js +++ b/chrome/browser/resources/pdf/pdf_viewer.js
@@ -4,7 +4,6 @@ import './elements/viewer-error-screen.js'; import './elements/viewer-password-screen.js'; -import './elements/viewer-pdf-sidenav.js'; import './elements/viewer-pdf-toolbar.js'; import './elements/viewer-zoom-toolbar.js'; import './elements/shared-vars.js'; @@ -18,12 +17,13 @@ import {assert, assertNotReached} from 'chrome://resources/js/assert.m.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; -import {hasKeyModifiers} from 'chrome://resources/js/util.m.js'; +import {hasKeyModifiers, listenOnce} from 'chrome://resources/js/util.m.js'; import {html} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {Bookmark} from './bookmark_type.js'; import {BrowserApi} from './browser_api.js'; import {Attachment, FittingType, Point, SaveRequestType} from './constants.js'; +import {ViewerPdfSidenavElement} from './elements/viewer-pdf-sidenav.js'; import {ViewerPdfToolbarNewElement} from './elements/viewer-pdf-toolbar-new.js'; // <if expr="chromeos"> import {InkController} from './ink_controller.js'; @@ -259,6 +259,12 @@ /** @private {boolean} */ this.sidenavCollapsed_ = false; + /** + * The state to restore sidenavCollapsed_ to after exiting annotation mode. + * @private {boolean} + */ + this.sidenavRestoreState_ = false; + if (this.pdfViewerUpdateEnabled_) { // TODO(dpapad): Add tests after crbug.com/1111459 is fixed. this.sidenavCollapsed_ = Boolean(Number.parseInt( @@ -459,18 +465,51 @@ // <if expr="chromeos"> /** + * @return {!Promise} Resolves when the sidenav animation is complete. + * @private + */ + waitForSidenavTransition_() { + return new Promise(resolve => { + listenOnce( + /** @type {!ViewerPdfSidenavElement} */ ( + this.shadowRoot.querySelector('#sidenav-container')), + 'transitionend', e => resolve()); + }); + } + + /** + * @return {!Promise} Resolves when the sidenav is restored to + * |sidenavRestoreState_|, after having been closed for annotation mode. + * @private + */ + restoreSidenav_() { + this.sidenavCollapsed_ = this.sidenavRestoreState_; + return this.sidenavCollapsed_ ? Promise.resolve() : + this.waitForSidenavTransition_(); + } + + /** * Handles the annotation mode being toggled on or off. * @param {!CustomEvent<boolean>} e * @private */ async onAnnotationModeToggled_(e) { const annotationMode = e.detail; - this.annotationMode_ = annotationMode; if (annotationMode) { // Enter annotation mode. assert(this.currentController === this.pluginController); // TODO(dstockwell): set plugin read-only, begin transition this.updateProgress(0); + + if (this.pdfViewerUpdateEnabled_) { + this.sidenavRestoreState_ = this.sidenavCollapsed_; + this.sidenavCollapsed_ = true; + if (!this.sidenavRestoreState_) { + // Wait for the animation before proceeding. + await this.waitForSidenavTransition_(); + } + } + // TODO(dstockwell): handle save failure const saveResult = await this.pluginController.save(SaveRequestType.ANNOTATION); @@ -483,12 +522,12 @@ } catch (e) { // The user aborted entering annotation mode. Revert to the plugin. this.getToolbar_().annotationMode = false; - this.annotationMode_ = false; this.updateProgress(100); return; } } PDFMetrics.record(PDFMetrics.UserAction.ENTER_ANNOTATION_MODE); + this.annotationMode_ = true; this.hasEnteredAnnotationMode_ = true; // TODO(dstockwell): feed real progress data from the Ink component this.updateProgress(50); @@ -502,6 +541,7 @@ assert(this.currentController === this.inkController_); // TODO(dstockwell): set ink read-only, begin transition this.updateProgress(0); + this.annotationMode_ = false; // This runs separately to allow other consumers of `loaded` to queue // up after this task. this.loaded.then(() => { @@ -513,6 +553,9 @@ await this.inkController_.save(SaveRequestType.ANNOTATION); // Data always exists when save is called with requestType = ANNOTATION. const result = /** @type {!RequiredSaveResult} */ (saveResult); + if (this.pdfViewerUpdateEnabled_) { + await this.restoreSidenav_(); + } await this.pluginController.load(result.fileName, result.dataToSave); // Ensure the plugin gets the initial viewport. this.pluginController.afterZoom(); @@ -529,6 +572,9 @@ } this.getToolbar_().toggleAnnotation(); this.annotationMode_ = false; + if (this.pdfViewerUpdateEnabled_) { + await this.restoreSidenav_(); + } await this.loaded; } // </if> @@ -546,7 +592,8 @@ * @private */ onScroll_(e) { - if (this.currentController === this.pluginController) { + if (this.currentController === this.pluginController && + !this.annotationMode_) { this.pluginController.updateScroll( e.target.scrollLeft, e.target.scrollTop); }
diff --git a/chrome/browser/safe_browsing/android/javatests/src/org/chromium/chrome/browser/safe_browsing/settings/SecuritySettingsFragmentTest.java b/chrome/browser/safe_browsing/android/javatests/src/org/chromium/chrome/browser/safe_browsing/settings/SecuritySettingsFragmentTest.java index 5c572d9..907cf23 100644 --- a/chrome/browser/safe_browsing/android/javatests/src/org/chromium/chrome/browser/safe_browsing/settings/SecuritySettingsFragmentTest.java +++ b/chrome/browser/safe_browsing/android/javatests/src/org/chromium/chrome/browser/safe_browsing/settings/SecuritySettingsFragmentTest.java
@@ -37,8 +37,8 @@ import org.chromium.components.browser_ui.settings.TextMessagePreference; import org.chromium.components.browser_ui.widget.RadioButtonWithDescription; import org.chromium.components.browser_ui.widget.RadioButtonWithDescriptionAndAuxButton; +import org.chromium.components.policy.test.annotations.Policies; import org.chromium.content_public.browser.test.util.TestThreadUtils; -import org.chromium.policy.test.annotations.Policies; /** * Tests for {@link SecuritySettingsFragment}.
diff --git a/chrome/browser/safe_browsing/android/javatests/src/org/chromium/chrome/browser/safe_browsing/settings/StandardProtectionSettingsFragmentTest.java b/chrome/browser/safe_browsing/android/javatests/src/org/chromium/chrome/browser/safe_browsing/settings/StandardProtectionSettingsFragmentTest.java index 8640841a..3a2f2a8 100644 --- a/chrome/browser/safe_browsing/android/javatests/src/org/chromium/chrome/browser/safe_browsing/settings/StandardProtectionSettingsFragmentTest.java +++ b/chrome/browser/safe_browsing/android/javatests/src/org/chromium/chrome/browser/safe_browsing/settings/StandardProtectionSettingsFragmentTest.java
@@ -25,10 +25,10 @@ import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.util.browser.Features; import org.chromium.components.browser_ui.settings.ChromeSwitchPreference; +import org.chromium.components.policy.test.annotations.Policies; import org.chromium.components.prefs.PrefService; import org.chromium.components.user_prefs.UserPrefs; import org.chromium.content_public.browser.test.util.TestThreadUtils; -import org.chromium.policy.test.annotations.Policies; /** * Tests for {@link StandardProtectionSettingsFragment}.
diff --git a/chrome/browser/safe_browsing/safe_browsing_navigation_observer.cc b/chrome/browser/safe_browsing/safe_browsing_navigation_observer.cc index 875baa9d..5765b20 100644 --- a/chrome/browser/safe_browsing/safe_browsing_navigation_observer.cc +++ b/chrome/browser/safe_browsing/safe_browsing_navigation_observer.cc
@@ -134,6 +134,23 @@ return; } + // When navigating a newly created portal contents, establish an association + // with its creator, so we can track the referrer chain across portal + // activations. + if (web_contents()->IsPortal() && + !web_contents()->GetController().GetLastCommittedEntry()) { + content::RenderFrameHost* initiator_frame_host = + content::RenderFrameHost::FromID( + navigation_handle->GetInitiatorRoutingId()); + content::WebContents* initiator_contents = + content::WebContents::FromRenderFrameHost(initiator_frame_host); + manager_->RecordNewWebContents( + initiator_contents, initiator_frame_host->GetProcess()->GetID(), + initiator_frame_host->GetRoutingID(), navigation_handle->GetURL(), + navigation_handle->GetPageTransition(), web_contents(), + navigation_handle->IsRendererInitiated()); + } + std::unique_ptr<NavigationEvent> nav_event = std::make_unique<NavigationEvent>(); auto it = navigation_handle_map_.find(navigation_handle); @@ -164,8 +181,7 @@ // If there was a URL previously committed in the current RenderFrameHost, // set it as the source url of this navigation. Otherwise, this is the - // first url going to commit in this frame. We set navigation_handle's URL as - // the source url. + // first url going to commit in this frame. int current_process_id = navigation_handle->GetStartingSiteInstance()->GetProcess()->GetID(); content::RenderFrameHost* current_frame_host = @@ -270,44 +286,6 @@ renderer_initiated); } -void SafeBrowsingNavigationObserver::DidActivatePortal( - content::WebContents* predecessor_web_contents, - base::TimeTicks activation_time) { - content::RenderFrameHost* predecessor_frame = - predecessor_web_contents->GetMainFrame(); - content::RenderFrameHost* successor_frame = web_contents()->GetMainFrame(); - - // Portal activation swaps contents in a tab, so to the user it looks like a - // navigation, so we treat activation as navigation event, with the - // predecessor as the source and the successor as the "navigation." - std::unique_ptr<NavigationEvent> nav_event = - std::make_unique<NavigationEvent>(); - nav_event->navigation_initiation = - predecessor_frame->HasTransientUserActivation() - ? ReferrerChainEntry::RENDERER_INITIATED_WITH_USER_GESTURE - : ReferrerChainEntry::RENDERER_INITIATED_WITHOUT_USER_GESTURE; - nav_event->frame_id = successor_frame->GetFrameTreeNodeId(); - DCHECK(predecessor_frame->GetLastCommittedURL().is_valid()); - DCHECK(successor_frame->GetLastCommittedURL().is_valid()); - nav_event->source_url = SafeBrowsingNavigationObserverManager::ClearURLRef( - predecessor_frame->GetLastCommittedURL()); - nav_event->source_main_frame_url = nav_event->source_url; - // TODO(mcnee): Ensure that redirects within a portal before it is activated - // are reflected in the referrer chain. See https://crbug.com/1096115 - nav_event->original_request_url = - SafeBrowsingNavigationObserverManager::ClearURLRef( - successor_frame->GetLastCommittedURL()); - nav_event->source_tab_id = - sessions::SessionTabHelper::IdForTab(predecessor_web_contents); - nav_event->target_tab_id = - sessions::SessionTabHelper::IdForTab(web_contents()); - nav_event->maybe_launched_by_external_application = false; - nav_event->has_committed = true; - nav_event->last_updated = base::Time::Now(); - - manager_->RecordNavigationEvent(std::move(nav_event)); -} - void SafeBrowsingNavigationObserver::OnContentSettingChanged( const ContentSettingsPattern& primary_pattern, const ContentSettingsPattern& secondary_pattern,
diff --git a/chrome/browser/safe_browsing/safe_browsing_navigation_observer.h b/chrome/browser/safe_browsing/safe_browsing_navigation_observer.h index fd79bf4..02b6788 100644 --- a/chrome/browser/safe_browsing/safe_browsing_navigation_observer.h +++ b/chrome/browser/safe_browsing/safe_browsing_navigation_observer.h
@@ -136,8 +136,6 @@ ui::PageTransition transition, bool started_from_context_menu, bool renderer_initiated) override; - void DidActivatePortal(content::WebContents* predecessor_web_contents, - base::TimeTicks activation_time) override; // content_settings::Observer overrides. void OnContentSettingChanged(const ContentSettingsPattern& primary_pattern,
diff --git a/chrome/browser/safe_browsing/safe_browsing_navigation_observer_browsertest.cc b/chrome/browser/safe_browsing/safe_browsing_navigation_observer_browsertest.cc index 9d5a75a..66ee1a6 100644 --- a/chrome/browser/safe_browsing/safe_browsing_navigation_observer_browsertest.cc +++ b/chrome/browser/safe_browsing/safe_browsing_navigation_observer_browsertest.cc
@@ -2704,6 +2704,33 @@ base::test::ScopedFeatureList scoped_feature_list_; }; +namespace { +class PortalActivationWaiter : public content::WebContentsObserver { + public: + explicit PortalActivationWaiter(content::WebContents* portal_contents) + : content::WebContentsObserver(portal_contents) {} + + void Wait() { + if (!web_contents()->IsPortal()) + return; + + base::RunLoop run_loop; + quit_closure_ = run_loop.QuitClosure(); + run_loop.Run(); + } + + // content::WebContentsObserver: + void DidActivatePortal(content::WebContents* predecessor_contents, + base::TimeTicks activation_time) override { + if (quit_closure_) + std::move(quit_closure_).Run(); + } + + private: + base::OnceClosure quit_closure_; +}; +} // namespace + // Click a link which activates a portal to the landing page, and then click on // the landing page to trigger the download. IN_PROC_BROWSER_TEST_F(SBNavigationObserverPortalBrowserTest, @@ -2713,6 +2740,7 @@ GURL download_url = embedded_test_server()->GetURL(kDownloadItemURL); ui_test_utils::NavigateToURL(browser(), initial_url); + SimulateUserGesture(); ASSERT_EQ(true, content::EvalJs( browser()->tab_strip_model()->GetActiveWebContents(), content::JsReplace( @@ -2724,11 +2752,19 @@ "});", landing_url))); - // Note that this runs with a user gesture. - ASSERT_EQ(true, content::EvalJs( - browser()->tab_strip_model()->GetActiveWebContents(), - "let portal = document.querySelector('portal');" - "portal.activate().then(() => { return true; });")); + std::vector<content::WebContents*> inner_web_contents = + browser() + ->tab_strip_model() + ->GetActiveWebContents() + ->GetInnerWebContents(); + ASSERT_EQ(1u, inner_web_contents.size()); + content::WebContents* portal_contents = inner_web_contents[0]; + + PortalActivationWaiter activation_waiter(portal_contents); + ASSERT_TRUE( + content::ExecJs(browser()->tab_strip_model()->GetActiveWebContents(), + "document.querySelector('portal').activate();")); + activation_waiter.Wait(); ClickTestLink("download_on_landing_page", 1, landing_url); @@ -2744,19 +2780,19 @@ true, // has_committed false, // has_server_redirect nav_list->Get(0)); - VerifyNavigationEvent(GURL(), // source_url - GURL(), // source_main_frame_url - landing_url, // original_request_url - landing_url, // destination_url - false, // is_user_initiated, - true, // has_committed - false, // has_server_redirect - nav_list->Get(1)); VerifyNavigationEvent(initial_url, // source_url initial_url, // source_main_frame_url landing_url, // original_request_url landing_url, // destination_url true, // is_user_initiated, + false, // has_committed + false, // has_server_redirect + nav_list->Get(1)); + VerifyNavigationEvent(GURL(), // source_url + GURL(), // source_main_frame_url + landing_url, // original_request_url + landing_url, // destination_url + false, // is_user_initiated, true, // has_committed false, // has_server_redirect nav_list->Get(2)); @@ -2808,4 +2844,144 @@ referrer_chain.Get(2)); } +// Click a link which creates a portal which redirects to the landing page and +// is then activated, and then click on the landing page to trigger the +// download. The redirect within the portal before it was activated should be +// reflected in the referrer chain. +IN_PROC_BROWSER_TEST_F(SBNavigationObserverPortalBrowserTest, + RedirectInPortalThenActivate) { + GURL initial_url = embedded_test_server()->GetURL(kSingleFrameTestURL); + GURL redirect_to_landing_url = + embedded_test_server()->GetURL(kRedirectToLandingURL); + GURL landing_url = embedded_test_server()->GetURL(kLandingURL); + GURL download_url = embedded_test_server()->GetURL(kDownloadItemURL); + ui_test_utils::NavigateToURL(browser(), initial_url); + + content::TestNavigationObserver redirect_observer(landing_url); + redirect_observer.StartWatchingNewWebContents(); + + SimulateUserGesture(); + ASSERT_EQ(true, content::EvalJs( + browser()->tab_strip_model()->GetActiveWebContents(), + content::JsReplace( + "new Promise((resolve) => {" + " let portal = document.createElement('portal');" + " portal.src = $1;" + " portal.onload = () => { resolve(true); };" + " document.body.appendChild(portal);" + "});", + redirect_to_landing_url))); + + redirect_observer.Wait(); + + std::vector<content::WebContents*> inner_web_contents = + browser() + ->tab_strip_model() + ->GetActiveWebContents() + ->GetInnerWebContents(); + ASSERT_EQ(1u, inner_web_contents.size()); + content::WebContents* portal_contents = inner_web_contents[0]; + + PortalActivationWaiter activation_waiter(portal_contents); + ASSERT_TRUE( + content::ExecJs(browser()->tab_strip_model()->GetActiveWebContents(), + "document.querySelector('portal').activate();")); + activation_waiter.Wait(); + + ClickTestLink("download_on_landing_page", 1, landing_url); + + std::string test_server_ip(embedded_test_server()->host_port_pair().host()); + auto* nav_list = navigation_event_list(); + ASSERT_TRUE(nav_list); + ASSERT_EQ(5U, nav_list->Size()); + VerifyNavigationEvent(GURL(), // source_url + GURL(), // source_main_frame_url + initial_url, // original_request_url + initial_url, // destination_url + true, // is_user_initiated, + true, // has_committed + false, // has_server_redirect + nav_list->Get(0)); + VerifyNavigationEvent(initial_url, // source_url + initial_url, // source_main_frame_url + redirect_to_landing_url, // original_request_url + redirect_to_landing_url, // destination_url + true, // is_user_initiated, + false, // has_committed + false, // has_server_redirect + nav_list->Get(1)); + VerifyNavigationEvent(GURL(), // source_url + GURL(), // source_main_frame_url + redirect_to_landing_url, // original_request_url + redirect_to_landing_url, // destination_url + false, // is_user_initiated, + true, // has_committed + false, // has_server_redirect + nav_list->Get(2)); + VerifyNavigationEvent(redirect_to_landing_url, // source_url + redirect_to_landing_url, // source_main_frame_url + landing_url, // original_request_url + landing_url, // destination_url + false, // is_user_initiated, + true, // has_committed + false, // has_server_redirect + nav_list->Get(3)); + VerifyNavigationEvent(landing_url, // source_url + landing_url, // source_main_frame_url + download_url, // original_request_url + download_url, // destination_url + true, // is_user_initiated, + false, // has_committed + false, // has_server_redirect + nav_list->Get(4)); + VerifyHostToIpMap(); + + ReferrerChain referrer_chain; + IdentifyReferrerChainForDownload(GetDownload(), &referrer_chain); + EXPECT_EQ(4, referrer_chain.size()); + VerifyReferrerChainEntry( + download_url, // url + GURL(), // main_frame_url + ReferrerChainEntry::EVENT_URL, // type + test_server_ip, // ip_address + landing_url, // referrer_url + GURL(), // referrer_main_frame_url + false, // is_retargeting + std::vector<GURL>(), // server redirects + ReferrerChainEntry::RENDERER_INITIATED_WITH_USER_GESTURE, + referrer_chain.Get(0)); + VerifyReferrerChainEntry( + landing_url, // url + GURL(), // main_frame_url + ReferrerChainEntry::LANDING_PAGE, // type + test_server_ip, // ip_address + redirect_to_landing_url, // referrer_url + GURL(), // referrer_main_frame_url + false, // is_retargeting + std::vector<GURL>(), // server redirects + ReferrerChainEntry::RENDERER_INITIATED_WITHOUT_USER_GESTURE, + referrer_chain.Get(1)); + VerifyReferrerChainEntry( + redirect_to_landing_url, // url + GURL(), // main_frame_url + ReferrerChainEntry::CLIENT_REDIRECT, // type + test_server_ip, // ip_address + initial_url, // referrer_url + GURL(), // referrer_main_frame_url + true, // is_retargeting + std::vector<GURL>(), // server redirects + ReferrerChainEntry::RENDERER_INITIATED_WITH_USER_GESTURE, + referrer_chain.Get(2)); + VerifyReferrerChainEntry(initial_url, // url + GURL(), // main_frame_url + ReferrerChainEntry::LANDING_REFERRER, // type + test_server_ip, // ip_address + GURL(), // referrer_url + GURL(), // referrer_main_frame_url + false, // is_retargeting + std::vector<GURL>(), // server redirects + ReferrerChainEntry::BROWSER_INITIATED, + referrer_chain.Get(3)); +} + } // namespace safe_browsing
diff --git a/chrome/browser/share/DEPS b/chrome/browser/share/DEPS index c99df3bfc..d7aba3d 100644 --- a/chrome/browser/share/DEPS +++ b/chrome/browser/share/DEPS
@@ -12,6 +12,7 @@ "+chrome/android/java/src/org/chromium/chrome/browser/media/MediaViewerUtils.java", "+chrome/android/java/src/org/chromium/chrome/browser/modules/ModuleInstallUi.java", "+chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtils.java", + "+chrome/android/java/src/org/chromium/chrome/browser/notifications", "+chrome/android/java/src/org/chromium/chrome/browser/screenshot/EditorScreenshotTask.java", "+chrome/android/java/src/org/chromium/chrome/browser/share", "+chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java", @@ -19,9 +20,7 @@ "+components/browser_ui/notifications/android", "+components/browser_ui/share/android", "+components/browser_ui/android/bottomsheet", + "+components/infobars/android", "+content/public/android/java/src/org/chromium/content_public/browser/RenderWidgetHostView.java", "+content/public/android/java/src/org/chromium/content_public/browser/WebContents.java", - - # TODO(crbug/1090917): Remove this dependency once the STTS java code is moved. - "+chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfCoordinator.java", ]
diff --git a/chrome/browser/share/android/BUILD.gn b/chrome/browser/share/android/BUILD.gn index dd31391..524196e 100644 --- a/chrome/browser/share/android/BUILD.gn +++ b/chrome/browser/share/android/BUILD.gn
@@ -31,5 +31,11 @@ sources = [ "java/src/org/chromium/chrome/browser/share/BitmapDownloadRequest.java", "java/src/org/chromium/chrome/browser/share/qrcode/QRCodeGenerationRequest.java", + "java/src/org/chromium/chrome/browser/share/send_tab_to_self/NotificationManager.java", + "java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfAndroidBridge.java", + "java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfEntry.java", + "java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfInfoBar.java", + "java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfModelObserverBridge.java", + "java/src/org/chromium/chrome/browser/share/send_tab_to_self/TargetDeviceInfo.java", ] }
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/link_to_text/LinkToTextCoordinator.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/link_to_text/LinkToTextCoordinator.java index 50e3e1a..acfae3d5 100644 --- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/link_to_text/LinkToTextCoordinator.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/link_to_text/LinkToTextCoordinator.java
@@ -7,39 +7,49 @@ import android.content.Context; import android.net.Uri; +import org.chromium.blink.mojom.TextFragmentSelectorProducer; import org.chromium.chrome.R; import org.chromium.chrome.browser.share.ChromeShareExtras; import org.chromium.chrome.browser.share.share_sheet.ChromeOptionShareCallback; +import org.chromium.chrome.browser.tab.EmptyTabObserver; +import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.tab.TabHidingType; import org.chromium.components.browser_ui.share.ShareParams; -import org.chromium.ui.base.WindowAndroid; +import org.chromium.services.service_manager.InterfaceProvider; /** * Handles the Link To Text action in the Sharing Hub. */ -public class LinkToTextCoordinator { +public class LinkToTextCoordinator extends EmptyTabObserver { private static final String SHARE_TEXT_TEMPLATE = "\"%s\"\n%s"; private static final String TEXT_FRAGMENT_PREFIX = ":~:text="; + private static final String INVALID_SELECTOR = ""; private final Context mContext; - private final WindowAndroid mWindow; private final ChromeOptionShareCallback mChromeOptionShareCallback; private final String mVisibleUrl; private final String mSelectedText; + private final Tab mTab; - public LinkToTextCoordinator(Context context, WindowAndroid window, + private TextFragmentSelectorProducer mProducer; + private boolean mCancelRequest; + + public LinkToTextCoordinator(Context context, Tab tab, ChromeOptionShareCallback chromeOptionShareCallback, String visibleUrl, String selectedText) { mContext = context; - mWindow = window; mChromeOptionShareCallback = chromeOptionShareCallback; mVisibleUrl = visibleUrl; mSelectedText = selectedText; + mTab = tab; + mTab.addObserver(this); + mCancelRequest = false; - // TODO(1102382): Replace following line with a request to create text fragment selector and - // pass |OnSelectorReady| as callback. - onSelectorReady(""); + requestSelector(); } public void onSelectorReady(String selector) { + if (mCancelRequest) return; + String successMessage = mContext.getResources().getString(R.string.link_to_text_success_message); String failureMessage = @@ -48,9 +58,10 @@ // TODO(1102382): Consider creating SharedParams on sharesheet side. In that case there will // be no need to keep the WindowAndroid in this class. String textToShare = getTextToShare(selector); - ShareParams params = new ShareParams.Builder(mWindow, /*title=*/"", /*url=*/"") - .setText(textToShare) - .build(); + ShareParams params = + new ShareParams.Builder(mTab.getWindowAndroid(), /*title=*/"", /*url=*/"") + .setText(textToShare) + .build(); ChromeShareExtras chromeShareExtras = new ChromeShareExtras.Builder().build(); mChromeOptionShareCallback.showThirdPartyShareSheetWithMessage( @@ -58,6 +69,23 @@ System.currentTimeMillis()); } + public void requestSelector() { + if (mTab.getWebContents().getMainFrame() != mTab.getWebContents().getFocusedFrame()) { + onSelectorReady(INVALID_SELECTOR); + return; + } + + InterfaceProvider interfaces = mTab.getWebContents().getMainFrame().getRemoteInterfaces(); + mProducer = interfaces.getInterface(TextFragmentSelectorProducer.MANAGER); + mProducer.generateSelector(new TextFragmentSelectorProducer.GenerateSelectorResponse() { + @Override + public void call(String selector) { + onSelectorReady(selector); + cleanup(); + } + }); + } + public String getTextToShare(String selector) { String url = mVisibleUrl; if (!selector.isEmpty()) { @@ -67,4 +95,29 @@ } return String.format(SHARE_TEXT_TEMPLATE, mSelectedText, url); } + + // Discard results if tab is not on foreground anymore. + @Override + public void onHidden(Tab tab, @TabHidingType int type) { + cleanup(); + } + + // Discard results if tab content is changed by typing new URL in omnibox. + @Override + public void onUpdateUrl(Tab tab, String url) { + cleanup(); + } + + // Discard results if tab content crashes. + @Override + public void onCrash(Tab tab) { + cleanup(); + } + + private void cleanup() { + // TODO(gayane): Consider canceling request in renderer. + if (mProducer != null) mProducer.close(); + mCancelRequest = true; + mTab.removeObserver(this); + } } \ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/DevicePickerBottomSheetAdapter.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/DevicePickerBottomSheetAdapter.java similarity index 97% rename from chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/DevicePickerBottomSheetAdapter.java rename to chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/DevicePickerBottomSheetAdapter.java index bb0019f3..428e90e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/DevicePickerBottomSheetAdapter.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/DevicePickerBottomSheetAdapter.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.send_tab_to_self; +package org.chromium.chrome.browser.share.send_tab_to_self; import android.content.Context; import android.content.res.Resources;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/DevicePickerBottomSheetContent.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/DevicePickerBottomSheetContent.java similarity index 97% rename from chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/DevicePickerBottomSheetContent.java rename to chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/DevicePickerBottomSheetContent.java index 779f085..ef6e7f4e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/DevicePickerBottomSheetContent.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/DevicePickerBottomSheetContent.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.send_tab_to_self; +package org.chromium.chrome.browser.share.send_tab_to_self; import android.content.Context; import android.content.res.Resources; @@ -18,8 +18,8 @@ import org.chromium.base.metrics.RecordUserAction; import org.chromium.chrome.R; import org.chromium.chrome.browser.profiles.Profile; -import org.chromium.chrome.browser.send_tab_to_self.SendTabToSelfMetrics.SendTabToSelfShareClickResult; import org.chromium.chrome.browser.settings.SettingsLauncher; +import org.chromium.chrome.browser.share.send_tab_to_self.SendTabToSelfMetrics.SendTabToSelfShareClickResult; import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.ui.widget.ButtonCompat;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/NotificationManager.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/NotificationManager.java similarity index 98% rename from chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/NotificationManager.java rename to chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/NotificationManager.java index c650df6..9b19f3f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/NotificationManager.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/NotificationManager.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.send_tab_to_self; +package org.chromium.chrome.browser.share.send_tab_to_self; import android.app.AlarmManager; import android.app.Notification;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/NotificationSharedPrefManager.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/NotificationSharedPrefManager.java similarity index 98% rename from chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/NotificationSharedPrefManager.java rename to chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/NotificationSharedPrefManager.java index 1e1db15..5f9be1645 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/NotificationSharedPrefManager.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/NotificationSharedPrefManager.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.send_tab_to_self; +package org.chromium.chrome.browser.share.send_tab_to_self; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -23,7 +23,6 @@ * with all previous versions. */ public class NotificationSharedPrefManager { - // Any time the serialization of the ActiveNotification needs to change, increment this version. private static final int VERSION = 1;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/OWNERS b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/OWNERS similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/OWNERS rename to chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/OWNERS
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfAndroidBridge.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfAndroidBridge.java similarity index 98% rename from chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfAndroidBridge.java rename to chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfAndroidBridge.java index 7ea49f77..4455714 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfAndroidBridge.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfAndroidBridge.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.send_tab_to_self; +package org.chromium.chrome.browser.share.send_tab_to_self; import androidx.annotation.Nullable; @@ -164,7 +164,7 @@ } @NativeMethods - interface Natives { + public interface Natives { SendTabToSelfEntry addEntry(Profile profile, String url, String title, long navigationTime, String targetDeviceSyncCacheGuid);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfCoordinator.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfCoordinator.java similarity index 90% rename from chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfCoordinator.java rename to chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfCoordinator.java index 863e1a7..fb1c8fc7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfCoordinator.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfCoordinator.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.send_tab_to_self; +package org.chromium.chrome.browser.share.send_tab_to_self; import android.content.Context; @@ -47,8 +47,8 @@ mController.expandSheet(); } - static BottomSheetContent createBottomSheetContent(Context context, String url, String title, - long navigationTime, BottomSheetController controller, + public static BottomSheetContent createBottomSheetContent(Context context, String url, + String title, long navigationTime, BottomSheetController controller, SettingsLauncher settingsLauncher, boolean isSyncEnabled) { if (sBottomSheetContentForTesting != null) { return sBottomSheetContentForTesting;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfEntry.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfEntry.java similarity index 96% rename from chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfEntry.java rename to chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfEntry.java index 66d5795..286788c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfEntry.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfEntry.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.send_tab_to_self; +package org.chromium.chrome.browser.share.send_tab_to_self; import org.chromium.base.annotations.CalledByNative;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfInfoBar.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfInfoBar.java similarity index 95% rename from chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfInfoBar.java rename to chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfInfoBar.java index e32f8c59..75e8e2f3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfInfoBar.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfInfoBar.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.send_tab_to_self; +package org.chromium.chrome.browser.share.send_tab_to_self; import org.chromium.base.annotations.CalledByNative; import org.chromium.chrome.R;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfInfoBarController.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfInfoBarController.java similarity index 97% rename from chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfInfoBarController.java rename to chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfInfoBarController.java index a07b3dea..6e80fac5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfInfoBarController.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfInfoBarController.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.send_tab_to_self; +package org.chromium.chrome.browser.share.send_tab_to_self; import org.chromium.chrome.browser.app.ChromeActivity; import org.chromium.chrome.browser.lifecycle.Destroyable;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfMetrics.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfMetrics.java similarity index 95% rename from chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfMetrics.java rename to chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfMetrics.java index 3fb3e656..e528b06 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfMetrics.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfMetrics.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.send_tab_to_self; +package org.chromium.chrome.browser.share.send_tab_to_self; import androidx.annotation.IntDef;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfModelObserverBridge.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfModelObserverBridge.java similarity index 98% rename from chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfModelObserverBridge.java rename to chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfModelObserverBridge.java index 951009d..4e315b3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfModelObserverBridge.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfModelObserverBridge.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.send_tab_to_self; +package org.chromium.chrome.browser.share.send_tab_to_self; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/TargetDeviceInfo.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/TargetDeviceInfo.java similarity index 96% rename from chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/TargetDeviceInfo.java rename to chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/TargetDeviceInfo.java index d410ed1..e3d7c7f3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/TargetDeviceInfo.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/TargetDeviceInfo.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.send_tab_to_self; +package org.chromium.chrome.browser.share.send_tab_to_self; import androidx.annotation.IntDef;
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProvider.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProvider.java index c2da26f..014cef2 100644 --- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProvider.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProvider.java
@@ -21,12 +21,12 @@ import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.preferences.Pref; import org.chromium.chrome.browser.profiles.Profile; -import org.chromium.chrome.browser.send_tab_to_self.SendTabToSelfCoordinator; import org.chromium.chrome.browser.settings.SettingsLauncher; import org.chromium.chrome.browser.share.ChromeShareExtras; import org.chromium.chrome.browser.share.link_to_text.LinkToTextCoordinator; import org.chromium.chrome.browser.share.qrcode.QrCodeCoordinator; import org.chromium.chrome.browser.share.screenshot.ScreenshotCoordinator; +import org.chromium.chrome.browser.share.send_tab_to_self.SendTabToSelfCoordinator; import org.chromium.chrome.browser.share.share_sheet.ShareSheetPropertyModelBuilder.ContentType; import org.chromium.chrome.browser.tab.Tab; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; @@ -340,10 +340,9 @@ .setIcon(R.drawable.link, R.string.sharing_highlights) .setFeatureNameForMetrics("SharingHubAndroid.LinkToTextSelected") .setOnClickCallback((view) -> { - LinkToTextCoordinator linkToTextCoordinator = new LinkToTextCoordinator( - mActivity, mTabProvider.get().getWindowAndroid(), - mChromeOptionShareCallback, mShareParams.getUrl(), - mShareParams.getText()); + LinkToTextCoordinator linkToTextCoordinator = + new LinkToTextCoordinator(mActivity, mTabProvider.get(), + mChromeOptionShareCallback, mUrl, mShareParams.getText()); }) .build(); }
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetBottomSheetContent.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetBottomSheetContent.java index 279f068..39750e8 100644 --- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetBottomSheetContent.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetBottomSheetContent.java
@@ -5,7 +5,10 @@ package org.chromium.chrome.browser.share.share_sheet; import android.content.Context; +import android.content.res.Resources; import android.graphics.Bitmap; +import android.net.Uri; +import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -14,21 +17,32 @@ import android.widget.ImageView; import android.widget.TextView; +import androidx.annotation.ColorInt; +import androidx.annotation.Nullable; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.metrics.RecordUserAction; import org.chromium.chrome.R; +import org.chromium.chrome.browser.flags.ChromeFeatureList; +import org.chromium.chrome.browser.share.share_sheet.ShareSheetPropertyModelBuilder.ContentType; +import org.chromium.chrome.browser.ui.favicon.IconType; +import org.chromium.chrome.browser.ui.favicon.LargeIconBridge; import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent; import org.chromium.components.browser_ui.share.ShareParams; +import org.chromium.components.browser_ui.widget.RoundedIconGenerator; import org.chromium.ui.modelutil.LayoutViewBuilder; import org.chromium.ui.modelutil.MVCListAdapter.ListItem; import org.chromium.ui.modelutil.MVCListAdapter.ModelList; import org.chromium.ui.modelutil.PropertyKey; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.SimpleRecyclerViewAdapter; +import org.chromium.url.GURL; +import java.io.IOException; import java.util.List; +import java.util.Set; /** * Bottom sheet content to display a 2-row custom share sheet. @@ -36,20 +50,24 @@ class ShareSheetBottomSheetContent implements BottomSheetContent, OnItemClickListener { private static final int SHARE_SHEET_ITEM = 0; private final Context mContext; + private final LargeIconBridge mIconBridge; private final ShareSheetCoordinator mShareSheetCoordinator; - private ViewGroup mToolbarView; private ViewGroup mContentView; private ShareParams mParams; + private String mUrl; /** * Creates a ShareSheetBottomSheetContent (custom share sheet) opened from the given activity. * * @param context The context the share sheet was launched from. - * @param shareSheetCoordinator The Cooredinator that instatiated this BottomSheetContent. + * @param iconBridge The {@link LargeIconBridge} to generate the icon in the preview. + * @param shareSheetCoordinator The Coordinator that instantiated this BottomSheetContent. + * @param params The {@link ShareParams} for the current share. */ - ShareSheetBottomSheetContent( - Context context, ShareSheetCoordinator shareSheetCoordinator, ShareParams params) { + ShareSheetBottomSheetContent(Context context, LargeIconBridge iconBridge, + ShareSheetCoordinator shareSheetCoordinator, ShareParams params) { mContext = context; + mIconBridge = iconBridge; mShareSheetCoordinator = shareSheetCoordinator; mParams = params; createContentView(); @@ -66,10 +84,11 @@ * @param activity The activity the share sheet belongs to. * @param firstPartyModels The PropertyModels used to build the top row. * @param thirdPartyModels The PropertyModels used to build the bottom row. + * @param contentTypes The {@link Set} of {@link ContentType}s to build the preview. * @param message The message to show on top of the share sheet. */ void createRecyclerViews(List<PropertyModel> firstPartyModels, - List<PropertyModel> thirdPartyModels, String message) { + List<PropertyModel> thirdPartyModels, Set<Integer> contentTypes, String message) { // A success/failure message can be shown for features such as LinkToText. if (!message.isEmpty()) { TextView messageView = this.getContentView().findViewById(R.id.message); @@ -80,10 +99,7 @@ } // If there's no message to be shown, show a preview of the content to be shared. else { - TextView titleView = this.getContentView().findViewById(R.id.title_preview); - titleView.setText(mParams.getTitle()); - TextView urlView = this.getContentView().findViewById(R.id.url_preview); - urlView.setText(mParams.getUrl()); + createPreview(contentTypes); } createFirstPartyRecyclerViews(firstPartyModels); @@ -135,12 +151,130 @@ } } - void setFaviconForPreview(Bitmap icon) { + private void createPreview(Set<Integer> contentTypes) { + // Default preview is to show title + url. + String title = mParams.getTitle(); + String subtitle = mParams.getUrl(); + if (!ChromeFeatureList.isEnabled(ChromeFeatureList.CHROME_SHARING_HUB_V15)) { + fetchFavicon(mParams.getUrl()); + setTitleStyle(R.style.TextAppearance_TextMediumThick_Primary); + setTextForPreview(title, subtitle); + return; + } + + if (contentTypes.contains(ContentType.IMAGE)) { + setImageForPreviewFromUri(mParams.getFileUris().get(0)); + if (TextUtils.isEmpty(subtitle)) { + subtitle = mContext.getResources().getString( + R.string.sharing_hub_image_preview_subtitle); + } + } else if (contentTypes.contains(ContentType.OTHER_FILE_TYPE)) { + // TODO(1120093): Set file icon. + } else if (contentTypes.size() == 1 + && (contentTypes.contains(ContentType.HIGHLIGHTED_TEXT) + || contentTypes.contains(ContentType.TEXT))) { + // TODO(1120093): Set text monogram icon. + title = ""; + subtitle = mParams.getText(); + setSubtitleMaxLines(2); + } else { + fetchFavicon(mParams.getUrl()); + } + + if (contentTypes.contains(ContentType.TEXT) + && contentTypes.contains(ContentType.LINK_PAGE_NOT_VISIBLE)) { + title = mParams.getText(); + setTitleStyle(R.style.TextAppearance_TextMedium_Primary); + } else { + setTitleStyle(R.style.TextAppearance_TextMediumThick_Primary); + } + + setTextForPreview(title, subtitle); + } + + private void setImageForPreviewFromUri(Uri imageUri) { + try { + setImagePreview( + ApiCompatibilityUtils.getBitmapByUri(mContext.getContentResolver(), imageUri)); + } catch (IOException e) { + // If no image preview available, don't show a preview. + } + } + + private void setTitleStyle(int resId) { + TextView titleView = this.getContentView().findViewById(R.id.title_preview); + ApiCompatibilityUtils.setTextAppearance(titleView, resId); + } + + private void setTextForPreview(String title, String subtitle) { + TextView titleView = this.getContentView().findViewById(R.id.title_preview); + titleView.setText(title); + TextView subtitleView = this.getContentView().findViewById(R.id.subtitle_preview); + subtitleView.setText(subtitle); + + // If there is no title, have subtitleView take up the whole area. + if (TextUtils.isEmpty(title)) { + titleView.setVisibility(View.GONE); + } + } + + private void setSubtitleMaxLines(int maxLines) { + TextView subtitleView = this.getContentView().findViewById(R.id.subtitle_preview); + subtitleView.setMaxLines(maxLines); + } + + private void setImagePreview(Bitmap icon) { ImageView imageView = this.getContentView().findViewById(R.id.image_preview); imageView.setImageBitmap(icon); } /** + * Fetches the favicon for the given url. + **/ + private void fetchFavicon(String url) { + if (!url.isEmpty()) { + mUrl = url; + mIconBridge.getLargeIconForUrl(new GURL(url), + mContext.getResources().getDimensionPixelSize(R.dimen.default_favicon_min_size), + this::onFaviconAvailable); + } + } + + /** + * Passed as the callback to {@link LargeIconBridge#getLargeIconForStringUrl} + * by showShareSheetWithMessage. + */ + private void onFaviconAvailable(@Nullable Bitmap icon, @ColorInt int fallbackColor, + boolean isColorDefault, @IconType int iconType) { + // If we didn't get a favicon, generate a monogram instead + if (icon == null) { + RoundedIconGenerator iconGenerator = createRoundedIconGenerator(fallbackColor); + icon = iconGenerator.generateIconForUrl(mUrl); + // generateIconForUrl might return null if the URL is empty or the domain cannot be + // resolved. See https://crbug.com/987101 + // TODO(1120093): Handle the case where generating an icon fails. + if (icon == null) { + return; + } + } + + int size = mContext.getResources().getDimensionPixelSize( + R.dimen.sharing_hub_preview_monogram_size); + + setImagePreview(Bitmap.createScaledBitmap(icon, size, size, true)); + } + + private RoundedIconGenerator createRoundedIconGenerator(@ColorInt int iconColor) { + Resources resources = mContext.getResources(); + int iconSize = resources.getDimensionPixelSize(R.dimen.sharing_hub_preview_monogram_size); + int cornerRadius = iconSize / 2; + int textSize = + resources.getDimensionPixelSize(R.dimen.sharing_hub_preview_monogram_text_size); + + return new RoundedIconGenerator(iconSize, iconSize, cornerRadius, iconColor, textSize); + } + + /** * One-shot reporter that records the first time the user scrolls a {@link RecyclerView}. */ private static class ScrollEventReporter extends RecyclerView.OnScrollListener {
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinator.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinator.java index 99292e5..6689f69 100644 --- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinator.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinator.java
@@ -6,12 +6,9 @@ import android.app.Activity; import android.content.res.Configuration; -import android.content.res.Resources; import android.graphics.Bitmap; import android.view.View; -import androidx.annotation.ColorInt; -import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.appcompat.content.res.AppCompatResources; @@ -27,14 +24,12 @@ import org.chromium.chrome.browser.share.ChromeShareExtras; import org.chromium.chrome.browser.share.ShareHelper; import org.chromium.chrome.browser.tab.Tab; -import org.chromium.chrome.browser.ui.favicon.IconType; import org.chromium.chrome.browser.ui.favicon.LargeIconBridge; import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.browser_ui.bottomsheet.BottomSheetObserver; import org.chromium.components.browser_ui.bottomsheet.EmptyBottomSheetObserver; import org.chromium.components.browser_ui.share.ShareParams; -import org.chromium.components.browser_ui.widget.RoundedIconGenerator; import org.chromium.ui.base.WindowAndroid; import org.chromium.ui.base.WindowAndroid.ActivityStateObserver; import org.chromium.ui.modelutil.PropertyModel; @@ -140,8 +135,7 @@ } } - mBottomSheet = new ShareSheetBottomSheetContent(mActivity, this, params); - fetchFavicon(mActivity, params.getUrl()); + mBottomSheet = new ShareSheetBottomSheetContent(mActivity, mIconBridge, this, params); mShareStartTime = shareStartTime; mContentTypes = ShareSheetPropertyModelBuilder.getContentTypes(params, chromeShareExtras); @@ -150,7 +144,7 @@ List<PropertyModel> thirdPartyApps = createThirdPartyPropertyModels( mActivity, params, mContentTypes, chromeShareExtras.saveLastUsed()); - mBottomSheet.createRecyclerViews(firstPartyApps, thirdPartyApps, message); + mBottomSheet.createRecyclerViews(firstPartyApps, thirdPartyApps, mContentTypes, message); boolean shown = mBottomSheetController.requestShowContent(mBottomSheet, true); if (shown) { @@ -258,58 +252,4 @@ mBottomSheet.getThirdPartyView().requestLayout(); } - /** Fetches the favicon for the given url. **/ - void fetchFavicon(Activity activity, String url) { - if (!url.isEmpty()) { - // Update mActivity so it's non-null in onFaviconAvailable in tests. - mActivity = activity; - mUrl = url; - mIconBridge.getLargeIconForStringUrl(url, - activity.getResources().getDimensionPixelSize(R.dimen.default_favicon_min_size), - this::onFaviconAvailable); - } - } - - /** - * Passed as the callback to {@link LargeIconBridge#getLargeIconForStringUrl} - * by showShareSheetWithMessage. - */ - void onFaviconAvailable(@Nullable Bitmap icon, @ColorInt int fallbackColor, - boolean isColorDefault, @IconType int iconType) { - // If we didn't get a favicon, generate a monogram instead - if (icon == null) { - RoundedIconGenerator iconGenerator = createRoundedIconGenerator(fallbackColor); - icon = iconGenerator.generateIconForUrl(mUrl); - // generateIconForUrl might return null if the URL is empty or the domain cannot be - // resolved. See https://crbug.com/987101 - // TODO(1120093): Handle the case where generating an icon fails. - if (icon == null) { - return; - } - } - - int size = mActivity.getResources().getDimensionPixelSize( - R.dimen.sharing_hub_preview_monogram_size); - - mIconForPreview = Bitmap.createScaledBitmap(icon, size, size, true); - - if (mBottomSheet != null) { - mBottomSheet.setFaviconForPreview(mIconForPreview); - } - } - - private RoundedIconGenerator createRoundedIconGenerator(@ColorInt int iconColor) { - Resources resources = mActivity.getResources(); - int iconSize = resources.getDimensionPixelSize(R.dimen.sharing_hub_preview_monogram_size); - int cornerRadius = iconSize / 2; - int textSize = - resources.getDimensionPixelSize(R.dimen.sharing_hub_preview_monogram_text_size); - - return new RoundedIconGenerator(iconSize, iconSize, cornerRadius, iconColor, textSize); - } - - @VisibleForTesting - Bitmap getIconForPreview() { - return mIconForPreview; - } }
diff --git a/chrome/browser/share/android/java_sources.gni b/chrome/browser/share/android/java_sources.gni index 3786a33..00f7a02b 100644 --- a/chrome/browser/share/android/java_sources.gni +++ b/chrome/browser/share/android/java_sources.gni
@@ -35,6 +35,18 @@ "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetView.java", "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetViewBinder.java", "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetViewProperties.java", + "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/DevicePickerBottomSheetAdapter.java", + "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/DevicePickerBottomSheetContent.java", + "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/NotificationManager.java", + "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/NotificationSharedPrefManager.java", + "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfAndroidBridge.java", + "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfCoordinator.java", + "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfEntry.java", + "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfInfoBar.java", + "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfInfoBarController.java", + "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfMetrics.java", + "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfModelObserverBridge.java", + "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/TargetDeviceInfo.java", "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProvider.java", "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetBottomSheetContent.java", "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinator.java",
diff --git a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/link_to_text/LinkToTextCoordinatorTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/link_to_text/LinkToTextCoordinatorTest.java index f768a0cfd..2a5b5d1 100644 --- a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/link_to_text/LinkToTextCoordinatorTest.java +++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/link_to_text/LinkToTextCoordinatorTest.java
@@ -11,6 +11,7 @@ import static org.mockito.Mockito.verify; import android.app.Activity; +import android.content.Context; import androidx.test.filters.SmallTest; @@ -19,11 +20,14 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.robolectric.Robolectric; import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.chrome.browser.share.share_sheet.ChromeOptionShareCallback; +import org.chromium.chrome.browser.tab.Tab; +import org.chromium.content_public.browser.WebContents; import org.chromium.ui.base.WindowAndroid; /** @@ -31,10 +35,26 @@ */ @RunWith(BaseRobolectricTestRunner.class) public class LinkToTextCoordinatorTest { + // Mock class for |LinkToTextCoordinator| that disables |requestSelector| call. + private class MockLinkToTextCoordinator extends LinkToTextCoordinator { + public MockLinkToTextCoordinator(Context context, Tab tab, + ChromeOptionShareCallback chromeOptionShareCallback, String visibleUrl, + String selectedText) { + super(context, tab, chromeOptionShareCallback, visibleUrl, selectedText); + } + + @Override + public void requestSelector() {} + }; + @Mock private ChromeOptionShareCallback mShareCallback; @Mock private WindowAndroid mWindow; + @Mock + private Tab mTab; + @Mock + private WebContents mWebContents; private Activity mAcivity; private static final String SELECTED_TEXT = "selection"; @@ -47,6 +67,8 @@ doNothing() .when(mShareCallback) .showThirdPartyShareSheetWithMessage(anyString(), any(), any(), anyLong()); + Mockito.when(mTab.getWebContents()).thenReturn(mWebContents); + Mockito.when(mTab.getWindowAndroid()).thenReturn(mWindow); } @Test @@ -54,8 +76,8 @@ public void getTextToShareTest() { String selector = "selector"; String expectedTextToShare = "\"selection\"\nwww.example.com#:~:text=selector"; - LinkToTextCoordinator coordinator = new LinkToTextCoordinator( - mAcivity, mWindow, mShareCallback, VISIBLE_URL, SELECTED_TEXT); + MockLinkToTextCoordinator coordinator = new MockLinkToTextCoordinator( + mAcivity, mTab, mShareCallback, VISIBLE_URL, SELECTED_TEXT); Assert.assertEquals(expectedTextToShare, coordinator.getTextToShare(selector)); } @@ -64,8 +86,8 @@ public void getTextToShareTest_URLWithFragment() { String selector = "selector"; String expectedTextToShare = "\"selection\"\nwww.example.com#:~:text=selector"; - LinkToTextCoordinator coordinator = new LinkToTextCoordinator( - mAcivity, mWindow, mShareCallback, VISIBLE_URL + "#elementid", SELECTED_TEXT); + MockLinkToTextCoordinator coordinator = new MockLinkToTextCoordinator( + mAcivity, mTab, mShareCallback, VISIBLE_URL + "#elementid", SELECTED_TEXT); Assert.assertEquals(expectedTextToShare, coordinator.getTextToShare(selector)); } @@ -74,17 +96,29 @@ public void getTextToShareTest_EmptySelector() { String selector = ""; String expectedTextToShare = "\"selection\"\nwww.example.com"; - LinkToTextCoordinator coordinator = new LinkToTextCoordinator( - mAcivity, mWindow, mShareCallback, VISIBLE_URL, SELECTED_TEXT); + MockLinkToTextCoordinator coordinator = new MockLinkToTextCoordinator( + mAcivity, mTab, mShareCallback, VISIBLE_URL, SELECTED_TEXT); Assert.assertEquals(expectedTextToShare, coordinator.getTextToShare(selector)); } @Test @SmallTest public void onSelectorReadyTest() { - LinkToTextCoordinator coordinator = new LinkToTextCoordinator( - mAcivity, mWindow, mShareCallback, VISIBLE_URL, SELECTED_TEXT); + MockLinkToTextCoordinator coordinator = new MockLinkToTextCoordinator( + mAcivity, mTab, mShareCallback, VISIBLE_URL, SELECTED_TEXT); // OnSelectorReady should call back the share sheet. + coordinator.onSelectorReady("selector"); + verify(mShareCallback) + .showThirdPartyShareSheetWithMessage(anyString(), any(), any(), anyLong()); + } + + @Test + @SmallTest + public void onSelectorReadyTest_EmptySelector() { + MockLinkToTextCoordinator coordinator = new MockLinkToTextCoordinator( + mAcivity, mTab, mShareCallback, VISIBLE_URL, SELECTED_TEXT); + // OnSelectorReady should call back the share sheet. + coordinator.onSelectorReady(""); verify(mShareCallback) .showThirdPartyShareSheetWithMessage(anyString(), any(), any(), anyLong()); }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/send_tab_to_self/NotificationSharedPrefManagerTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/send_tab_to_self/NotificationSharedPrefManagerTest.java similarity index 96% rename from chrome/android/junit/src/org/chromium/chrome/browser/send_tab_to_self/NotificationSharedPrefManagerTest.java rename to chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/send_tab_to_self/NotificationSharedPrefManagerTest.java index 695f3fc4..9f6381b 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/send_tab_to_self/NotificationSharedPrefManagerTest.java +++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/send_tab_to_self/NotificationSharedPrefManagerTest.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.send_tab_to_self; +package org.chromium.chrome.browser.share.send_tab_to_self; import android.support.test.filters.SmallTest; @@ -16,7 +16,7 @@ import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; import org.chromium.chrome.browser.preferences.SharedPreferencesManager; -import org.chromium.chrome.browser.send_tab_to_self.NotificationSharedPrefManager.ActiveNotification; +import org.chromium.chrome.browser.share.send_tab_to_self.NotificationSharedPrefManager.ActiveNotification; /** Tests for NotificationSharedPrefManagerTest */ @RunWith(BaseRobolectricTestRunner.class)
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfAndroidBridgeTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfAndroidBridgeTest.java similarity index 97% rename from chrome/android/junit/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfAndroidBridgeTest.java rename to chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfAndroidBridgeTest.java index f18ab32..b39c1e7 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfAndroidBridgeTest.java +++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfAndroidBridgeTest.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.send_tab_to_self; +package org.chromium.chrome.browser.share.send_tab_to_self; import static org.mockito.AdditionalAnswers.answerVoid; import static org.mockito.Mockito.any; @@ -27,7 +27,7 @@ import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.base.test.util.JniMocker; import org.chromium.chrome.browser.profiles.Profile; -import org.chromium.chrome.browser.send_tab_to_self.TargetDeviceInfo.DeviceType; +import org.chromium.chrome.browser.share.send_tab_to_self.TargetDeviceInfo.DeviceType; import org.chromium.content_public.browser.WebContents; import java.util.Arrays;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfCoordinatorTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfCoordinatorTest.java similarity index 96% rename from chrome/android/javatests/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfCoordinatorTest.java rename to chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfCoordinatorTest.java index 94e112ee..9507e44 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfCoordinatorTest.java +++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfCoordinatorTest.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.send_tab_to_self; +package org.chromium.chrome.browser.share.send_tab_to_self; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.eq;
diff --git a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProviderTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProviderTest.java index 71ed137d..2c3a5fa 100644 --- a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProviderTest.java +++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProviderTest.java
@@ -307,16 +307,17 @@ Mockito.when(mPrefService.getBoolean(anyString())).thenReturn(printingEnabled); ShareParams shareParams = new ShareParams.Builder(null, /*title=*/"", /*url=*/"").build(); - mChromeProvidedSharingOptionsProvider = new ChromeProvidedSharingOptionsProvider(mActivity, - mTabProvider, - /*bottomSheetController=*/null, - new ShareSheetBottomSheetContent(mActivity, mShareSheetCoordinator, shareParams), - new ShareParams.Builder(null, "", "").build(), - new ChromeShareExtras.Builder().build(), - /*TabPrinterDelegate=*/null, - /*settingsLauncher=*/null, - /*syncState=*/false, - /*shareStartTime=*/0, mShareSheetCoordinator); + mChromeProvidedSharingOptionsProvider = + new ChromeProvidedSharingOptionsProvider(mActivity, mTabProvider, + /*bottomSheetController=*/null, + new ShareSheetBottomSheetContent( + mActivity, null, mShareSheetCoordinator, shareParams), + new ShareParams.Builder(null, "", "").build(), + new ChromeShareExtras.Builder().build(), + /*TabPrinterDelegate=*/null, + /*settingsLauncher=*/null, + /*syncState=*/false, + /*shareStartTime=*/0, mShareSheetCoordinator); } private void assertCorrectModelsAreInTheRightOrder(
diff --git a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetBottomSheetContentTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetBottomSheetContentTest.java new file mode 100644 index 0000000..f8e5bcc --- /dev/null +++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetBottomSheetContentTest.java
@@ -0,0 +1,226 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.share.share_sheet; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import android.app.Activity; +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.net.Uri; +import android.support.test.rule.ActivityTestRule; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.test.filters.MediumTest; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.chrome.R; +import org.chromium.chrome.browser.flags.ChromeFeatureList; +import org.chromium.chrome.browser.share.share_sheet.ShareSheetPropertyModelBuilder.ContentType; +import org.chromium.chrome.browser.ui.favicon.IconType; +import org.chromium.chrome.browser.ui.favicon.LargeIconBridge; +import org.chromium.chrome.test.ChromeBrowserTestRule; +import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.util.browser.Features; +import org.chromium.components.browser_ui.share.ShareParams; +import org.chromium.ui.test.util.DummyUiActivity; +import org.chromium.url.GURL; + +import java.util.ArrayList; + +/** + * Tests {@link ShareSheetBottomSheetContent}. + */ +@RunWith(ChromeJUnit4ClassRunner.class) +@Features.EnableFeatures({ChromeFeatureList.CHROME_SHARING_HUB_V15}) +public final class ShareSheetBottomSheetContentTest { + @Rule + public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule(); + + @Rule + public ActivityTestRule<DummyUiActivity> mActivityTestRule = + new ActivityTestRule<>(DummyUiActivity.class); + + private static final Bitmap.Config sConfig = Bitmap.Config.ALPHA_8; + private static final Uri sImageUri = Uri.parse("content://testImage.png"); + private static final String sText = "Text"; + private static final String sTitle = "Title"; + private static final String sUrl = "https://www.example.com"; + + private Activity mActivity; + private ShareParams mShareParams; + private ShareSheetBottomSheetContent mShareSheetBottomSheetContent; + + @Before + public void setUp() { + mActivity = mActivityTestRule.getActivity(); + mShareParams = new ShareParams.Builder(/*window=*/null, sTitle, sUrl) + .setText(sText) + .setFileUris(new ArrayList<>(ImmutableList.of(sImageUri))) + .build(); + + mShareSheetBottomSheetContent = new ShareSheetBottomSheetContent( + mActivity, new MockLargeIconBridge(), null, mShareParams); + } + + @Test + @MediumTest + public void createRecyclerViews_hasMessage_doesNotShowPreview() { + mShareSheetBottomSheetContent.createRecyclerViews( + ImmutableList.of(), ImmutableList.of(), ImmutableSet.of(), "message"); + + TextView titleView = + mShareSheetBottomSheetContent.getContentView().findViewById(R.id.title_preview); + TextView subtitleView = + mShareSheetBottomSheetContent.getContentView().findViewById(R.id.subtitle_preview); + ImageView imageView = + mShareSheetBottomSheetContent.getContentView().findViewById(R.id.image_preview); + assertEquals("", titleView.getText()); + assertEquals("", subtitleView.getText()); + assertNull(imageView.getDrawable()); + } + + @Test + @MediumTest + public void createRecyclerViews_imageOnlyShare() { + ShareSheetBottomSheetContent shareSheetBottomSheetContent = + new ShareSheetBottomSheetContent(mActivity, new MockLargeIconBridge(), null, + new ShareParams.Builder(/*window=*/null, /*title=*/"", /*url=*/"") + .setFileUris(new ArrayList<>(ImmutableList.of(sImageUri))) + .build()); + + shareSheetBottomSheetContent.createRecyclerViews( + ImmutableList.of(), ImmutableList.of(), ImmutableSet.of(ContentType.IMAGE), ""); + + TextView titleView = + shareSheetBottomSheetContent.getContentView().findViewById(R.id.title_preview); + TextView subtitleView = + shareSheetBottomSheetContent.getContentView().findViewById(R.id.subtitle_preview); + assertEquals("", titleView.getText()); + assertEquals(mActivity.getString(R.string.sharing_hub_image_preview_subtitle), + subtitleView.getText()); + } + + @Test + @MediumTest + public void createRecyclerViews_highlightedTextShare() { + mShareSheetBottomSheetContent.createRecyclerViews(ImmutableList.of(), ImmutableList.of(), + ImmutableSet.of(ContentType.HIGHLIGHTED_TEXT), ""); + + TextView titleView = + mShareSheetBottomSheetContent.getContentView().findViewById(R.id.title_preview); + TextView subtitleView = + mShareSheetBottomSheetContent.getContentView().findViewById(R.id.subtitle_preview); + assertEquals(View.GONE, titleView.getVisibility()); + assertEquals(mShareParams.getText(), subtitleView.getText()); + } + + @Test + @MediumTest + public void createRecyclerViews_textOnlyShare() { + mShareSheetBottomSheetContent.createRecyclerViews( + ImmutableList.of(), ImmutableList.of(), ImmutableSet.of(ContentType.TEXT), ""); + + TextView titleView = + mShareSheetBottomSheetContent.getContentView().findViewById(R.id.title_preview); + TextView subtitleView = + mShareSheetBottomSheetContent.getContentView().findViewById(R.id.subtitle_preview); + assertEquals(View.GONE, titleView.getVisibility()); + assertEquals(mShareParams.getText(), subtitleView.getText()); + } + + @Test + @MediumTest + public void createRecyclerViews_producesCorrectFavicon() { + mShareSheetBottomSheetContent.createRecyclerViews(ImmutableList.of(), ImmutableList.of(), + ImmutableSet.of(ContentType.LINK_PAGE_VISIBLE), ""); + + ImageView imageView = + mShareSheetBottomSheetContent.getContentView().findViewById(R.id.image_preview); + assertNotNull(imageView.getDrawable()); + Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap(); + int size = mActivity.getResources().getDimensionPixelSize( + R.dimen.sharing_hub_preview_monogram_size); + assertEquals(size, bitmap.getWidth()); + assertEquals(size, bitmap.getHeight()); + assertEquals(sConfig, bitmap.getConfig()); + } + + @Test + @MediumTest + public void createRecyclerViews_tabShare() { + mShareSheetBottomSheetContent.createRecyclerViews(ImmutableList.of(), ImmutableList.of(), + ImmutableSet.of(ContentType.LINK_PAGE_VISIBLE), ""); + + TextView titleView = + mShareSheetBottomSheetContent.getContentView().findViewById(R.id.title_preview); + TextView subtitleView = + mShareSheetBottomSheetContent.getContentView().findViewById(R.id.subtitle_preview); + ImageView imageView = + mShareSheetBottomSheetContent.getContentView().findViewById(R.id.image_preview); + assertEquals(mShareParams.getTitle(), titleView.getText()); + assertEquals(mShareParams.getUrl(), subtitleView.getText()); + assertNotNull(imageView.getDrawable()); + } + + @Test + @MediumTest + public void createRecyclerViews_webShareTextAndUrl() { + mShareSheetBottomSheetContent.createRecyclerViews(ImmutableList.of(), ImmutableList.of(), + ImmutableSet.of(ContentType.LINK_PAGE_NOT_VISIBLE, ContentType.TEXT), ""); + + TextView titleView = + mShareSheetBottomSheetContent.getContentView().findViewById(R.id.title_preview); + TextView subtitleView = + mShareSheetBottomSheetContent.getContentView().findViewById(R.id.subtitle_preview); + ImageView imageView = + mShareSheetBottomSheetContent.getContentView().findViewById(R.id.image_preview); + assertEquals(mShareParams.getText(), titleView.getText()); + assertEquals(mShareParams.getUrl(), subtitleView.getText()); + assertNotNull(imageView.getDrawable()); + } + + @Test + @MediumTest + public void createRecyclerViews_webShareUrl() { + ShareSheetBottomSheetContent shareSheetBottomSheetContent = + new ShareSheetBottomSheetContent(mActivity, new MockLargeIconBridge(), null, + new ShareParams.Builder(/*window=*/null, /*title=*/"", sUrl).build()); + + shareSheetBottomSheetContent.createRecyclerViews(ImmutableList.of(), ImmutableList.of(), + ImmutableSet.of(ContentType.LINK_PAGE_NOT_VISIBLE), ""); + + TextView titleView = + shareSheetBottomSheetContent.getContentView().findViewById(R.id.title_preview); + TextView subtitleView = + shareSheetBottomSheetContent.getContentView().findViewById(R.id.subtitle_preview); + ImageView imageView = + shareSheetBottomSheetContent.getContentView().findViewById(R.id.image_preview); + assertEquals(View.GONE, titleView.getVisibility()); + assertEquals(mShareParams.getUrl(), subtitleView.getText()); + assertNotNull(imageView.getDrawable()); + } + + private static class MockLargeIconBridge extends LargeIconBridge { + @Override + public boolean getLargeIconForUrl( + GURL pageUrl, int desiredSizePx, final LargeIconBridge.LargeIconCallback callback) { + callback.onLargeIconAvailable( + Bitmap.createBitmap(48, 84, sConfig), 0, false, IconType.INVALID); + return true; + } + } +}
diff --git a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinatorTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinatorTest.java index 8ea6f4b..1c699e36 100644 --- a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinatorTest.java +++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinatorTest.java
@@ -12,7 +12,6 @@ import static org.mockito.Mockito.when; import android.app.Activity; -import android.graphics.Bitmap; import android.support.test.rule.ActivityTestRule; import androidx.test.filters.MediumTest; @@ -29,8 +28,6 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher; -import org.chromium.chrome.browser.ui.favicon.IconType; -import org.chromium.chrome.browser.ui.favicon.LargeIconBridge; import org.chromium.chrome.test.ChromeBrowserTestRule; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.util.browser.Features; @@ -74,8 +71,6 @@ private Activity mActivity; private ShareSheetCoordinator mShareSheetCoordinator; - private static Bitmap.Config sConfig = Bitmap.Config.ALPHA_8; - @Before public void setUp() { mActivity = mActivityTestRule.getActivity(); @@ -99,7 +94,7 @@ .thenReturn(thirdPartyPropertyModels); mShareSheetCoordinator = new ShareSheetCoordinator(mController, mLifecycleDispatcher, null, - mPropertyModelBuilder, null, new MockLargeIconBridge(), null, false); + mPropertyModelBuilder, null, null, null, false); } @Test @@ -129,28 +124,4 @@ mActivity.getResources().getString(R.string.sharing_more_icon_label), propertyModels.get(2).get(ShareSheetItemViewProperties.LABEL)); } - - @Test - @MediumTest - public void testFetchFavicon() { - Activity activity = mActivityTestRule.getActivity(); - mShareSheetCoordinator.fetchFavicon(activity, "https://www.example.com"); - - Bitmap bitmap = mShareSheetCoordinator.getIconForPreview(); - int size = activity.getResources().getDimensionPixelSize( - R.dimen.sharing_hub_preview_monogram_size); - assertEquals(size, bitmap.getWidth()); - assertEquals(size, bitmap.getHeight()); - assertEquals(sConfig, bitmap.getConfig()); - } - - private static class MockLargeIconBridge extends LargeIconBridge { - @Override - public boolean getLargeIconForStringUrl(String pageUrl, int desiredSizePx, - final LargeIconBridge.LargeIconCallback callback) { - callback.onLargeIconAvailable( - Bitmap.createBitmap(48, 84, sConfig), 0, false, IconType.INVALID); - return true; - } - } }
diff --git a/chrome/browser/share/android/test_java_sources.gni b/chrome/browser/share/android/test_java_sources.gni index 3f5c335..a881a58 100644 --- a/chrome/browser/share/android/test_java_sources.gni +++ b/chrome/browser/share/android/test_java_sources.gni
@@ -7,7 +7,9 @@ "//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/clipboard/ClipboardImageFileProviderTest.java", "//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetSaveDelegateTest.java", "//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetViewTest.java", + "//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfCoordinatorTest.java", "//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProviderTest.java", + "//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetBottomSheetContentTest.java", "//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinatorTest.java", "//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetPropertyModelBuilderTest.java", ] @@ -15,4 +17,6 @@ share_junit_test_java_sources = [ "//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/link_to_text/LinkToTextCoordinatorTest.java", "//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetMediatorUnitTest.java", + "//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/send_tab_to_self/NotificationSharedPrefManagerTest.java", + "//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfAndroidBridgeTest.java", ]
diff --git a/chrome/browser/sharesheet/drive_share_action.cc b/chrome/browser/sharesheet/drive_share_action.cc index 018c641..ceeff8b 100644 --- a/chrome/browser/sharesheet/drive_share_action.cc +++ b/chrome/browser/sharesheet/drive_share_action.cc
@@ -28,7 +28,8 @@ } const gfx::ImageSkia DriveShareAction::GetActionIcon() { - // TODO(crbug.com/1097623): Get the icon. + // TODO(crbug.com/1127750): Update to create the Icon at the + // Sharesheet bubble view. Only get the VectorIcon here. return gfx::ImageSkia(); }
diff --git a/chrome/browser/ssl/security_state_tab_helper_browsertest.cc b/chrome/browser/ssl/security_state_tab_helper_browsertest.cc index 82a40f8..00a0bfc 100644 --- a/chrome/browser/ssl/security_state_tab_helper_browsertest.cc +++ b/chrome/browser/ssl/security_state_tab_helper_browsertest.cc
@@ -180,13 +180,6 @@ return security_state::InsecureInputEventData(); } -security_state::SecurityLevel GetLevelForPassiveMixedContent() { - return base::FeatureList::IsEnabled( - security_state::features::kPassiveMixedContentWarning) - ? security_state::WARNING - : security_state::NONE; -} - // A delegate class that allows emulating selection of a file for an // INPUT TYPE=FILE form field. class FileChooserDelegate : public content::WebContentsDelegate { @@ -778,7 +771,7 @@ https_server_.GetURL(replacement_path)); CheckSecurityInfoForSecure( browser()->tab_strip_model()->GetActiveWebContents(), - GetLevelForPassiveMixedContent(), false, true, false, + security_state::WARNING, false, true, false, false /* expect cert status error */); // Navigate to an HTTPS page that displays mixed content dynamically. @@ -798,7 +791,7 @@ EXPECT_TRUE(js_result); CheckSecurityInfoForSecure( browser()->tab_strip_model()->GetActiveWebContents(), - GetLevelForPassiveMixedContent(), false, true, false, + security_state::WARNING, false, true, false, false /* expect cert status error */); // Navigate to an HTTPS page that runs mixed content. @@ -842,7 +835,7 @@ SecurityStateTabHelperTestWithAutoupgradesDisabledAndMixedContentWarningEnabled() { feature_list.InitWithFeatures( /* enabled_features */ - {security_state::features::kPassiveMixedContentWarning}, + {}, /* disabled_features */ {blink::features::kMixedContentAutoupgrade}); } @@ -871,7 +864,7 @@ https_server_.GetURL(replacement_path)); CheckSecurityInfoForSecure( browser()->tab_strip_model()->GetActiveWebContents(), - GetLevelForPassiveMixedContent(), false, true, false, + security_state::WARNING, false, true, false, false /* expect cert status error */); // Navigate to an HTTPS page that displays mixed content dynamically. @@ -891,7 +884,7 @@ EXPECT_TRUE(js_result); CheckSecurityInfoForSecure( browser()->tab_strip_model()->GetActiveWebContents(), - GetLevelForPassiveMixedContent(), false, true, false, + security_state::WARNING, false, true, false, false /* expect cert status error */); } @@ -1634,9 +1627,7 @@ ui_test_utils::NavigateToURL(browser(), mixed_content_url); blink::SecurityStyle expected_mixed_content_security_style = - base::FeatureList::IsEnabled( - security_state::features::kPassiveMixedContentWarning) && - security_state::ShouldShowDangerTriangleForWarningLevel() + security_state::ShouldShowDangerTriangleForWarningLevel() ? blink::SecurityStyle::kInsecure : blink::SecurityStyle::kNeutral; EXPECT_EQ(expected_mixed_content_security_style, @@ -2231,8 +2222,7 @@ "i.src = 'http://example.test';" "document.body.appendChild(i);")); observer.WaitForDidChangeVisibleSecurityState(); - histograms.ExpectUniqueSample(kHistogramName, - GetLevelForPassiveMixedContent(), 1); + histograms.ExpectUniqueSample(kHistogramName, security_state::WARNING, 1); } // Navigate away and the histogram should be recorded exactly once again, when
diff --git a/chrome/browser/ssl/ssl_browsertest.cc b/chrome/browser/ssl/ssl_browsertest.cc index fbccb35e..21400af8 100644 --- a/chrome/browser/ssl/ssl_browsertest.cc +++ b/chrome/browser/ssl/ssl_browsertest.cc
@@ -234,14 +234,6 @@ SSL_INTERSTITIAL_DO_NOT_PROCEED }; -security_state::SecurityLevel GetPassiveMixedContentSecurityLevel() { - if (base::FeatureList::IsEnabled( - security_state::features::kPassiveMixedContentWarning)) { - return security_state::WARNING; - } - return security_state::NONE; -} - // This observer waits for the SSLErrorHandler to start an interstitial timer // for the given web contents. class SSLInterstitialTimerObserver { @@ -1178,7 +1170,7 @@ "document.body.appendChild(i);")); observer.WaitForDidChangeVisibleSecurityState(); ssl_test_util::CheckSecurityState(tab, CertError::NONE, - GetPassiveMixedContentSecurityLevel(), + security_state::WARNING, AuthState::DISPLAYED_INSECURE_CONTENT); // Now navigate somewhere else, and then back to the page that dynamically @@ -1209,7 +1201,7 @@ "document.body.appendChild(i);")); security_state_observer.WaitForDidChangeVisibleSecurityState(); ssl_test_util::CheckSecurityState(tab, CertError::NONE, - GetPassiveMixedContentSecurityLevel(), + security_state::WARNING, AuthState::DISPLAYED_INSECURE_CONTENT); // Initiate a same-document navigation and check that the page is still @@ -1219,7 +1211,7 @@ https_server_.GetURL("/ssl/google.html#foo")); navigation_observer.WaitForSameDocumentNavigation(); ssl_test_util::CheckSecurityState(tab, CertError::NONE, - GetPassiveMixedContentSecurityLevel(), + security_state::WARNING, AuthState::DISPLAYED_INSECURE_CONTENT); } @@ -2387,8 +2379,7 @@ ssl_test_util::CheckSecurityState( browser()->tab_strip_model()->GetActiveWebContents(), CertError::NONE, - GetPassiveMixedContentSecurityLevel(), - AuthState::DISPLAYED_INSECURE_CONTENT); + security_state::WARNING, AuthState::DISPLAYED_INSECURE_CONTENT); } // Visits a page that displays an insecure form. @@ -2718,7 +2709,7 @@ // We should now have insecure content. ssl_test_util::CheckSecurityState(tab, CertError::NONE, - GetPassiveMixedContentSecurityLevel(), + security_state::WARNING, AuthState::DISPLAYED_INSECURE_CONTENT); } @@ -2756,7 +2747,7 @@ // The new tab has insecure content. ssl_test_util::CheckSecurityState(tab2, CertError::NONE, - GetPassiveMixedContentSecurityLevel(), + security_state::WARNING, AuthState::DISPLAYED_INSECURE_CONTENT); // The original tab should not be contaminated. @@ -2833,7 +2824,7 @@ const GURL url_https = https_server_.GetURL(replacement_path); ui_test_utils::NavigateToURL(browser(), url_https); ssl_test_util::CheckSecurityState(tab, CertError::NONE, - GetPassiveMixedContentSecurityLevel(), + security_state::WARNING, AuthState::DISPLAYED_INSECURE_CONTENT); } @@ -3158,7 +3149,7 @@ run_loop.Run(); ssl_test_util::CheckSecurityState(tab, CertError::NONE, - GetPassiveMixedContentSecurityLevel(), + security_state::WARNING, AuthState::DISPLAYED_INSECURE_CONTENT); } @@ -5680,7 +5671,7 @@ EXPECT_TRUE(content::WaitForLoadStop(tab)); ssl_test_util::CheckSecurityState(tab, CertError::NONE, - GetPassiveMixedContentSecurityLevel(), + security_state::WARNING, AuthState::DISPLAYED_INSECURE_CONTENT); }
diff --git a/chrome/browser/subresource_filter/ads_intervention_manager.cc b/chrome/browser/subresource_filter/ads_intervention_manager.cc new file mode 100644 index 0000000..8b78ab1 --- /dev/null +++ b/chrome/browser/subresource_filter/ads_intervention_manager.cc
@@ -0,0 +1,71 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/subresource_filter/ads_intervention_manager.h" + +#include "base/time/default_clock.h" +#include "base/time/time.h" +#include "base/values.h" +#include "chrome/browser/subresource_filter/subresource_filter_content_settings_manager.h" +#include "components/subresource_filter/core/browser/subresource_filter_features.h" +#include "url/gurl.h" + +namespace { + +// Key into the website settings dict for last active ads violation. +const char kLastAdsViolationTimeKey[] = "LastAdsViolationTime"; +const char kLastAdsViolationKey[] = "LastAdsViolation"; + +} // namespace + +using subresource_filter::mojom::AdsViolation; + +AdsInterventionManager::AdsInterventionManager( + SubresourceFilterContentSettingsManager* settings_manager) + : settings_manager_(settings_manager), + clock_(base::DefaultClock::GetInstance()) {} + +AdsInterventionManager::~AdsInterventionManager() = default; + +void AdsInterventionManager::TriggerAdsInterventionForUrlOnSubsequentLoads( + const GURL& url, + AdsViolation ads_violation) { + std::unique_ptr<base::DictionaryValue> additional_metadata = + std::make_unique<base::DictionaryValue>(); + + double now = clock_->Now().ToDoubleT(); + additional_metadata->SetDouble(kLastAdsViolationTimeKey, now); + additional_metadata->SetInteger(kLastAdsViolationKey, + static_cast<int>(ads_violation)); + + bool activated = base::FeatureList::IsEnabled( + subresource_filter::kAdsInterventionsEnforced); + // This is a no-op if the metadata already exists for an active + // ads intervention. + settings_manager_->SetSiteMetadataBasedOnActivation( + url, activated, + SubresourceFilterContentSettingsManager::ActivationSource:: + kAdsIntervention, + std::move(additional_metadata)); +} + +base::Optional<AdsInterventionManager::LastAdsIntervention> +AdsInterventionManager::GetLastAdsIntervention(const GURL& url) const { + int ads_violation; + double last_violation_time; + // The last active ads intervention is stored in the site metadata. + std::unique_ptr<base::DictionaryValue> dict = + settings_manager_->GetSiteMetadata(url); + + if (dict && dict->GetInteger(kLastAdsViolationKey, &ads_violation) && + dict->GetDouble(kLastAdsViolationTimeKey, &last_violation_time)) { + base::TimeDelta diff = + clock_->Now() - base::Time::FromDoubleT(last_violation_time); + + return LastAdsIntervention( + {diff, static_cast<AdsViolation>(ads_violation)}); + } + + return base::nullopt; +}
diff --git a/chrome/browser/subresource_filter/ads_intervention_manager.h b/chrome/browser/subresource_filter/ads_intervention_manager.h new file mode 100644 index 0000000..9ad9d126 --- /dev/null +++ b/chrome/browser/subresource_filter/ads_intervention_manager.h
@@ -0,0 +1,80 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_SUBRESOURCE_FILTER_ADS_INTERVENTION_MANAGER_H_ +#define CHROME_BROWSER_SUBRESOURCE_FILTER_ADS_INTERVENTION_MANAGER_H_ + +#include <memory> + +#include "base/optional.h" +#include "chrome/browser/subresource_filter/subresource_filter_content_settings_manager.h" +#include "components/subresource_filter/core/mojom/subresource_filter.mojom.h" + +class GURL; + +namespace base { +class Clock; +} + +// This class tracks ads interventions that have occurred on origins and is +// bound to the user's profile. The ads intervention manager operates in two +// modes set by the feature flag kAdsInterventionsEnforced: +// 1. Dry run: Ads are not blocked on sites with ad interventions, however, +// the ads intervention manager records metrics as if ads were blocked. +// If the ads intervention manager is asked to intervene on the same URL +// in the period where we would block ads during enforcement, it will only +// record the first seen intervention. +// 2. Enforced: Ads are blocked on sites with ad interventions. +// +// The duration of an ad intervention is set by the feature flag +// kAdsInterventionDuration. +// +// This class maintain's metadata for ads interventions in the user's website +// settings. This is persisted to disk and cleared with browsing history. The +// content subresource filter manager expires ads intervention metadata after +// 7 days. As a result, kAdsInterventionDuration should be less than 7 days +// to prevent expiry from impacting metrics. The metadata is scoped to each +// url's origin. This API would ideally work with Origins insead of GURLs, +// however, downstream APIs use GURL's. +class AdsInterventionManager { + public: + // Struct representing the last triggered ads intervention. + struct LastAdsIntervention { + base::TimeDelta duration_since; + subresource_filter::mojom::AdsViolation ads_violation; + }; + + // The content_settings_manager should outlive the ads intervention manager. + // This is satisfied as the SubresourceFilterContentSettingsManager and the + // AdsInterventionManager are both bound to the profile. + explicit AdsInterventionManager( + SubresourceFilterContentSettingsManager* content_settings_manager); + ~AdsInterventionManager(); + AdsInterventionManager(const AdsInterventionManager&) = delete; + AdsInterventionManager& operator=(const AdsInterventionManager&) = delete; + + // The ads intervention manager should trigger an ads intervention on each + // subsequent page load to |url| for kAdsInterventionDuration. The active + // intervention is recorded in the user's website settings and updates + // |url| site metadata with the last active intervention. + void TriggerAdsInterventionForUrlOnSubsequentLoads( + const GURL& url, + subresource_filter::mojom::AdsViolation ads_violation); + + // Returns the last active ads intervention written to metadata, + // otherwise base::nullopt is returned. + base::Optional<LastAdsIntervention> GetLastAdsIntervention( + const GURL& url) const; + + void set_clock_for_testing(base::Clock* clock) { clock_ = clock; } + + private: + // The SubresourceFilterContentSettingsManager is guaranteed to outlive the + // AdsInterventionManager. Both are bound to the profile. + SubresourceFilterContentSettingsManager* settings_manager_ = nullptr; + + base::Clock* clock_; +}; + +#endif // CHROME_BROWSER_SUBRESOURCE_FILTER_ADS_INTERVENTION_MANAGER_H_
diff --git a/chrome/browser/subresource_filter/ads_intervention_manager_browsertest.cc b/chrome/browser/subresource_filter/ads_intervention_manager_browsertest.cc new file mode 100644 index 0000000..37bae42 --- /dev/null +++ b/chrome/browser/subresource_filter/ads_intervention_manager_browsertest.cc
@@ -0,0 +1,166 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/test/scoped_feature_list.h" +#include "base/test/simple_test_clock.h" +#include "chrome/browser/subresource_filter/ads_intervention_manager.h" +#include "chrome/browser/subresource_filter/chrome_subresource_filter_client.h" +#include "chrome/browser/subresource_filter/subresource_filter_browser_test_harness.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" +#include "components/subresource_filter/core/mojom/subresource_filter.mojom.h" +#include "content/public/test/browser_test.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +namespace subresource_filter { + +namespace { + +const char kSubresourceFilterActionsHistogram[] = "SubresourceFilter.Actions2"; + +} // namespace + +class AdsInterventionManagerTestWithEnforcement + : public SubresourceFilterBrowserTest { + public: + AdsInterventionManagerTestWithEnforcement() { + feature_list_.InitAndEnableFeature( + subresource_filter::kAdsInterventionsEnforced); + } + + private: + base::test::ScopedFeatureList feature_list_; +}; + +IN_PROC_BROWSER_TEST_F(AdsInterventionManagerTestWithEnforcement, + AdsInterventionEnforced_PageActivated) { + base::HistogramTester histogram_tester; + ChromeSubresourceFilterClient* client = + ChromeSubresourceFilterClient::FromWebContents(web_contents()); + auto test_clock = std::make_unique<base::SimpleTestClock>(); + ads_intervention_manager()->set_clock_for_testing(test_clock.get()); + + const GURL url( + GetTestUrl("subresource_filter/frame_with_included_script.html")); + ASSERT_NO_FATAL_FAILURE( + SetRulesetToDisallowURLsWithPathSuffix("included_script.js")); + + // Should not trigger activation as the URL is not on the blocklist and + // has no active ads interventions. + ui_test_utils::NavigateToURL(browser(), url); + EXPECT_TRUE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame())); + histogram_tester.ExpectBucketCount(kSubresourceFilterActionsHistogram, + SubresourceFilterAction::kUIShown, 0); + + // Trigger an ads violation and renavigate the page. Should trigger + // subresource filter activation. + client->OnAdsViolationTriggered( + web_contents()->GetMainFrame(), + mojom::AdsViolation::kMobileAdDensityByHeightAbove30); + ui_test_utils::NavigateToURL(browser(), url); + + EXPECT_FALSE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame())); + histogram_tester.ExpectBucketCount(kSubresourceFilterActionsHistogram, + SubresourceFilterAction::kUIShown, 1); + + // Advance the clock to clear the intervention. + test_clock->Advance(subresource_filter::kAdsInterventionDuration.Get()); + ui_test_utils::NavigateToURL(browser(), url); + + EXPECT_TRUE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame())); +} + +IN_PROC_BROWSER_TEST_F( + AdsInterventionManagerTestWithEnforcement, + MultipleAdsInterventions_PageActivationClearedAfterFirst) { + base::HistogramTester histogram_tester; + ChromeSubresourceFilterClient* client = + ChromeSubresourceFilterClient::FromWebContents(web_contents()); + auto test_clock = std::make_unique<base::SimpleTestClock>(); + ads_intervention_manager()->set_clock_for_testing(test_clock.get()); + + const GURL url( + GetTestUrl("subresource_filter/frame_with_included_script.html")); + ASSERT_NO_FATAL_FAILURE( + SetRulesetToDisallowURLsWithPathSuffix("included_script.js")); + + // Should not trigger activation as the URL is not on the blocklist and + // has no active ads interventions. + ui_test_utils::NavigateToURL(browser(), url); + EXPECT_TRUE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame())); + histogram_tester.ExpectBucketCount(kSubresourceFilterActionsHistogram, + SubresourceFilterAction::kUIShown, 0); + + // Trigger an ads violation and renavigate the page. Should trigger + // subresource filter activation. + client->OnAdsViolationTriggered( + web_contents()->GetMainFrame(), + mojom::AdsViolation::kMobileAdDensityByHeightAbove30); + ui_test_utils::NavigateToURL(browser(), url); + + EXPECT_FALSE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame())); + histogram_tester.ExpectBucketCount(kSubresourceFilterActionsHistogram, + SubresourceFilterAction::kUIShown, 1); + + // Advance the clock by less than kAdsInterventionDuration and trigger another + // intervention. This intervention is a no-op. + test_clock->Advance(subresource_filter::kAdsInterventionDuration.Get() - + base::TimeDelta::FromMinutes(30)); + client->OnAdsViolationTriggered( + web_contents()->GetMainFrame(), + mojom::AdsViolation::kMobileAdDensityByHeightAbove30); + + // Advance the clock to to kAdsInterventionDuration from the first + // intervention, this clear the intervention. + test_clock->Advance(base::TimeDelta::FromMinutes(30)); + ui_test_utils::NavigateToURL(browser(), url); + + EXPECT_TRUE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame())); +} + +class AdsInterventionManagerTestWithoutEnforcement + : public SubresourceFilterBrowserTest { + public: + AdsInterventionManagerTestWithoutEnforcement() { + feature_list_.InitAndDisableFeature( + subresource_filter::kAdsInterventionsEnforced); + } + + private: + base::test::ScopedFeatureList feature_list_; +}; + +IN_PROC_BROWSER_TEST_F(AdsInterventionManagerTestWithoutEnforcement, + AdsInterventionNotEnforced_NoPageActivation) { + base::HistogramTester histogram_tester; + ChromeSubresourceFilterClient* client = + ChromeSubresourceFilterClient::FromWebContents(web_contents()); + + const GURL url( + GetTestUrl("subresource_filter/frame_with_included_script.html")); + ASSERT_NO_FATAL_FAILURE( + SetRulesetToDisallowURLsWithPathSuffix("included_script.js")); + + // Should not trigger activation as the URL is not on the blocklist and + // has no active ads interventions. + ui_test_utils::NavigateToURL(browser(), url); + EXPECT_TRUE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame())); + histogram_tester.ExpectBucketCount(kSubresourceFilterActionsHistogram, + SubresourceFilterAction::kUIShown, 0); + + // Trigger an ads violation and renavigate to the page. Interventions are not + // enforced so no activation should occur. + client->OnAdsViolationTriggered( + web_contents()->GetMainFrame(), + mojom::AdsViolation::kMobileAdDensityByHeightAbove30); + ui_test_utils::NavigateToURL(browser(), url); + + EXPECT_TRUE(WasParsedScriptElementLoaded(web_contents()->GetMainFrame())); + histogram_tester.ExpectBucketCount(kSubresourceFilterActionsHistogram, + SubresourceFilterAction::kUIShown, 0); +} + +} // namespace subresource_filter
diff --git a/chrome/browser/subresource_filter/ads_intervention_manager_unittest.cc b/chrome/browser/subresource_filter/ads_intervention_manager_unittest.cc new file mode 100644 index 0000000..1d99ae3 --- /dev/null +++ b/chrome/browser/subresource_filter/ads_intervention_manager_unittest.cc
@@ -0,0 +1,80 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/subresource_filter/ads_intervention_manager.h" + +#include <memory> + +#include "base/test/simple_test_clock.h" +#include "base/time/time.h" +#include "chrome/browser/subresource_filter/subresource_filter_profile_context.h" +#include "chrome/browser/subresource_filter/subresource_filter_profile_context_factory.h" +#include "chrome/test/base/testing_profile.h" +#include "components/subresource_filter/core/mojom/subresource_filter.mojom.h" +#include "content/public/test/browser_task_environment.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +using subresource_filter::mojom::AdsViolation; + +class AdsInterventionManagerTest : public testing::Test { + public: + AdsInterventionManagerTest() = default; + AdsInterventionManagerTest(const AdsInterventionManagerTest&) = delete; + AdsInterventionManagerTest& operator=(const AdsInterventionManagerTest&) = + delete; + + void SetUp() override { + ads_intervention_manager_ = + SubresourceFilterProfileContextFactory::GetForProfile(&testing_profile_) + ->ads_intervention_manager(); + + test_clock_ = std::make_unique<base::SimpleTestClock>(); + ads_intervention_manager_->set_clock_for_testing(test_clock_.get()); + } + + base::SimpleTestClock* test_clock() { return test_clock_.get(); } + + protected: + // Owned by the testing_profile_. + AdsInterventionManager* ads_intervention_manager_ = nullptr; + + private: + content::BrowserTaskEnvironment task_environment_; + TestingProfile testing_profile_; + + std::unique_ptr<base::SimpleTestClock> test_clock_; +}; + +TEST_F(AdsInterventionManagerTest, + NoIntervention_NoActiveInterventionReturned) { + GURL url("https://example.test/"); + + base::Optional<AdsInterventionManager::LastAdsIntervention> ads_intervention = + ads_intervention_manager_->GetLastAdsIntervention(url); + EXPECT_FALSE(ads_intervention.has_value()); +} + +TEST_F(AdsInterventionManagerTest, SingleIntervention_TimeSinceMatchesClock) { + GURL url("https://example.test/"); + + ads_intervention_manager_->TriggerAdsInterventionForUrlOnSubsequentLoads( + url, AdsViolation::kMobileAdDensityByHeightAbove30); + test_clock()->Advance(base::TimeDelta::FromHours(1)); + + base::Optional<AdsInterventionManager::LastAdsIntervention> ads_intervention = + ads_intervention_manager_->GetLastAdsIntervention(url); + EXPECT_TRUE(ads_intervention.has_value()); + EXPECT_EQ(ads_intervention->ads_violation, + AdsViolation::kMobileAdDensityByHeightAbove30); + EXPECT_EQ(ads_intervention->duration_since, base::TimeDelta::FromHours(1)); + + // Advance the clock by two hours, duration since should now be 3 hours. + test_clock()->Advance(base::TimeDelta::FromHours(2)); + ads_intervention = ads_intervention_manager_->GetLastAdsIntervention(url); + EXPECT_TRUE(ads_intervention.has_value()); + EXPECT_EQ(ads_intervention->ads_violation, + AdsViolation::kMobileAdDensityByHeightAbove30); + EXPECT_EQ(ads_intervention->duration_since, base::TimeDelta::FromHours(3)); +}
diff --git a/chrome/browser/subresource_filter/chrome_subresource_filter_client.cc b/chrome/browser/subresource_filter/chrome_subresource_filter_client.cc index 86555fbc..ec11f2c4f 100644 --- a/chrome/browser/subresource_filter/chrome_subresource_filter_client.cc +++ b/chrome/browser/subresource_filter/chrome_subresource_filter_client.cc
@@ -14,6 +14,7 @@ #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" +#include "chrome/browser/subresource_filter/ads_intervention_manager.h" #include "chrome/browser/subresource_filter/subresource_filter_content_settings_manager.h" #include "chrome/browser/subresource_filter/subresource_filter_profile_context.h" #include "chrome/browser/subresource_filter/subresource_filter_profile_context_factory.h" @@ -31,6 +32,8 @@ #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 "services/metrics/public/cpp/ukm_source_id.h" #if defined(OS_ANDROID) #include "chrome/browser/ui/android/content_settings/ads_blocked_infobar_delegate.h" @@ -40,10 +43,8 @@ content::WebContents* web_contents) : content::WebContentsObserver(web_contents) { DCHECK(web_contents); - SubresourceFilterProfileContext* context = - SubresourceFilterProfileContextFactory::GetForProfile( - Profile::FromBrowserContext(web_contents->GetBrowserContext())); - settings_manager_ = context->settings_manager(); + profile_context_ = SubresourceFilterProfileContextFactory::GetForProfile( + Profile::FromBrowserContext(web_contents->GetBrowserContext())); subresource_filter::RulesetService* ruleset_service = g_browser_process->subresource_filter_ruleset_service(); @@ -94,7 +95,8 @@ return; const GURL& top_level_url = web_contents()->GetLastCommittedURL(); - if (settings_manager_->ShouldShowUIForSite(top_level_url)) { + if (profile_context_->settings_manager()->ShouldShowUIForSite( + top_level_url)) { ShowUI(top_level_url); } else { LogAction(SubresourceFilterAction::kUISuppressed); @@ -117,8 +119,26 @@ } const GURL& url(navigation_handle->GetURL()); + + base::Optional<AdsInterventionManager::LastAdsIntervention> + last_intervention = + profile_context_->ads_intervention_manager()->GetLastAdsIntervention( + url); + + // Only activate the subresource filter if we are intervening on + // ads + if (profile_context_->settings_manager()->GetSiteActivationFromMetadata( + url) && + last_intervention && + last_intervention->duration_since < + subresource_filter::kAdsInterventionDuration.Get()) { + effective_activation_level = + subresource_filter::mojom::ActivationLevel::kEnabled; + *decision = subresource_filter::ActivationDecision::ACTIVATED; + } + if (url.SchemeIsHTTPOrHTTPS()) { - settings_manager_->SetSiteMetadataBasedOnActivation( + profile_context_->settings_manager()->SetSiteMetadataBasedOnActivation( url, effective_activation_level == subresource_filter::mojom::ActivationLevel::kEnabled, @@ -126,19 +146,43 @@ kSafeBrowsing); } - if (settings_manager_->GetSitePermission(url) == CONTENT_SETTING_ALLOW) { + if (profile_context_->settings_manager()->GetSitePermission(url) == + CONTENT_SETTING_ALLOW) { if (effective_activation_level == subresource_filter::mojom::ActivationLevel::kEnabled) { *decision = subresource_filter::ActivationDecision::URL_ALLOWLISTED; } return subresource_filter::mojom::ActivationLevel::kDisabled; } + return effective_activation_level; } +void ChromeSubresourceFilterClient::OnAdsViolationTriggered( + content::RenderFrameHost* rfh, + subresource_filter::mojom::AdsViolation triggered_violation) { + // If the feature is disabled, simulate ads interventions as if we were + // enforcing on ads: do not record new interventions if we would be enforcing + // an intervention on ads already. + // TODO(https://crbug/1107998): Verify this behavior when violation signals + // and histograms are added. + const GURL& url = rfh->GetLastCommittedURL(); + base::Optional<AdsInterventionManager::LastAdsIntervention> + last_intervention = + profile_context_->ads_intervention_manager()->GetLastAdsIntervention( + url); + if (last_intervention && + last_intervention->duration_since < + subresource_filter::kAdsInterventionDuration.Get()) + return; + + profile_context_->ads_intervention_manager() + ->TriggerAdsInterventionForUrlOnSubsequentLoads(url, triggered_violation); +} + void ChromeSubresourceFilterClient::AllowlistByContentSettings( const GURL& top_level_url) { - settings_manager_->AllowlistSite(top_level_url); + profile_context_->settings_manager()->AllowlistSite(top_level_url); } void ChromeSubresourceFilterClient::ToggleForceActivationInCurrentWebContents( @@ -175,7 +219,7 @@ LogAction(SubresourceFilterAction::kUIShown); did_show_ui_for_navigation_ = true; - settings_manager_->OnDidShowUI(url); + profile_context_->settings_manager()->OnDidShowUI(url); } WEB_CONTENTS_USER_DATA_KEY_IMPL(ChromeSubresourceFilterClient)
diff --git a/chrome/browser/subresource_filter/chrome_subresource_filter_client.h b/chrome/browser/subresource_filter/chrome_subresource_filter_client.h index 3c4336a..cc150ae4 100644 --- a/chrome/browser/subresource_filter/chrome_subresource_filter_client.h +++ b/chrome/browser/subresource_filter/chrome_subresource_filter_client.h
@@ -15,7 +15,7 @@ #include "content/public/browser/web_contents_user_data.h" class GURL; -class SubresourceFilterContentSettingsManager; +class SubresourceFilterProfileContext; namespace content { class NavigationHandle; @@ -80,6 +80,9 @@ content::NavigationHandle* navigation_handle, subresource_filter::mojom::ActivationLevel initial_activation_level, subresource_filter::ActivationDecision* decision) override; + void OnAdsViolationTriggered( + content::RenderFrameHost* rfh, + subresource_filter::mojom::AdsViolation triggered_violation) override; // Should be called by devtools in response to a protocol command to enable ad // blocking in this WebContents. Should only persist while devtools is @@ -104,7 +107,7 @@ throttle_manager_; // Owned by the profile. - SubresourceFilterContentSettingsManager* settings_manager_ = nullptr; + SubresourceFilterProfileContext* profile_context_ = nullptr; bool did_show_ui_for_navigation_ = false;
diff --git a/chrome/browser/subresource_filter/subresource_filter_browser_test_harness.cc b/chrome/browser/subresource_filter/subresource_filter_browser_test_harness.cc index ca8515c..7c1c2d7 100644 --- a/chrome/browser/subresource_filter/subresource_filter_browser_test_harness.cc +++ b/chrome/browser/subresource_filter/subresource_filter_browser_test_harness.cc
@@ -72,9 +72,8 @@ ASSERT_TRUE(embedded_test_server()->Start()); - auto* factory = SubresourceFilterProfileContextFactory::GetForProfile( + profile_context_ = SubresourceFilterProfileContextFactory::GetForProfile( browser()->profile()); - settings_manager_ = factory->settings_manager(); } std::unique_ptr<TestSafeBrowsingDatabaseHelper>
diff --git a/chrome/browser/subresource_filter/subresource_filter_browser_test_harness.h b/chrome/browser/subresource_filter/subresource_filter_browser_test_harness.h index b923a0b..c24b8d1e 100644 --- a/chrome/browser/subresource_filter/subresource_filter_browser_test_harness.h +++ b/chrome/browser/subresource_filter/subresource_filter_browser_test_harness.h
@@ -11,6 +11,7 @@ #include "base/macros.h" #include "base/test/scoped_feature_list.h" +#include "chrome/browser/subresource_filter/subresource_filter_profile_context.h" #include "chrome/browser/subresource_filter/test_ruleset_publisher.h" #include "chrome/test/base/in_process_browser_test.h" #include "components/safe_browsing/core/db/util.h" @@ -32,6 +33,7 @@ } // namespace content class SubresourceFilterContentSettingsManager; +class AdsInterventionManager; class TestSafeBrowsingDatabaseHelper; namespace subresource_filter { @@ -64,7 +66,11 @@ content::WebContents* web_contents() const; SubresourceFilterContentSettingsManager* settings_manager() const { - return settings_manager_; + return profile_context_->settings_manager(); + } + + AdsInterventionManager* ads_intervention_manager() { + return profile_context_->ads_intervention_manager(); } content::RenderFrameHost* FindFrameByName(const std::string& name) const; @@ -114,7 +120,7 @@ std::unique_ptr<TestSafeBrowsingDatabaseHelper> database_helper_; // Owned by the profile. - SubresourceFilterContentSettingsManager* settings_manager_; + SubresourceFilterProfileContext* profile_context_; DISALLOW_COPY_AND_ASSIGN(SubresourceFilterBrowserTest); };
diff --git a/chrome/browser/subresource_filter/subresource_filter_browsertest.cc b/chrome/browser/subresource_filter/subresource_filter_browsertest.cc index b198d154..4a1914eb 100644 --- a/chrome/browser/subresource_filter/subresource_filter_browsertest.cc +++ b/chrome/browser/subresource_filter/subresource_filter_browsertest.cc
@@ -22,6 +22,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" +#include "base/test/simple_test_clock.h" #include "build/branding_buildflags.h" #include "build/build_config.h" #include "chrome/browser/browser_process.h"
diff --git a/chrome/browser/subresource_filter/subresource_filter_profile_context.cc b/chrome/browser/subresource_filter/subresource_filter_profile_context.cc index 756caf4..9d348ed 100644 --- a/chrome/browser/subresource_filter/subresource_filter_profile_context.cc +++ b/chrome/browser/subresource_filter/subresource_filter_profile_context.cc
@@ -4,15 +4,19 @@ #include "chrome/browser/subresource_filter/subresource_filter_profile_context.h" +#include "chrome/browser/subresource_filter/ads_intervention_manager.h" #include "chrome/browser/subresource_filter/subresource_filter_content_settings_manager.h" SubresourceFilterProfileContext::SubresourceFilterProfileContext( Profile* profile) : settings_manager_( - std::make_unique<SubresourceFilterContentSettingsManager>(profile)) {} + std::make_unique<SubresourceFilterContentSettingsManager>(profile)), + ads_intervention_manager_( + std::make_unique<AdsInterventionManager>(settings_manager_.get())) {} SubresourceFilterProfileContext::~SubresourceFilterProfileContext() {} void SubresourceFilterProfileContext::Shutdown() { settings_manager_.reset(); + ads_intervention_manager_.reset(); }
diff --git a/chrome/browser/subresource_filter/subresource_filter_profile_context.h b/chrome/browser/subresource_filter/subresource_filter_profile_context.h index 572da530c..c8836d7 100644 --- a/chrome/browser/subresource_filter/subresource_filter_profile_context.h +++ b/chrome/browser/subresource_filter/subresource_filter_profile_context.h
@@ -12,6 +12,7 @@ class Profile; class SubresourceFilterContentSettingsManager; +class AdsInterventionManager; // This class holds profile scoped context for subresource filtering. class SubresourceFilterProfileContext : public KeyedService { @@ -23,12 +24,20 @@ return settings_manager_.get(); } + AdsInterventionManager* ads_intervention_manager() { + return ads_intervention_manager_.get(); + } + private: // KeyedService: void Shutdown() override; std::unique_ptr<SubresourceFilterContentSettingsManager> settings_manager_; + // Manages ads interventions that have been triggered on previous + // navigations. + std::unique_ptr<AdsInterventionManager> ads_intervention_manager_; + DISALLOW_COPY_AND_ASSIGN(SubresourceFilterProfileContext); };
diff --git a/chrome/browser/sync/test/integration/wallet_helper.cc b/chrome/browser/sync/test/integration/wallet_helper.cc index b16aac6..2d9f9e1 100644 --- a/chrome/browser/sync/test/integration/wallet_helper.cc +++ b/chrome/browser/sync/test/integration/wallet_helper.cc
@@ -39,7 +39,6 @@ // Constants for the credit card. const int kDefaultCardExpMonth = 8; const int kDefaultCardExpYear = 2087; -const int kDefaultInstrumentId = 123; const char kDefaultCardLastFour[] = "1234"; const char kDefaultCardName[] = "Patrick Valenzuela"; const sync_pb::WalletMaskedCreditCard_WalletCardType kDefaultCardType = @@ -369,7 +368,6 @@ credit_card->set_name_on_card(kDefaultCardName); credit_card->set_status(sync_pb::WalletMaskedCreditCard::VALID); credit_card->set_type(kDefaultCardType); - credit_card->set_instrument_id(kDefaultInstrumentId); if (!billing_address_id.empty()) { credit_card->set_billing_address_id(billing_address_id); }
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 5336e8b..1d57541b 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -1017,6 +1017,8 @@ "hung_renderer/hung_renderer_core.h", "in_product_help/active_tab_tracker.cc", "in_product_help/active_tab_tracker.h", + "in_product_help/feature_promo_snooze_service.cc", + "in_product_help/feature_promo_snooze_service.h", "in_product_help/global_media_controls_in_product_help.cc", "in_product_help/global_media_controls_in_product_help.h", "in_product_help/global_media_controls_in_product_help_factory.cc", @@ -2177,10 +2179,6 @@ "webui/chromeos/drive_internals_ui.h", "webui/chromeos/edu_account_login_handler_chromeos.cc", "webui/chromeos/edu_account_login_handler_chromeos.h", - "webui/chromeos/file_manager/file_manager_page_handler.cc", - "webui/chromeos/file_manager/file_manager_page_handler.h", - "webui/chromeos/file_manager/file_manager_ui.cc", - "webui/chromeos/file_manager/file_manager_ui.h", "webui/chromeos/first_run/first_run_actor.cc", "webui/chromeos/first_run/first_run_actor.h", "webui/chromeos/first_run/first_run_handler.cc", @@ -2549,7 +2547,6 @@ "//chrome/browser/ui/webui/chromeos/add_supervision:mojo_bindings", "//chrome/browser/ui/webui/chromeos/crostini_installer:mojo_bindings", "//chrome/browser/ui/webui/chromeos/crostini_upgrader:mojo_bindings", - "//chrome/browser/ui/webui/chromeos/file_manager:mojo_bindings", "//chrome/browser/ui/webui/chromeos/machine_learning:mojo_bindings", "//chrome/browser/ui/webui/settings/chromeos/constants:mojom", "//chrome/browser/ui/webui/settings/chromeos/search:mojo_bindings", @@ -2655,6 +2652,7 @@ ] } deps += [ + "//chromeos/components/file_manager:file_manager_ui", "//chromeos/components/sample_system_web_app_ui", "//chromeos/components/telemetry_extension_ui", ]
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd index 5c2cb05b..717eac2 100644 --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -3590,6 +3590,9 @@ <message name="IDS_SHARING_HUB_OPEN_SETTINGS_LABEL" desc="Label for the open settings button."> Open Settings </message> + <message name="IDS_SHARING_HUB_IMAGE_PREVIEW_SUBTITLE" desc="Subtitle shown in the preview of Sharing Hub image shares."> + image + </message> <!-- ClickToCall --> <message name="IDS_CLICK_TO_CALL_NOTIFICATION_TEXT" desc="Text displayed in a click to call notification to call on a number.">
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SHARING_HUB_IMAGE_PREVIEW_SUBTITLE.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SHARING_HUB_IMAGE_PREVIEW_SUBTITLE.png.sha1 new file mode 100644 index 0000000..4385b497 --- /dev/null +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SHARING_HUB_IMAGE_PREVIEW_SUBTITLE.png.sha1
@@ -0,0 +1 @@ +18be3a695d8acb4116f4a896fe7b72f4f0d6b533 \ No newline at end of file
diff --git a/chrome/browser/ui/app_list/app_service/app_service_app_model_builder_unittest.cc b/chrome/browser/ui/app_list/app_service/app_service_app_model_builder_unittest.cc index ecf71ad..a166ca50 100644 --- a/chrome/browser/ui/app_list/app_service/app_service_app_model_builder_unittest.cc +++ b/chrome/browser/ui/app_list/app_service/app_service_app_model_builder_unittest.cc
@@ -8,6 +8,7 @@ #include <set> #include <string> +#include "ash/public/cpp/app_list/app_list_config.h" #include "base/files/file_path.h" #include "base/run_loop.h" #include "base/strings/string_util.h" @@ -24,6 +25,7 @@ #include "chrome/browser/chromeos/guest_os/guest_os_registry_service_factory.h" #include "chrome/browser/chromeos/plugin_vm/plugin_vm_features.h" #include "chrome/browser/chromeos/plugin_vm/plugin_vm_test_helper.h" +#include "chrome/browser/extensions/chrome_app_icon.h" #include "chrome/browser/extensions/extension_function_test_utils.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/install_tracker.h" @@ -31,10 +33,12 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/app_list/app_list_test_util.h" #include "chrome/browser/ui/app_list/chrome_app_list_item.h" +#include "chrome/browser/ui/app_list/icon_standardizer.h" #include "chrome/browser/ui/app_list/internal_app/internal_app_metadata.h" #include "chrome/browser/ui/app_list/test/fake_app_list_model_updater.h" #include "chrome/browser/ui/app_list/test/test_app_list_controller_delegate.h" #include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h" +#include "chrome/browser/web_applications/components/app_icon_manager.h" #include "chrome/browser/web_applications/test/test_web_app_provider.h" #include "chrome/browser/web_applications/test/web_app_test.h" #include "chrome/browser/web_applications/web_app_provider.h" @@ -45,9 +49,13 @@ #include "chromeos/dbus/dbus_thread_manager.h" #include "components/services/app_service/public/mojom/types.mojom-shared.h" #include "components/services/app_service/public/mojom/types.mojom.h" +#include "content/public/test/test_utils.h" +#include "extensions/browser/image_loader.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/gfx/image/image_skia_operations.h" +#include "ui/gfx/image/image_unittest_util.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/extensions/extension_constants.h" @@ -139,6 +147,31 @@ }); } +void WaitForIconUpdates(ChromeAppListItem* item) { + ASSERT_TRUE(item); + do { + content::RunAllTasksUntilIdle(); + } while (item->icon().isNull()); +} + +void VerifyIcon(const gfx::ImageSkia& src, const gfx::ImageSkia& dst) { + ASSERT_FALSE(src.isNull()); + ASSERT_FALSE(dst.isNull()); + + const std::vector<ui::ScaleFactor>& scale_factors = + ui::GetSupportedScaleFactors(); + ASSERT_EQ(2U, scale_factors.size()); + + for (auto& scale_factor : scale_factors) { + const float scale = ui::GetScaleForScaleFactor(scale_factor); + ASSERT_TRUE(src.HasRepresentation(scale)); + ASSERT_TRUE(dst.HasRepresentation(scale)); + ASSERT_TRUE( + gfx::test::AreBitmapsEqual(src.GetRepresentation(scale).GetBitmap(), + dst.GetRepresentation(scale).GetBitmap())); + } +} + } // namespace class AppServiceAppModelBuilderTest @@ -224,6 +257,33 @@ model_updater_.get()); } + void GenerateExtensionAppIcon(const std::string app_id, + gfx::ImageSkia& output_image_skia) { + extensions::ExtensionRegistry* registry = + extensions::ExtensionRegistry::Get(profile()); + ASSERT_TRUE(registry); + const extensions::Extension* extension = + registry->GetInstalledExtension(app_id); + ASSERT_TRUE(extension); + + base::RunLoop run_loop; + int size_in_dip = ash::AppListConfig::instance().grid_icon_dimension(); + extensions::ImageLoader::Get(profile())->LoadImageAtEveryScaleFactorAsync( + extension, gfx::Size(size_in_dip, size_in_dip), + base::BindOnce( + [](gfx::ImageSkia* image_skia, + base::OnceClosure load_app_icon_callback, + const gfx::Image& image) { + *image_skia = image.AsImageSkia(); + std::move(load_app_icon_callback).Run(); + }, + &output_image_skia, run_loop.QuitClosure())); + run_loop.Run(); + + if (base::FeatureList::IsEnabled(features::kAppServiceAdaptiveIcon)) + output_image_skia = app_list::CreateStandardIconImage(output_image_skia); + } + std::vector<std::string> default_apps_; }; @@ -250,6 +310,71 @@ RemoveApps(apps::mojom::AppType::kWeb, testing_profile(), model_updater_.get()); } + + std::string CreateWebApp(const std::string& app_name) { + const GURL kAppUrl("https://example.com/"); + + auto web_app_info = std::make_unique<WebApplicationInfo>(); + web_app_info->title = base::UTF8ToUTF16(app_name); + web_app_info->app_url = kAppUrl; + web_app_info->scope = kAppUrl; + web_app_info->open_as_window = true; + + return web_app::InstallWebApp(profile(), std::move(web_app_info)); + } + + void GenerateWebAppIcon(const std::string& app_id, + gfx::ImageSkia& output_image_skia) { + std::vector<int> icon_sizes_in_px; + apps::ScaleToSize scale_to_size_in_px; + int size_in_dip = ash::AppListConfig::instance().grid_icon_dimension(); + for (auto scale_factor : ui::GetSupportedScaleFactors()) { + int size_in_px = + gfx::ScaleToFlooredSize(gfx::Size(size_in_dip, size_in_dip), + ui::GetScaleForScaleFactor(scale_factor)) + .width(); + scale_to_size_in_px[ui::GetScaleForScaleFactor(scale_factor)] = + size_in_px; + icon_sizes_in_px.emplace_back(size_in_px); + } + + web_app::WebAppProvider* web_app_provider = + web_app::WebAppProvider::Get(profile()); + ASSERT_TRUE(web_app_provider); + + base::RunLoop run_loop; + IconPurpose icon_purpose = IconPurpose::ANY; + web_app_provider->icon_manager().ReadIcons( + app_id, icon_purpose, icon_sizes_in_px, + base::BindOnce( + [](gfx::ImageSkia* image_skia, + std::map<float, int> scale_to_size_in_px, + base::OnceClosure load_app_icon_callback, + std::map<SquareSizePx, SkBitmap> icon_bitmaps) { + for (auto it : scale_to_size_in_px) { + image_skia->AddRepresentation( + gfx::ImageSkiaRep(icon_bitmaps[it.second], it.first)); + } + std::move(load_app_icon_callback).Run(); + }, + &output_image_skia, scale_to_size_in_px, run_loop.QuitClosure())); + run_loop.Run(); + + if (base::FeatureList::IsEnabled(features::kAppServiceAdaptiveIcon)) { + output_image_skia = gfx::ImageSkiaOperations::CreateMaskedImage( + output_image_skia, apps::LoadMaskImage(scale_to_size_in_px)); + } + + extensions::ChromeAppIcon::ApplyEffects( + size_in_dip, extensions::ChromeAppIcon::ResizeFunction(), + true /* app_launchable */, true /* from_bookmark */, + extensions::ChromeAppIcon::Badge::kNone, &output_image_skia); + for (auto scale_factor : ui::GetSupportedScaleFactors()) { + // Force the icon to be loaded. + output_image_skia.GetRepresentation( + ui::GetScaleForScaleFactor(scale_factor)); + } + } }; TEST_P(BuiltInAppTest, Build) { @@ -441,6 +566,17 @@ CreateBuilder(); } +TEST_P(ExtensionAppTest, LoadIcon) { + // Generate the source icon for comparing. + gfx::ImageSkia src_image_skia; + GenerateExtensionAppIcon(kPackagedApp1Id, src_image_skia); + + auto* item = model_updater_->FindItem(kPackagedApp1Id); + WaitForIconUpdates(item); + + VerifyIcon(src_image_skia, item->icon()); +} + // This test adds a bookmark app to the app list. TEST_P(BookmarkAppBuilderTest, BookmarkAppList) { const std::string kAppName = "Bookmark App"; @@ -470,27 +606,32 @@ // This test adds a web app to the app list. TEST_P(WebAppBuilderTest, WebAppList) { - Profile* const profile = profile_.get(); - const std::string kAppName = "Web App"; - const GURL kAppUrl("https://example.com/"); - - auto web_app_info = std::make_unique<WebApplicationInfo>(); - web_app_info->title = base::UTF8ToUTF16(kAppName); - web_app_info->app_url = kAppUrl; - web_app_info->scope = kAppUrl; - web_app_info->open_as_window = true; - - const web_app::AppId app_id = - web_app::InstallWebApp(profile, std::move(web_app_info)); + CreateWebApp(kAppName); app_service_test_.SetUp(profile_.get()); - RemoveApps(apps::mojom::AppType::kWeb, profile, model_updater_.get()); + RemoveApps(apps::mojom::AppType::kWeb, profile(), model_updater_.get()); EXPECT_EQ(1u, model_updater_->ItemCount()); EXPECT_EQ((std::vector<std::string>{kAppName}), GetModelContent(model_updater_.get())); } +TEST_P(WebAppBuilderTest, LoadGeneratedIcon) { + const std::string kAppName = "Web App"; + const std::string app_id = CreateWebApp(kAppName); + + app_service_test_.FlushMojoCalls(); + + // Generate the source icon for comparing. + gfx::ImageSkia src_image_skia; + GenerateWebAppIcon(app_id, src_image_skia); + + auto* item = model_updater_->FindItem(app_id); + WaitForIconUpdates(item); + + VerifyIcon(src_image_skia, item->icon()); +} + class CrostiniAppTest : public AppServiceAppModelBuilderTest { public: CrostiniAppTest() {
diff --git a/chrome/browser/ui/ash/holding_space/holding_space_downloads_delegate.cc b/chrome/browser/ui/ash/holding_space/holding_space_downloads_delegate.cc index 78ce9f1..93393d0 100644 --- a/chrome/browser/ui/ash/holding_space/holding_space_downloads_delegate.cc +++ b/chrome/browser/ui/ash/holding_space/holding_space_downloads_delegate.cc
@@ -18,9 +18,11 @@ HoldingSpaceDownloadsDelegate::HoldingSpaceDownloadsDelegate( Profile* profile, HoldingSpaceModel* model, - ItemDownloadedCallback item_downloaded_callback) + ItemDownloadedCallback item_downloaded_callback, + DownloadsRestoredCallback downloads_restored_callback) : HoldingSpaceKeyedServiceDelegate(profile, model), - item_downloaded_callback_(item_downloaded_callback) {} + item_downloaded_callback_(item_downloaded_callback), + downloads_restored_callback_(std::move(downloads_restored_callback)) {} HoldingSpaceDownloadsDelegate::~HoldingSpaceDownloadsDelegate() = default; @@ -41,19 +43,34 @@ RemoveObservers(); } -void HoldingSpaceDownloadsDelegate::OnHoldingSpaceModelRestored() { +void HoldingSpaceDownloadsDelegate::OnPersistenceRestored() { content::DownloadManager* download_manager = download_manager_for_testing ? download_manager_for_testing : content::BrowserContext::GetDownloadManager(profile()); + if (download_manager->IsManagerInitialized()) + OnManagerInitialized(); +} + +void HoldingSpaceDownloadsDelegate::OnManagerInitialized() { + if (is_restoring_persistence()) + return; + + content::DownloadManager* download_manager = + download_manager_for_testing + ? download_manager_for_testing + : content::BrowserContext::GetDownloadManager(profile()); + + DCHECK(download_manager->IsManagerInitialized()); + download::SimpleDownloadManager::DownloadVector downloads; download_manager->GetAllDownloads(&downloads); for (auto* download : downloads) { switch (download->GetState()) { case download::DownloadItem::COMPLETE: - item_downloaded_callback_.Run(download->GetFullPath()); + OnDownloadCompleted(download); break; case download::DownloadItem::IN_PROGRESS: download_item_observer_.Add(download); @@ -64,6 +81,9 @@ break; } } + + // Notify completion of downloads restoration. + std::move(downloads_restored_callback_).Run(); } void HoldingSpaceDownloadsDelegate::ManagerGoingDown( @@ -95,7 +115,7 @@ void HoldingSpaceDownloadsDelegate::OnDownloadCompleted( download::DownloadItem* item) { - if (!is_restoring()) + if (!is_restoring_persistence()) item_downloaded_callback_.Run(item->GetFullPath()); }
diff --git a/chrome/browser/ui/ash/holding_space/holding_space_downloads_delegate.h b/chrome/browser/ui/ash/holding_space/holding_space_downloads_delegate.h index ad6b071..268c050 100644 --- a/chrome/browser/ui/ash/holding_space/holding_space_downloads_delegate.h +++ b/chrome/browser/ui/ash/holding_space/holding_space_downloads_delegate.h
@@ -26,14 +26,18 @@ public download::DownloadItem::Observer { public: // Callback to be invoked when a download is completed. Note that this - // callback will only be invoked after the holding space model is restored. + // callback will only be invoked after holding space persistence is restored. using ItemDownloadedCallback = base::RepeatingCallback<void(const base::FilePath&)>; + // Callback to invoke when all downloads have been restored to holding space. + using DownloadsRestoredCallback = base::OnceClosure; + HoldingSpaceDownloadsDelegate( Profile* profile, HoldingSpaceModel* model, - ItemDownloadedCallback item_downloaded_callback); + ItemDownloadedCallback item_downloaded_callback, + DownloadsRestoredCallback downloads_restored_callback); HoldingSpaceDownloadsDelegate(const HoldingSpaceDownloadsDelegate&) = delete; HoldingSpaceDownloadsDelegate& operator=( const HoldingSpaceDownloadsDelegate&) = delete; @@ -48,9 +52,10 @@ // HoldingSpaceKeyedServiceDelegate: void Init() override; void Shutdown() override; - void OnHoldingSpaceModelRestored() override; + void OnPersistenceRestored() override; // content::DownloadManager::Observer: + void OnManagerInitialized() override; void ManagerGoingDown(content::DownloadManager* manager) override; void OnDownloadCreated(content::DownloadManager* manager, download::DownloadItem* item) override; @@ -67,6 +72,9 @@ // Callback to invoke when a download is completed. ItemDownloadedCallback item_downloaded_callback_; + // Callback to invoke when all downloads have been restored to holding space. + DownloadsRestoredCallback downloads_restored_callback_; + ScopedObserver<content::DownloadManager, content::DownloadManager::Observer> download_manager_observer_{this};
diff --git a/chrome/browser/ui/ash/holding_space/holding_space_keyed_service.cc b/chrome/browser/ui/ash/holding_space/holding_space_keyed_service.cc index 0fb15a44..cb39ec8 100644 --- a/chrome/browser/ui/ash/holding_space/holding_space_keyed_service.cc +++ b/chrome/browser/ui/ash/holding_space/holding_space_keyed_service.cc
@@ -7,6 +7,7 @@ #include "ash/public/cpp/holding_space/holding_space_controller.h" #include "ash/public/cpp/holding_space/holding_space_image.h" #include "ash/public/cpp/holding_space/holding_space_item.h" +#include "base/barrier_closure.h" #include "base/files/file_path.h" #include "base/guid.h" #include "chrome/browser/browser_process.h" @@ -36,6 +37,14 @@ account_id_(account_id), holding_space_client_(profile), thumbnail_loader_(profile) { + // Model restoration is a multi-step process, currently consisting of a + // restoration from persistence followed by a restoration of downloads. Once + // all steps have indicated completion, `OnModelFullyRestored()` is invoked. + on_model_partially_restored_callback_ = base::BarrierClosure( + /*number_of_steps_before_fully_restored=*/2, + base::BindOnce(&HoldingSpaceKeyedService::OnModelFullyRestored, + base::Unretained(this))); + // The associated profile may not be ready yet. If it is, we can immediately // proceed with profile dependent initialization. ProfileManager* const profile_manager = GetProfileManager(); @@ -43,6 +52,7 @@ OnProfileReady(); return; } + // Otherwise we need to wait for the profile to be added. profile_manager_observer_.Add(profile_manager); } @@ -102,6 +112,12 @@ void HoldingSpaceKeyedService::AddDownload( const base::FilePath& download_file) { + const bool already_exists = + holding_space_model_.GetItem(HoldingSpaceItem::GetFileBackedItemId( + HoldingSpaceItem::Type::kDownload, download_file)); + if (already_exists) + return; + GURL file_system_url = holding_space_util::ResolveFileSystemUrl(profile_, download_file); if (file_system_url.is_empty()) @@ -133,9 +149,13 @@ void HoldingSpaceKeyedService::OnProfileReady() { // The `HoldingSpaceDownloadsDelegate` monitors the status of downloads. delegates_.push_back(std::make_unique<HoldingSpaceDownloadsDelegate>( - profile_, &holding_space_model_, /*item_downloaded_callback=*/ + profile_, &holding_space_model_, + /*item_downloaded_callback=*/ base::BindRepeating(&HoldingSpaceKeyedService::AddDownload, - weak_factory_.GetWeakPtr()))); + weak_factory_.GetWeakPtr()), + /*downloads_restored_callback=*/ + base::BindOnce(&HoldingSpaceKeyedService::OnDownloadsRestored, + weak_factory_.GetWeakPtr()))); // The `HoldingSpaceFileSystemDelegate` monitors the file system for changes. delegates_.push_back(std::make_unique<HoldingSpaceFileSystemDelegate>( @@ -150,8 +170,8 @@ /*item_restored_callback=*/ base::BindRepeating(&HoldingSpaceKeyedService::AddItem, weak_factory_.GetWeakPtr()), - /*model_restored_callback=*/ - base::BindOnce(&HoldingSpaceKeyedService::OnModelRestored, + /*persistence_restored_callback=*/ + base::BindOnce(&HoldingSpaceKeyedService::OnPersistenceRestored, weak_factory_.GetWeakPtr()))); // Initialize all delegates only after they have been added to our collection. @@ -170,10 +190,19 @@ std::cref(file_path))); } -void HoldingSpaceKeyedService::OnModelRestored() { +void HoldingSpaceKeyedService::OnDownloadsRestored() { for (auto& delegate : delegates_) - delegate->NotifyHoldingSpaceModelRestored(); + delegate->NotifyDownloadsRestored(); + on_model_partially_restored_callback_.Run(); +} +void HoldingSpaceKeyedService::OnPersistenceRestored() { + for (auto& delegate : delegates_) + delegate->NotifyPersistenceRestored(); + on_model_partially_restored_callback_.Run(); +} + +void HoldingSpaceKeyedService::OnModelFullyRestored() { HoldingSpaceController::Get()->RegisterClientAndModelForUser( account_id_, &holding_space_client_, &holding_space_model_); }
diff --git a/chrome/browser/ui/ash/holding_space/holding_space_keyed_service.h b/chrome/browser/ui/ash/holding_space/holding_space_keyed_service.h index 9390a4c..d13e4ff 100644 --- a/chrome/browser/ui/ash/holding_space/holding_space_keyed_service.h +++ b/chrome/browser/ui/ash/holding_space/holding_space_keyed_service.h
@@ -102,8 +102,15 @@ // Invoked when the specified `file_path` is removed. void OnFileRemoved(const base::FilePath& file_path); - // Invoked when the holding space model has been restored from persistence. - void OnModelRestored(); + // Invoked when all downloads have been restored to holding space. + void OnDownloadsRestored(); + + // Invoked when holding space persistence has been restored. + void OnPersistenceRestored(); + + // Invoked when the holding space model has been fully restored. This includes + // both holding space items restored from persistence as well as downloads. + void OnModelFullyRestored(); Profile* const profile_; const AccountId account_id_; @@ -118,6 +125,12 @@ // service. They operate autonomously of one another. std::vector<std::unique_ptr<HoldingSpaceKeyedServiceDelegate>> delegates_; + // A `base::BarrierClosure` that is run when the holding space model has been + // partially restored. This will occur multiple times, after restoration from + // persistence and after restoration of downloads. Once all restoration steps + // have indicated completion, `OnModelFullyRestored()` is invoked. + base::RepeatingClosure on_model_partially_restored_callback_; + ScopedObserver<ProfileManager, ProfileManagerObserver> profile_manager_observer_{this};
diff --git a/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_delegate.cc b/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_delegate.cc index 02cf558..978e02c 100644 --- a/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_delegate.cc +++ b/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_delegate.cc
@@ -21,10 +21,16 @@ void HoldingSpaceKeyedServiceDelegate::Shutdown() {} -void HoldingSpaceKeyedServiceDelegate::NotifyHoldingSpaceModelRestored() { - DCHECK(is_restoring_); - is_restoring_ = false; - OnHoldingSpaceModelRestored(); +void HoldingSpaceKeyedServiceDelegate::NotifyDownloadsRestored() { + DCHECK(is_restoring_downloads_); + is_restoring_downloads_ = false; + OnDownloadsRestored(); +} + +void HoldingSpaceKeyedServiceDelegate::NotifyPersistenceRestored() { + DCHECK(is_restoring_persistence_); + is_restoring_persistence_ = false; + OnPersistenceRestored(); } HoldingSpaceKeyedServiceDelegate::HoldingSpaceKeyedServiceDelegate( @@ -42,6 +48,8 @@ void HoldingSpaceKeyedServiceDelegate::OnHoldingSpaceItemRemoved( const HoldingSpaceItem* item) {} -void HoldingSpaceKeyedServiceDelegate::OnHoldingSpaceModelRestored() {} +void HoldingSpaceKeyedServiceDelegate::OnDownloadsRestored() {} + +void HoldingSpaceKeyedServiceDelegate::OnPersistenceRestored() {} } // namespace ash
diff --git a/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_delegate.h b/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_delegate.h index d846f7ec..64c9c96 100644 --- a/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_delegate.h +++ b/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_delegate.h
@@ -29,9 +29,13 @@ // Delegates should perform any necessary clean up. virtual void Shutdown(); - // Invoked by `HoldingSpaceKeyedService` to notify delegates when the holding - // space model has been restored from persistence. - void NotifyHoldingSpaceModelRestored(); + // Invoked by `HoldingSpaceKeyedService` to notify delegates when all + // downloads have been restored to holding space. + void NotifyDownloadsRestored(); + + // Invoked by `HoldingSpaceKeyedService` to notify delegates when holding + // space persistence has been restored. + void NotifyPersistenceRestored(); protected: HoldingSpaceKeyedServiceDelegate(Profile* profile, HoldingSpaceModel* model); @@ -42,22 +46,31 @@ // Returns the holding space model owned by `HoldingSpaceKeyedService`. const HoldingSpaceModel* model() const { return model_; } - // Returns if the holding space model is being restored from persistence. - bool is_restoring() const { return is_restoring_; } + // Returns if downloads are being restored. + bool is_restoring_downloads() const { return is_restoring_downloads_; } + + // Returns if persistence is being restored. + bool is_restoring_persistence() const { return is_restoring_persistence_; } private: // HoldingSpaceModelObserver: void OnHoldingSpaceItemAdded(const HoldingSpaceItem* item) override; void OnHoldingSpaceItemRemoved(const HoldingSpaceItem* item) override; - // Invoked when the holding space model has been restored from persistence. - virtual void OnHoldingSpaceModelRestored(); + // Invoked when all downloads have been restored to holding space. + virtual void OnDownloadsRestored(); + + // Invoked when holding space persistence has been restored. + virtual void OnPersistenceRestored(); Profile* const profile_; const HoldingSpaceModel* const model_; - // If the holding space model is being restored from persistence. - bool is_restoring_ = true; + // If downloads are being restored. + bool is_restoring_downloads_ = true; + + // If persistence is being restored. + bool is_restoring_persistence_ = true; ScopedObserver<HoldingSpaceModel, HoldingSpaceModelObserver> holding_space_model_observer_{this};
diff --git a/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_unittest.cc b/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_unittest.cc index a92ee25e..2ebf97d 100644 --- a/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_unittest.cc +++ b/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_unittest.cc
@@ -161,9 +161,12 @@ public: HoldingSpaceKeyedServiceTest() : fake_user_manager_(new chromeos::FakeChromeUserManager), - user_manager_enabler_(base::WrapUnique(fake_user_manager_)) { + user_manager_enabler_(base::WrapUnique(fake_user_manager_)), + download_manager_( + std::make_unique<testing::NiceMock<MockDownloadManager>>()) { scoped_feature_list_.InitAndEnableFeature(features::kTemporaryHoldingSpace); } + HoldingSpaceKeyedServiceTest(const HoldingSpaceKeyedServiceTest& other) = delete; HoldingSpaceKeyedServiceTest& operator=( @@ -295,9 +298,48 @@ return result; } + std::unique_ptr<download::MockDownloadItem> CreateMockDownloadItem( + base::FilePath full_file_path) { + auto item = + std::make_unique<testing::NiceMock<download::MockDownloadItem>>(); + ON_CALL(*item, GetId()).WillByDefault(testing::Return(1)); + ON_CALL(*item, GetGuid()) + .WillByDefault(testing::ReturnRefOfCopy( + std::string("14CA04AF-ECEC-4B13-8829-817477EFAB83"))); + ON_CALL(*item, GetFullPath()) + .WillByDefault(testing::ReturnRefOfCopy(full_file_path)); + ON_CALL(*item, GetURL()) + .WillByDefault(testing::ReturnRefOfCopy(GURL("foo/bar"))); + ON_CALL(*item, GetMimeType()).WillByDefault(testing::Return(std::string())); + content::DownloadItemUtils::AttachInfo(item.get(), GetProfile(), nullptr); + return item; + } + + MockDownloadManager* download_manager() { return download_manager_.get(); } + private: + // BrowserWithTestWindowTest: + void SetUp() override { + SetUpDownloadManager(); + BrowserWithTestWindowTest::SetUp(); + } + + void SetUpDownloadManager() { + // The `content::DownloadManager` needs to be set prior to initialization + // of the `HoldingSpaceDownloadsDelegate`. This must happen before the + // `HoldingSpaceKeyedService` is created for the profile under test. + MockDownloadManager* mock_download_manager = download_manager(); + HoldingSpaceDownloadsDelegate::SetDownloadManagerForTesting( + mock_download_manager); + + // Spoof initialization of the `mock_download_manager`. + ON_CALL(*mock_download_manager, IsManagerInitialized) + .WillByDefault(testing::Return(true)); + } + chromeos::FakeChromeUserManager* fake_user_manager_; user_manager::ScopedUserManager user_manager_enabler_; + std::unique_ptr<MockDownloadManager> download_manager_; base::test::ScopedFeatureList scoped_feature_list_; }; @@ -310,6 +352,9 @@ ScopedDownloadsMountPoint downloads_mount(GetProfile()); ASSERT_TRUE(downloads_mount.IsValid()); + // Wait for the holding space model. + HoldingSpaceModelAttachedWaiter(GetProfile()).Wait(); + // Verify that the holding space model gets set even if the holding space // keyed service is not explicitly created. HoldingSpaceModel* const initial_model = @@ -560,52 +605,7 @@ persisted_holding_space_items_after_restoration); } -class HoldingSpaceKeyedServiceDownloadsTest - : public HoldingSpaceKeyedServiceTest { - public: - HoldingSpaceKeyedServiceDownloadsTest() - : download_manager_( - std::make_unique<testing::NiceMock<MockDownloadManager>>()) {} - - std::unique_ptr<download::MockDownloadItem> CreateMockDownloadItem( - base::FilePath full_file_path) { - auto item = - std::make_unique<testing::NiceMock<download::MockDownloadItem>>(); - ON_CALL(*item, GetId()).WillByDefault(testing::Return(1)); - ON_CALL(*item, GetGuid()) - .WillByDefault(testing::ReturnRefOfCopy( - std::string("14CA04AF-ECEC-4B13-8829-817477EFAB83"))); - ON_CALL(*item, GetFullPath()) - .WillByDefault(testing::ReturnRefOfCopy(full_file_path)); - ON_CALL(*item, GetURL()) - .WillByDefault(testing::ReturnRefOfCopy(GURL("foo/bar"))); - ON_CALL(*item, GetMimeType()).WillByDefault(testing::Return(std::string())); - content::DownloadItemUtils::AttachInfo(item.get(), GetProfile(), nullptr); - return item; - } - - MockDownloadManager* download_manager() { return download_manager_.get(); } - - private: - // HoldingSpaceKeyedServiceTest: - void SetUp() override { - SetUpDownloadManager(); - HoldingSpaceKeyedServiceTest::SetUp(); - } - - void SetUpDownloadManager() { - // The `content::DownloadManager` needs to be set prior to initialization - // of the `HoldingSpaceDownloadsDelegate`. This must happen before the - // `HoldingSpaceKeyedService` is created for the profile under test. - MockDownloadManager* mock_download_manager = download_manager(); - HoldingSpaceDownloadsDelegate::SetDownloadManagerForTesting( - mock_download_manager); - } - - std::unique_ptr<MockDownloadManager> download_manager_; -}; - -TEST_F(HoldingSpaceKeyedServiceDownloadsTest, RetrieveHistory) { +TEST_F(HoldingSpaceKeyedServiceTest, RetrieveHistory) { TestingProfile* profile = GetProfile(); // Create a test downloads mount point. ScopedDownloadsMountPoint downloads_mount(profile); @@ -674,7 +674,7 @@ delete download_items_mock[i]; } -TEST_F(HoldingSpaceKeyedServiceDownloadsTest, AddDownloadItem) { +TEST_F(HoldingSpaceKeyedServiceTest, AddDownloadItem) { TestingProfile* profile = GetProfile(); // Create a test downloads mount point. ScopedDownloadsMountPoint downloads_mount(profile);
diff --git a/chrome/browser/ui/ash/holding_space/holding_space_persistence_delegate.cc b/chrome/browser/ui/ash/holding_space/holding_space_persistence_delegate.cc index 9e416b9..332eaed 100644 --- a/chrome/browser/ui/ash/holding_space/holding_space_persistence_delegate.cc +++ b/chrome/browser/ui/ash/holding_space/holding_space_persistence_delegate.cc
@@ -21,11 +21,12 @@ HoldingSpaceModel* model, HoldingSpaceThumbnailLoader* thumbnail_loader, ItemRestoredCallback item_restored_callback, - ModelRestoredCallback model_restored_callback) + PersistenceRestoredCallback persistence_restored_callback) : HoldingSpaceKeyedServiceDelegate(profile, model), thumbnail_loader_(thumbnail_loader), item_restored_callback_(item_restored_callback), - model_restored_callback_(std::move(model_restored_callback)) {} + persistence_restored_callback_(std::move(persistence_restored_callback)) { +} HoldingSpacePersistenceDelegate::~HoldingSpacePersistenceDelegate() = default; @@ -44,7 +45,7 @@ void HoldingSpacePersistenceDelegate::OnHoldingSpaceItemAdded( const HoldingSpaceItem* item) { - if (is_restoring()) + if (is_restoring_persistence()) return; // `kDownload` type holding space items have their own persistence mechanism. @@ -58,7 +59,7 @@ void HoldingSpacePersistenceDelegate::OnHoldingSpaceItemRemoved( const HoldingSpaceItem* item) { - if (is_restoring()) + if (is_restoring_persistence()) return; // `kDownload` type holding space items have their own persistence mechanism. @@ -73,7 +74,6 @@ }); } -// TODO(dmblack): Restore download holding space items. void HoldingSpacePersistenceDelegate::RestoreModelFromPersistence() { DCHECK(model()->items().empty()); @@ -81,9 +81,9 @@ profile()->GetPrefs()->GetList(kPersistencePath); // If persistent storage is empty we can immediately notify the callback of - // model restoration completion and quit early. + // persistence restoration completion and quit early. if (persisted_holding_space_items->GetList().empty()) { - std::move(model_restored_callback_).Run(); + std::move(persistence_restored_callback_).Run(); return; } @@ -128,8 +128,8 @@ }); } - // Notify the callback of model restoration completion. - std::move(model_restored_callback_).Run(); + // Notify completion of persistence restoration. + std::move(persistence_restored_callback_).Run(); } } // namespace ash
diff --git a/chrome/browser/ui/ash/holding_space/holding_space_persistence_delegate.h b/chrome/browser/ui/ash/holding_space/holding_space_persistence_delegate.h index 8760054..b30bedf 100644 --- a/chrome/browser/ui/ash/holding_space/holding_space_persistence_delegate.h +++ b/chrome/browser/ui/ash/holding_space/holding_space_persistence_delegate.h
@@ -37,15 +37,15 @@ using ItemRestoredCallback = base::RepeatingCallback<void(HoldingSpaceItemPtr)>; - // Callback to invoke when the model has been restored from persistence. - using ModelRestoredCallback = base::OnceClosure; + // Callback to invoke when holding space persistence has been restored. + using PersistenceRestoredCallback = base::OnceClosure; HoldingSpacePersistenceDelegate( Profile* profile, HoldingSpaceModel* model, HoldingSpaceThumbnailLoader* thumbnail_loader, ItemRestoredCallback item_restored_callback, - ModelRestoredCallback model_restored_callback); + PersistenceRestoredCallback persistence_restored_callback); HoldingSpacePersistenceDelegate(const HoldingSpacePersistenceDelegate&) = delete; HoldingSpacePersistenceDelegate& operator=( @@ -73,8 +73,8 @@ // Callback to invoke when an item has been restored from persistence. ItemRestoredCallback item_restored_callback_; - // Callback to invoke when the model has been restored from persistence. - ModelRestoredCallback model_restored_callback_; + // Callback to invoke when holding space persistence has been restored. + PersistenceRestoredCallback persistence_restored_callback_; base::WeakPtrFactory<HoldingSpacePersistenceDelegate> weak_factory_{this}; };
diff --git a/chrome/browser/ui/ash/test_session_controller.cc b/chrome/browser/ui/ash/test_session_controller.cc index f348313..c833212 100644 --- a/chrome/browser/ui/ash/test_session_controller.cc +++ b/chrome/browser/ui/ash/test_session_controller.cc
@@ -6,9 +6,17 @@ #include <utility> +#include "ash/public/cpp/session/session_observer.h" + TestSessionController::TestSessionController() = default; TestSessionController::~TestSessionController() = default; +void TestSessionController::SetScreenLocked(bool locked) { + is_screen_locked_ = locked; + for (auto& observer : observers_) + observer.OnLockStateChanged(locked); +} + void TestSessionController::SetClient(ash::SessionControllerClient* client) {} void TestSessionController::SetSessionInfo(const ash::SessionInfo& info) { @@ -77,11 +85,14 @@ const AccountId& account_id, ash::SessionActivationObserver* observer) {} -void TestSessionController::AddObserver(ash::SessionObserver* observer) {} +void TestSessionController::AddObserver(ash::SessionObserver* observer) { + observers_.AddObserver(observer); +} -void TestSessionController::RemoveObserver(ash::SessionObserver* observer) {} +void TestSessionController::RemoveObserver(ash::SessionObserver* observer) { + observers_.RemoveObserver(observer); +} bool TestSessionController::IsScreenLocked() const { - NOTIMPLEMENTED(); - return false; + return is_screen_locked_; }
diff --git a/chrome/browser/ui/ash/test_session_controller.h b/chrome/browser/ui/ash/test_session_controller.h index e872d84..e26e019 100644 --- a/chrome/browser/ui/ash/test_session_controller.h +++ b/chrome/browser/ui/ash/test_session_controller.h
@@ -10,6 +10,7 @@ #include "ash/public/cpp/session/session_controller.h" #include "base/macros.h" +#include "base/observer_list.h" #include "base/optional.h" // Test implementation of ash's SessionController interface. @@ -44,6 +45,8 @@ return set_user_session_order_count_; } + void SetScreenLocked(bool locked); + // ash::SessionController: void SetClient(ash::SessionControllerClient* client) override; void SetSessionInfo(const ash::SessionInfo& info) override; @@ -82,6 +85,8 @@ int update_user_session_count_ = 0; int lock_animation_complete_call_count_ = 0; int set_user_session_order_count_ = 0; + bool is_screen_locked_ = false; + base::ObserverList<ash::SessionObserver> observers_; DISALLOW_COPY_AND_ASSIGN(TestSessionController); };
diff --git a/chrome/browser/ui/content_settings/content_setting_bubble_model.cc b/chrome/browser/ui/content_settings/content_setting_bubble_model.cc index 36e9248..8875011 100644 --- a/chrome/browser/ui/content_settings/content_setting_bubble_model.cc +++ b/chrome/browser/ui/content_settings/content_setting_bubble_model.cc
@@ -77,6 +77,7 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/window_open_disposition.h" +#include "ui/events/event.h" #include "ui/gfx/vector_icon_types.h" #include "ui/resources/grit/ui_resources.h" @@ -793,7 +794,7 @@ void BlockedUrlAdded(int32_t id, const GURL& url) override; private: - void OnListItemClicked(int index, int event_flags) override; + void OnListItemClicked(int index, const ui::Event& event) override; int32_t item_id_from_item_index(int index) const { return bubble_content().list_items[index].item_id; @@ -833,11 +834,11 @@ } void ContentSettingPopupBubbleModel::OnListItemClicked(int index, - int event_flags) { + const ui::Event& event) { auto* helper = blocked_content::PopupBlockerTabHelper::FromWebContents(web_contents()); helper->ShowBlockedPopup(item_id_from_item_index(index), - ui::DispositionFromEventFlags(event_flags)); + ui::DispositionFromEventFlags(event.flags())); RemoveListItem(index); content_settings::RecordPopupsAction( content_settings::POPUPS_ACTION_CLICKED_LIST_ITEM_CLICKED); @@ -1550,7 +1551,7 @@ void ContentSettingFramebustBlockBubbleModel::OnListItemClicked( int index, - int event_flags) { + const ui::Event& event) { FramebustBlockTabHelper::FromWebContents(web_contents()) ->OnBlockedUrlClicked(index); }
diff --git a/chrome/browser/ui/content_settings/content_setting_bubble_model.h b/chrome/browser/ui/content_settings/content_setting_bubble_model.h index ae133ec..296192f 100644 --- a/chrome/browser/ui/content_settings/content_setting_bubble_model.h +++ b/chrome/browser/ui/content_settings/content_setting_bubble_model.h
@@ -41,6 +41,10 @@ class RapporServiceImpl; } +namespace ui { +class Event; +} + // The hierarchy of bubble models: // // ContentSettingBubbleModel - base class @@ -182,7 +186,7 @@ void set_owner(Owner* owner) { owner_ = owner; } - virtual void OnListItemClicked(int index, int event_flags) {} + virtual void OnListItemClicked(int index, const ui::Event& event) {} virtual void OnCustomLinkClicked() {} virtual void OnManageButtonClicked() {} virtual void OnManageCheckboxChecked(bool is_checked) {} @@ -554,7 +558,7 @@ ~ContentSettingFramebustBlockBubbleModel() override; // ContentSettingBubbleModel: - void OnListItemClicked(int index, int event_flags) override; + void OnListItemClicked(int index, const ui::Event& event) override; ContentSettingFramebustBlockBubbleModel* AsFramebustBlockBubbleModel() override;
diff --git a/chrome/browser/ui/content_settings/content_setting_bubble_model_browsertest.cc b/chrome/browser/ui/content_settings/content_setting_bubble_model_browsertest.cc index d128e537..6c1f86d2 100644 --- a/chrome/browser/ui/content_settings/content_setting_bubble_model_browsertest.cc +++ b/chrome/browser/ui/content_settings/content_setting_bubble_model_browsertest.cc
@@ -35,7 +35,8 @@ #include "net/test/embedded_test_server/request_handler_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/common/features.h" -#include "ui/events/event_constants.h" +#include "ui/events/base_event_utils.h" +#include "ui/events/event.h" using content_settings::PageSpecificContentSettings; @@ -328,7 +329,11 @@ "ContentSettings.Popups", content_settings::POPUPS_ACTION_DISPLAYED_BUBBLE, 1); - model->OnListItemClicked(0, ui::EF_LEFT_MOUSE_BUTTON); + ui::MouseEvent click_event(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), + ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, + ui::EF_LEFT_MOUSE_BUTTON); + + model->OnListItemClicked(0, click_event); histograms.ExpectBucketCount( "ContentSettings.Popups", content_settings::POPUPS_ACTION_CLICKED_LIST_ITEM_CLICKED, 1);
diff --git a/chrome/browser/ui/content_settings/framebust_block_browsertest.cc b/chrome/browser/ui/content_settings/framebust_block_browsertest.cc index 3c6bee21..60a2c05 100644 --- a/chrome/browser/ui/content_settings/framebust_block_browsertest.cc +++ b/chrome/browser/ui/content_settings/framebust_block_browsertest.cc
@@ -37,7 +37,8 @@ #include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/events/event_constants.h" +#include "ui/events/base_event_utils.h" +#include "ui/events/event.h" #include "url/gurl.h" #if defined(OS_CHROMEOS) @@ -141,8 +142,10 @@ EXPECT_FALSE(clicked_url_.has_value()); content::TestNavigationObserver observer(GetWebContents()); - framebust_block_bubble_model.OnListItemClicked(/* index = */ 1, - ui::EF_LEFT_MOUSE_BUTTON); + ui::MouseEvent click_event(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), + ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, + ui::EF_LEFT_MOUSE_BUTTON); + framebust_block_bubble_model.OnListItemClicked(/* index = */ 1, click_event); observer.Wait(); EXPECT_TRUE(clicked_index_.has_value());
diff --git a/chrome/browser/ui/in_product_help/feature_promo_snooze_service.cc b/chrome/browser/ui/in_product_help/feature_promo_snooze_service.cc new file mode 100644 index 0000000..dfa5673 --- /dev/null +++ b/chrome/browser/ui/in_product_help/feature_promo_snooze_service.cc
@@ -0,0 +1,154 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/in_product_help/feature_promo_snooze_service.h" + +#include <ostream> + +#include "base/feature_list.h" +#include "base/optional.h" +#include "base/time/time.h" +#include "base/util/values/values_util.h" +#include "base/values.h" +#include "chrome/browser/profiles/profile.h" +#include "components/prefs/pref_registry_simple.h" +#include "components/prefs/scoped_user_pref_update.h" + +namespace { +// Snooze data will be saved as a dictionary in the PrefService of a profile. + +// PrefService path. +const char kIPHSnoozeDataPath[] = "in_product_help.snoozed_feature"; + +// Path to the boolean indicates if an IPH is dismissed. +// in_product_help.snoozed_feature.[iph_name].is_dismissed +constexpr char kIPHIsFeatureDismissed[] = "is_dismissed"; +// Path to the timestamp an IPH is snoozed. +// in_product_help.snoozed_feature.[iph_name].last_snooze_time +constexpr char kIPHSnoozedFeatureTime[] = "last_snooze_time"; +// Path to the duration of snooze. +// in_product_help.snoozed_feature.[iph_name].last_snooze_duration +constexpr char kIPHSnoozedFeatureDuration[] = "last_snooze_duration"; +// Path to the count of how many times this IPH has been snoozed. +// in_product_help.snoozed_feature.[iph_name].snooze_count +constexpr char kIPHSnoozedFeatureCount[] = "snooze_count"; +} // namespace + +FeaturePromoSnoozeService::FeaturePromoSnoozeService(Profile* profile) + : profile_(profile) {} + +void FeaturePromoSnoozeService::OnUserSnooze(const base::Feature& iph_feature, + base::TimeDelta snooze_duration) { + DCHECK(snooze_duration > base::TimeDelta::FromSeconds(0)); + auto snooze_data = ReadSnoozeData(iph_feature); + + if (!snooze_data) + snooze_data = SnoozeData(); + + snooze_data->last_snooze_time = base::Time::Now(); + snooze_data->last_snooze_duration = snooze_duration; + snooze_data->snooze_count++; + + SaveSnoozeData(iph_feature, *snooze_data); +} + +void FeaturePromoSnoozeService::OnUserDismiss( + const base::Feature& iph_feature) { + auto snooze_data = ReadSnoozeData(iph_feature); + + if (!snooze_data) + snooze_data = SnoozeData(); + + snooze_data->is_dismissed = true; + + SaveSnoozeData(iph_feature, *snooze_data); +} + +bool FeaturePromoSnoozeService::IsBlocked(const base::Feature& iph_feature) { + auto snooze_data = ReadSnoozeData(iph_feature); + + if (!snooze_data) + return false; + + // This IPH has been dismissed by user permanently. + if (snooze_data->is_dismissed) + return true; + + // This IPH has neither been dismissed nor snoozed. + if (snooze_data->snooze_count == 0) + return false; + + // Corruption: Snooze time is in the future. + if (snooze_data->last_snooze_time > base::Time::Now()) + return true; + + // This IPH is snoozed. Test if snooze period has expired. + return base::Time::Now() < + snooze_data->last_snooze_time + snooze_data->last_snooze_duration; +} + +// static +void FeaturePromoSnoozeService::RegisterProfilePrefs( + PrefRegistrySimple* registry) { + registry->RegisterDictionaryPref(kIPHSnoozeDataPath); +} + +void FeaturePromoSnoozeService::Reset(const base::Feature& iph_feature) { + DictionaryPrefUpdate update(profile_->GetPrefs(), kIPHSnoozeDataPath); + base::DictionaryValue* pref_data = update.Get(); + pref_data->RemovePath(iph_feature.name); +} + +base::Optional<FeaturePromoSnoozeService::SnoozeData> +FeaturePromoSnoozeService::ReadSnoozeData(const base::Feature& iph_feature) { + std::string path_prefix = std::string(iph_feature.name) + "."; + + const base::DictionaryValue* pref_data = + profile_->GetPrefs()->GetDictionary(kIPHSnoozeDataPath); + base::Optional<bool> is_dismissed = + pref_data->FindBoolPath(path_prefix + kIPHIsFeatureDismissed); + base::Optional<base::Time> snooze_time = util::ValueToTime( + pref_data->FindPath(path_prefix + kIPHSnoozedFeatureTime)); + base::Optional<int> snooze_count = + pref_data->FindIntPath(path_prefix + kIPHSnoozedFeatureCount); + base::Optional<base::TimeDelta> snooze_duration = util::ValueToTimeDelta( + pref_data->FindPath(path_prefix + kIPHSnoozedFeatureDuration)); + + base::Optional<SnoozeData> snooze_data; + + if (!is_dismissed) + return snooze_data; + + if (!snooze_time || !snooze_count || !snooze_duration) { + // IPH snooze data is corrupt. Clear data of this feature. + Reset(iph_feature); + return snooze_data; + } + + snooze_data = SnoozeData(); + snooze_data->is_dismissed = *is_dismissed; + snooze_data->last_snooze_time = *snooze_time; + snooze_data->last_snooze_duration = *snooze_duration; + snooze_data->snooze_count = *snooze_count; + + return snooze_data; +} + +void FeaturePromoSnoozeService::SaveSnoozeData( + const base::Feature& iph_feature, + const FeaturePromoSnoozeService::SnoozeData& snooze_data) { + std::string path_prefix = std::string(iph_feature.name) + "."; + + DictionaryPrefUpdate update(profile_->GetPrefs(), kIPHSnoozeDataPath); + base::DictionaryValue* pref_data = update.Get(); + + pref_data->SetBoolPath(path_prefix + kIPHIsFeatureDismissed, + snooze_data.is_dismissed); + pref_data->SetPath(path_prefix + kIPHSnoozedFeatureTime, + util::TimeToValue(snooze_data.last_snooze_time)); + pref_data->SetPath(path_prefix + kIPHSnoozedFeatureDuration, + util::TimeDeltaToValue(snooze_data.last_snooze_duration)); + pref_data->SetIntPath(path_prefix + kIPHSnoozedFeatureCount, + snooze_data.snooze_count); +}
diff --git a/chrome/browser/ui/in_product_help/feature_promo_snooze_service.h b/chrome/browser/ui/in_product_help/feature_promo_snooze_service.h new file mode 100644 index 0000000..3403cc8c --- /dev/null +++ b/chrome/browser/ui/in_product_help/feature_promo_snooze_service.h
@@ -0,0 +1,73 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_IN_PRODUCT_HELP_FEATURE_PROMO_SNOOZE_SERVICE_H_ +#define CHROME_BROWSER_UI_IN_PRODUCT_HELP_FEATURE_PROMO_SNOOZE_SERVICE_H_ + +#include <string> +#include "base/optional.h" +#include "base/time/time.h" + +namespace base { +struct Feature; +} // namespace base + +class Profile; +class PrefRegistrySimple; + +// This service manages snooze and dismiss of in-product help promo. +// +// An IPH controller notifies this service when an IPH is snoozed or dismissed. +// When the snooze period expires, this service will approve controller's +// request to retrigger the IPH. +// If an IPH is dismissed, this service will reject controller's request. +class FeaturePromoSnoozeService { + public: + explicit FeaturePromoSnoozeService(Profile* profile); + + // Disallow copy and assign. + FeaturePromoSnoozeService(const FeaturePromoSnoozeService&) = delete; + FeaturePromoSnoozeService& operator=(const FeaturePromoSnoozeService&) = + delete; + + // The IPH controller must call this method when the user snoozes an IPH. + // The snooze duration defaults to 1 day plus 2 additional hours in hope to + // stagger busy hours in the days. + void OnUserSnooze( + const base::Feature& iph_feature, + base::TimeDelta snooze_duration = base::TimeDelta::FromHours(26)); + + // The IPH controller must call this method when the user actively dismiss an + // IPH. Don't call this method in case of a passive dismiss, i.e. auto dismiss + // after a fixed amount of time. + void OnUserDismiss(const base::Feature& iph_feature); + + // The IPH controller must call this method to check if an IPH is blocked by + // dismiss or snooze. An IPH will be approved if it is not snoozed or the + // snoozing period has timed out. + bool IsBlocked(const base::Feature& iph_feature); + + static void RegisterProfilePrefs(PrefRegistrySimple* registry); + + // Reset the state of |iph_feature|. + void Reset(const base::Feature& iph_feature); + + private: + // Snooze information dictionary saved under path + // in_product_help.snoozed_feature.[iph_name] in PerfService. + struct SnoozeData { + bool is_dismissed = false; + base::Time last_snooze_time = base::Time(); + base::TimeDelta last_snooze_duration = base::TimeDelta(); + int snooze_count = 0; + }; + + base::Optional<SnoozeData> ReadSnoozeData(const base::Feature& iph_feature); + void SaveSnoozeData(const base::Feature& iph_feature, + const SnoozeData& snooze_data); + + Profile* const profile_; +}; + +#endif // CHROME_BROWSER_UI_IN_PRODUCT_HELP_FEATURE_PROMO_SNOOZE_SERVICE_H_
diff --git a/chrome/browser/ui/in_product_help/feature_promo_snooze_service_unittest.cc b/chrome/browser/ui/in_product_help/feature_promo_snooze_service_unittest.cc new file mode 100644 index 0000000..d7cb8c8 --- /dev/null +++ b/chrome/browser/ui/in_product_help/feature_promo_snooze_service_unittest.cc
@@ -0,0 +1,76 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/in_product_help/feature_promo_snooze_service.h" + +#include <memory> + +#include "base/feature_list.h" +#include "base/test/task_environment.h" +#include "base/time/time.h" +#include "chrome/test/base/testing_profile.h" +#include "content/public/test/browser_task_environment.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { +base::Feature kTestIPHFeature{"TestIPHFeature", + base::FEATURE_ENABLED_BY_DEFAULT}; +base::Feature kTestIPHFeature2{"TestIPHFeature2", + base::FEATURE_ENABLED_BY_DEFAULT}; +} // namespace + +class FeaturePromoSnoozeServiceTest : public testing::Test { + public: + FeaturePromoSnoozeServiceTest() + : task_environment_{base::test::SingleThreadTaskEnvironment::TimeSource:: + MOCK_TIME}, + service_{&profile_} {} + + protected: + content::BrowserTaskEnvironment task_environment_; + TestingProfile profile_; + FeaturePromoSnoozeService service_; +}; + +TEST_F(FeaturePromoSnoozeServiceTest, AllowNonSnoozedIPH) { + service_.Reset(kTestIPHFeature); + EXPECT_FALSE(service_.IsBlocked(kTestIPHFeature)); +} + +TEST_F(FeaturePromoSnoozeServiceTest, BlockDismissedIPH) { + service_.Reset(kTestIPHFeature); + service_.OnUserDismiss(kTestIPHFeature); + EXPECT_TRUE(service_.IsBlocked(kTestIPHFeature)); + service_.Reset(kTestIPHFeature); + EXPECT_FALSE(service_.IsBlocked(kTestIPHFeature)); +} + +TEST_F(FeaturePromoSnoozeServiceTest, BlockSnoozedIPH) { + service_.Reset(kTestIPHFeature); + service_.OnUserSnooze(kTestIPHFeature); + EXPECT_TRUE(service_.IsBlocked(kTestIPHFeature)); +} + +TEST_F(FeaturePromoSnoozeServiceTest, ReleaseSnoozedIPH) { + service_.Reset(kTestIPHFeature); + service_.OnUserSnooze(kTestIPHFeature, base::TimeDelta::FromHours(1)); + EXPECT_TRUE(service_.IsBlocked(kTestIPHFeature)); + task_environment_.FastForwardBy(base::TimeDelta::FromHours(2)); + EXPECT_FALSE(service_.IsBlocked(kTestIPHFeature)); +} + +TEST_F(FeaturePromoSnoozeServiceTest, MultipleIPH) { + service_.Reset(kTestIPHFeature); + service_.Reset(kTestIPHFeature2); + service_.OnUserSnooze(kTestIPHFeature, base::TimeDelta::FromHours(1)); + service_.OnUserSnooze(kTestIPHFeature2, base::TimeDelta::FromHours(3)); + EXPECT_TRUE(service_.IsBlocked(kTestIPHFeature)); + EXPECT_TRUE(service_.IsBlocked(kTestIPHFeature2)); + task_environment_.FastForwardBy(base::TimeDelta::FromHours(2)); + EXPECT_FALSE(service_.IsBlocked(kTestIPHFeature)); + EXPECT_TRUE(service_.IsBlocked(kTestIPHFeature2)); + task_environment_.FastForwardBy(base::TimeDelta::FromHours(2)); + EXPECT_FALSE(service_.IsBlocked(kTestIPHFeature)); + EXPECT_FALSE(service_.IsBlocked(kTestIPHFeature2)); +}
diff --git a/chrome/browser/ui/search/ntp_user_data_logger.cc b/chrome/browser/ui/search/ntp_user_data_logger.cc index d6289df2..ad8b732 100644 --- a/chrome/browser/ui/search/ntp_user_data_logger.cc +++ b/chrome/browser/ui/search/ntp_user_data_logger.cc
@@ -548,6 +548,9 @@ case NTP_CUSTOMIZE_SHORTCUT_VISIBILITY_TOGGLE_CLICKED: RecordAction(LoggingEventToShortcutUserActionName(event)); break; + case NTP_MODULES_SHOWN: + UMA_HISTOGRAM_LOAD_TIME("NewTabPage.Modules.ShownTime", time); + break; } }
diff --git a/chrome/browser/ui/views/accessibility/invert_bubble_view.cc b/chrome/browser/ui/views/accessibility/invert_bubble_view.cc index 2193c86d..9587148 100644 --- a/chrome/browser/ui/views/accessibility/invert_bubble_view.cc +++ b/chrome/browser/ui/views/accessibility/invert_bubble_view.cc
@@ -72,7 +72,7 @@ // Overridden from views::ButtonListener: void ButtonPressed(views::Button* sender, const ui::Event& event) override; - void OpenLink(const std::string& url, int event_flags); + void OpenLink(const std::string& url, const ui::Event& event); Browser* browser_; @@ -141,12 +141,13 @@ void InvertBubbleView::ButtonPressed(views::Button* sender, const ui::Event& event) { if (sender->tag() == kLearnMoreButton) - OpenLink(kLearnMoreUrl, event.flags()); + OpenLink(kLearnMoreUrl, event); } -void InvertBubbleView::OpenLink(const std::string& url, int event_flags) { +void InvertBubbleView::OpenLink(const std::string& url, + const ui::Event& event) { WindowOpenDisposition disposition = ui::DispositionFromEventFlags( - event_flags, WindowOpenDisposition::NEW_FOREGROUND_TAB); + event.flags(), WindowOpenDisposition::NEW_FOREGROUND_TAB); content::OpenURLParams params(GURL(url), content::Referrer(), disposition, ui::PAGE_TRANSITION_LINK, false); browser_->OpenURL(params);
diff --git a/chrome/browser/ui/views/content_setting_bubble_contents.cc b/chrome/browser/ui/views/content_setting_bubble_contents.cc index a2a4ea02..abeea0e 100644 --- a/chrome/browser/ui/views/content_setting_bubble_contents.cc +++ b/chrome/browser/ui/views/content_setting_bubble_contents.cc
@@ -251,10 +251,10 @@ link->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT); link->set_callback(base::BindRepeating( [](const std::vector<Row>* items, const views::Link* link, - ContentSettingBubbleContents* parent, int event_flags) { + ContentSettingBubbleContents* parent, const ui::Event& event) { const auto it = base::ranges::find(*items, link, &Row::second); DCHECK(it != items->cend()); - parent->LinkClicked(std::distance(items->cbegin(), it), event_flags); + parent->LinkClicked(std::distance(items->cbegin(), it), event); }, base::Unretained(&list_item_views_), base::Unretained(link.get()), base::Unretained(parent_))); @@ -619,10 +619,11 @@ return container; } -void ContentSettingBubbleContents::LinkClicked(int row, int event_flags) { +void ContentSettingBubbleContents::LinkClicked(int row, + const ui::Event& event) { DCHECK(content_setting_bubble_model_); DCHECK_NE(row, -1); - content_setting_bubble_model_->OnListItemClicked(row, event_flags); + content_setting_bubble_model_->OnListItemClicked(row, event); } void ContentSettingBubbleContents::CustomLinkClicked() {
diff --git a/chrome/browser/ui/views/content_setting_bubble_contents.h b/chrome/browser/ui/views/content_setting_bubble_contents.h index efbf8d18..36fd469 100644 --- a/chrome/browser/ui/views/content_setting_bubble_contents.h +++ b/chrome/browser/ui/views/content_setting_bubble_contents.h
@@ -76,7 +76,7 @@ // "learn more" button and a "manage" button. std::unique_ptr<View> CreateHelpAndManageView(); - void LinkClicked(int row, int event_flags); + void LinkClicked(int row, const ui::Event& event); void CustomLinkClicked(); void OnPerformAction(views::Combobox* combobox);
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc index f604cd99..7c2006a 100644 --- a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc +++ b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc
@@ -268,11 +268,8 @@ if (audio_share_checkbox_) { switch (source_types_[index]) { case DesktopMediaID::TYPE_SCREEN: -#if defined(USE_CRAS) || defined(OS_WIN) - audio_share_checkbox_->SetVisible(true); -#else - audio_share_checkbox_->SetVisible(false); -#endif + audio_share_checkbox_->SetVisible( + DesktopMediaPickerViews::kScreenAudioShareSupportedOnPlatform); break; case DesktopMediaID::TYPE_WINDOW: audio_share_checkbox_->SetVisible(false); @@ -341,7 +338,8 @@ bool DesktopMediaPickerDialogView::IsDialogButtonEnabled( ui::DialogButton button) const { return button != ui::DIALOG_BUTTON_OK || - GetSelectedController()->GetSelection().has_value(); + GetSelectedController()->GetSelection().has_value() || + accepted_source_.has_value(); } views::View* DesktopMediaPickerDialogView::GetInitiallyFocusedView() { @@ -349,6 +347,7 @@ } bool DesktopMediaPickerDialogView::Accept() { + DCHECK(IsDialogButtonEnabled(ui::DIALOG_BUTTON_OK)); // Ok button should only be enabled when a source is selected. base::Optional<DesktopMediaID> source_optional = accepted_source_.has_value() ? accepted_source_ @@ -445,6 +444,8 @@ GetWidget()->CenterWindow(new_size); } +constexpr bool DesktopMediaPickerViews::kScreenAudioShareSupportedOnPlatform; + DesktopMediaPickerViews::DesktopMediaPickerViews() : dialog_(nullptr) {} DesktopMediaPickerViews::~DesktopMediaPickerViews() {
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.h b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.h index 96dc67ab..da08c138 100644 --- a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.h +++ b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.h
@@ -6,6 +6,7 @@ #define CHROME_BROWSER_UI_VIEWS_DESKTOP_CAPTURE_DESKTOP_MEDIA_PICKER_VIEWS_H_ #include "base/macros.h" +#include "build/build_config.h" #include "chrome/browser/media/webrtc/desktop_media_picker.h" #include "chrome/browser/ui/views/desktop_capture/desktop_media_list_controller.h" #include "ui/views/controls/label.h" @@ -86,6 +87,12 @@ // DesktopMediaPicker. class DesktopMediaPickerViews : public DesktopMediaPicker { public: +#if defined(OS_WIN) || defined(USE_CRAS) + static constexpr bool kScreenAudioShareSupportedOnPlatform = true; +#else + static constexpr bool kScreenAudioShareSupportedOnPlatform = false; +#endif + DesktopMediaPickerViews(); ~DesktopMediaPickerViews() override;
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_unittest.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_unittest.cc index 227772d..4e4017d 100644 --- a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_unittest.cc +++ b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_unittest.cc
@@ -22,7 +22,6 @@ #include "chrome/test/views/chrome_test_views_delegate.h" #include "components/web_modal/test_web_contents_modal_dialog_host.h" #include "content/public/test/browser_task_environment.h" -#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/ui_base_switches.h" #include "ui/events/event_utils.h" @@ -30,6 +29,8 @@ #include "ui/views/controls/tabbed_pane/tabbed_pane.h" #include "ui/views/test/scoped_views_test_helper.h" #include "ui/views/test/test_views_delegate.h" +#include "ui/views/test/widget_test.h" +#include "ui/views/widget/any_widget_observer.h" #include "ui/views/widget/widget.h" #include "ui/views/window/dialog_delegate.h" @@ -37,11 +38,19 @@ namespace views { -class MockDesktopMediaPickerDialogObserver - : public DesktopMediaPickerManager::DialogObserver { +class TestDialogObserver : public DesktopMediaPickerManager::DialogObserver { public: - MOCK_METHOD0(OnDialogOpened, void()); - MOCK_METHOD0(OnDialogClosed, void()); + ~TestDialogObserver() override { + EXPECT_TRUE(opened_); + EXPECT_TRUE(closed_); + } + + private: + void OnDialogOpened() override { opened_ = true; } + void OnDialogClosed() override { closed_ = true; } + + bool opened_ = false; + bool closed_ = false; }; const std::vector<DesktopMediaID::Type> kSourceTypes = { @@ -63,37 +72,41 @@ base::CommandLine::ForCurrentProcess()->AppendSwitch( switches::kDisableModalAnimations); #endif - - std::vector<std::unique_ptr<DesktopMediaList>> source_lists; - for (auto type : source_types_) { - media_lists_[type] = new FakeDesktopMediaList(type); - source_lists.push_back( - std::unique_ptr<FakeDesktopMediaList>(media_lists_[type])); - } - - base::string16 app_name = base::ASCIIToUTF16("foo"); + DesktopMediaPickerManager::Get()->AddObserver(&observer_); picker_views_ = std::make_unique<DesktopMediaPickerViews>(); test_api_.set_picker(picker_views_.get()); + + views::NamedWidgetShownWaiter waiter(views::test::AnyWidgetTestPasskey{}, + "DesktopMediaPickerDialogView"); + + const base::string16 kAppName = base::ASCIIToUTF16("foo"); DesktopMediaPicker::Params picker_params; picker_params.context = test_helper_.GetContext(); - picker_params.app_name = app_name; - picker_params.target_name = app_name; + picker_params.app_name = kAppName; + picker_params.target_name = kAppName; picker_params.request_audio = true; - DesktopMediaPickerManager::Get()->AddObserver(&observer_); - EXPECT_CALL(observer_, OnDialogOpened()); - EXPECT_CALL(observer_, OnDialogClosed()); + + std::vector<std::unique_ptr<DesktopMediaList>> source_lists; + for (auto type : source_types_) { + source_lists.push_back(std::make_unique<FakeDesktopMediaList>(type)); + media_lists_[type] = + static_cast<FakeDesktopMediaList*>(source_lists.back().get()); + } + picker_views_->Show( picker_params, std::move(source_lists), base::BindOnce(&DesktopMediaPickerViewsTest::OnPickerDone, base::Unretained(this))); + widget_destroyed_waiter_ = + std::make_unique<views::test::WidgetDestroyedWaiter>( + waiter.WaitIfNeededAndGet()); } void TearDown() override { - if (GetPickerDialogView()) { - EXPECT_CALL(*this, OnPickerDone(content::DesktopMediaID())); + if (GetPickerDialogView()) GetPickerDialogView()->GetWidget()->CloseNow(); - } + widget_destroyed_waiter_->Wait(); DesktopMediaPickerManager::Get()->RemoveObserver(&observer_); } @@ -101,7 +114,19 @@ return picker_views_->GetDialogViewForTesting(); } - MOCK_METHOD1(OnPickerDone, void(content::DesktopMediaID)); + void OnPickerDone(content::DesktopMediaID picked_id) { + picked_id_ = picked_id; + run_loop_.Quit(); + } + + base::Optional<content::DesktopMediaID> WaitForPickerDone() { + run_loop_.Run(); + return picked_id_; + } + + base::Optional<content::DesktopMediaID> picked_id() const { + return picked_id_; + } protected: content::BrowserTaskEnvironment task_environment_; @@ -110,20 +135,21 @@ std::map<DesktopMediaID::Type, FakeDesktopMediaList*> media_lists_; std::unique_ptr<DesktopMediaPickerViews> picker_views_; DesktopMediaPickerViewsTestApi test_api_; - MockDesktopMediaPickerDialogObserver observer_; + TestDialogObserver observer_; const std::vector<DesktopMediaID::Type> source_types_; + + base::RunLoop run_loop_; + base::Optional<content::DesktopMediaID> picked_id_; + std::unique_ptr<views::test::WidgetDestroyedWaiter> widget_destroyed_waiter_; }; TEST_F(DesktopMediaPickerViewsTest, DoneCallbackCalledWhenWindowClosed) { - EXPECT_CALL(*this, OnPickerDone(content::DesktopMediaID())); - GetPickerDialogView()->GetWidget()->Close(); - base::RunLoop().RunUntilIdle(); + EXPECT_EQ(content::DesktopMediaID(), WaitForPickerDone()); } TEST_F(DesktopMediaPickerViewsTest, DoneCallbackCalledOnOkButtonPressed) { const DesktopMediaID kFakeId(DesktopMediaID::TYPE_WINDOW, 222); - EXPECT_CALL(*this, OnPickerDone(kFakeId)); media_lists_[DesktopMediaID::TYPE_WINDOW]->AddSourceByFullMediaID(kFakeId); test_api_.GetAudioShareCheckbox()->SetChecked(true); @@ -138,7 +164,7 @@ GetPickerDialogView()->IsDialogButtonEnabled(ui::DIALOG_BUTTON_OK)); GetPickerDialogView()->AcceptDialog(); - base::RunLoop().RunUntilIdle(); + EXPECT_EQ(kFakeId, WaitForPickerDone()); } // Verifies that a MediaSourceView is selected with mouse left click and @@ -166,8 +192,7 @@ // Regression test for https://crbug.com/1102153 TEST_F(DesktopMediaPickerViewsTest, DoneCallbackNotCalledOnDoubleClick) { - const DesktopMediaID kFakeId(DesktopMediaID::TYPE_WEB_CONTENTS, 222); - EXPECT_CALL(*this, OnPickerDone(kFakeId)).Times(0); + constexpr DesktopMediaID kFakeId(DesktopMediaID::TYPE_WEB_CONTENTS, 222); media_lists_[DesktopMediaID::TYPE_WEB_CONTENTS]->AddSourceByFullMediaID( kFakeId); @@ -175,20 +200,19 @@ test_api_.GetAudioShareCheckbox()->SetChecked(false); test_api_.PressMouseOnSourceAtIndex(0, true); - base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(picked_id().has_value()); } // Regression test for https://crbug.com/1102153 TEST_F(DesktopMediaPickerViewsTest, DoneCallbackNotCalledOnDoubleTap) { const DesktopMediaID kFakeId(DesktopMediaID::TYPE_SCREEN, 222); - EXPECT_CALL(*this, OnPickerDone(kFakeId)).Times(0); test_api_.SelectTabForSourceType(DesktopMediaID::TYPE_SCREEN); test_api_.GetAudioShareCheckbox()->SetChecked(false); media_lists_[DesktopMediaID::TYPE_SCREEN]->AddSourceByFullMediaID(kFakeId); test_api_.DoubleTapSourceAtIndex(0); - base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(picked_id().has_value()); } TEST_F(DesktopMediaPickerViewsTest, CancelButtonAlwaysEnabled) { @@ -261,12 +285,9 @@ // Verifies the visible status of audio checkbox. TEST_F(DesktopMediaPickerViewsTest, AudioCheckboxState) { - bool expect_value = false; test_api_.SelectTabForSourceType(DesktopMediaID::TYPE_SCREEN); -#if defined(OS_WIN) || defined(USE_CRAS) - expect_value = true; -#endif - EXPECT_EQ(expect_value, test_api_.GetAudioShareCheckbox()->GetVisible()); + EXPECT_EQ(DesktopMediaPickerViews::kScreenAudioShareSupportedOnPlatform, + test_api_.GetAudioShareCheckbox()->GetVisible()); test_api_.SelectTabForSourceType(DesktopMediaID::TYPE_WINDOW); EXPECT_FALSE(test_api_.GetAudioShareCheckbox()->GetVisible()); @@ -278,23 +299,36 @@ // Verifies that audio share information is recorded in the ID if the checkbox // is checked. TEST_F(DesktopMediaPickerViewsTest, DoneWithAudioShare) { - DesktopMediaID originId(DesktopMediaID::TYPE_WEB_CONTENTS, 222); - DesktopMediaID returnId = originId; - returnId.audio_share = true; + constexpr DesktopMediaID kOriginId(DesktopMediaID::TYPE_WEB_CONTENTS, 222); + constexpr DesktopMediaID kResultId(DesktopMediaID::TYPE_WEB_CONTENTS, 222, + true); // This matches the real workflow that when a source is generated in // media_list, its |audio_share| bit is not set. The bit is set by the picker // UI if the audio checkbox is checked. - EXPECT_CALL(*this, OnPickerDone(returnId)); media_lists_[DesktopMediaID::TYPE_WEB_CONTENTS]->AddSourceByFullMediaID( - originId); + kOriginId); test_api_.SelectTabForSourceType(DesktopMediaID::TYPE_WEB_CONTENTS); test_api_.GetAudioShareCheckbox()->SetChecked(true); test_api_.FocusSourceAtIndex(0); GetPickerDialogView()->AcceptDialog(); - base::RunLoop().RunUntilIdle(); + EXPECT_EQ(kResultId, WaitForPickerDone()); +} + +TEST_F(DesktopMediaPickerViewsTest, OkButtonEnabledDuringAcceptSpecific) { + constexpr DesktopMediaID kFakeId( + DesktopMediaID::TYPE_SCREEN, 222, + DesktopMediaPickerViews::kScreenAudioShareSupportedOnPlatform); + + media_lists_[DesktopMediaID::TYPE_WINDOW]->AddSourceByFullMediaID(kFakeId); + + EXPECT_FALSE( + GetPickerDialogView()->IsDialogButtonEnabled(ui::DIALOG_BUTTON_OK)); + + GetPickerDialogView()->AcceptSpecificSource(kFakeId); + EXPECT_EQ(kFakeId, WaitForPickerDone()); } // Creates a single pane DesktopMediaPickerViews that only has a tab list.
diff --git a/chrome/browser/ui/views/infobars/infobar_view.cc b/chrome/browser/ui/views/infobars/infobar_view.cc index bd1e906..547aba1 100644 --- a/chrome/browser/ui/views/infobars/infobar_view.cc +++ b/chrome/browser/ui/views/infobars/infobar_view.cc
@@ -402,9 +402,9 @@ 0)); } -void InfoBarView::LinkClicked(int event_flags) { +void InfoBarView::LinkClicked(const ui::Event& event) { if (!owner()) return; // We're closing; don't call anything, it might access the owner. - if (delegate()->LinkClicked(ui::DispositionFromEventFlags(event_flags))) + if (delegate()->LinkClicked(ui::DispositionFromEventFlags(event.flags()))) RemoveSelf(); }
diff --git a/chrome/browser/ui/views/infobars/infobar_view.h b/chrome/browser/ui/views/infobars/infobar_view.h index 48b819a0..530999a 100644 --- a/chrome/browser/ui/views/infobars/infobar_view.h +++ b/chrome/browser/ui/views/infobars/infobar_view.h
@@ -109,7 +109,7 @@ void SetLabelDetails(views::Label* label) const; // Callback used by the link created by CreateLink(). - void LinkClicked(int event_flags); + void LinkClicked(const ui::Event& event); // The optional icon at the left edge of the InfoBar. views::ImageView* icon_ = nullptr;
diff --git a/chrome/browser/ui/views/network_profile_bubble_view.cc b/chrome/browser/ui/views/network_profile_bubble_view.cc index d1e7f318..d644a73 100644 --- a/chrome/browser/ui/views/network_profile_bubble_view.cc +++ b/chrome/browser/ui/views/network_profile_bubble_view.cc
@@ -35,7 +35,7 @@ void Init() override; bool Accept() override; - void LinkClicked(int event_flags); + void LinkClicked(const ui::Event&); // Used for loading pages. content::PageNavigator* navigator_; @@ -87,11 +87,11 @@ return true; } -void NetworkProfileBubbleView::LinkClicked(int event_flags) { +void NetworkProfileBubbleView::LinkClicked(const ui::Event& event) { NetworkProfileBubble::RecordUmaEvent( NetworkProfileBubble::METRIC_LEARN_MORE_CLICKED); WindowOpenDisposition disposition = ui::DispositionFromEventFlags( - event_flags, WindowOpenDisposition::NEW_FOREGROUND_TAB); + event.flags(), WindowOpenDisposition::NEW_FOREGROUND_TAB); content::OpenURLParams params( GURL("https://sites.google.com/a/chromium.org/dev/administrators/" "common-problems-and-solutions#network_profile"),
diff --git a/chrome/browser/ui/views/page_action/pwa_install_view.cc b/chrome/browser/ui/views/page_action/pwa_install_view.cc index 8ad2c50..0f0decb1 100644 --- a/chrome/browser/ui/views/page_action/pwa_install_view.cc +++ b/chrome/browser/ui/views/page_action/pwa_install_view.cc
@@ -30,7 +30,7 @@ {ExperimentIcon::kDownload, "download"}}; constexpr base::FeatureParam<ExperimentIcon> kInstallIconParam{ - &kInstallIconExperiment, "shape", ExperimentIcon::kDownloadToDevice, + &kInstallIconExperiment, "installIcon", ExperimentIcon::kDownloadToDevice, &kIconParamOptions}; } // namespace
diff --git a/chrome/browser/ui/views/page_action/pwa_install_view_browsertest.cc b/chrome/browser/ui/views/page_action/pwa_install_view_browsertest.cc index d0769ee2..792487b 100644 --- a/chrome/browser/ui/views/page_action/pwa_install_view_browsertest.cc +++ b/chrome/browser/ui/views/page_action/pwa_install_view_browsertest.cc
@@ -311,8 +311,8 @@ EXPECT_FALSE(pwa_install_view_->GetVisible()); } -// Tests that the plus icon is shown when an existing app is installed and set -// to open in a tab. +// Tests that the install icon is shown when an existing app is installed and +// set to open in a tab. IN_PROC_BROWSER_TEST_P(PwaInstallViewBrowserTest, PwaSetToOpenInTabIsInstallable) { bool installable = OpenTab(GetInstallableAppURL()).installable; @@ -333,6 +333,18 @@ EXPECT_TRUE(pwa_install_view_->GetVisible()); } +// Test that the accept metrics is reported correctly. +IN_PROC_BROWSER_TEST_P(PwaInstallViewBrowserTest, PwaInstalledMetricRecorded) { + bool installable = OpenTab(GetInstallableAppURL()).installable; + ASSERT_TRUE(installable); + + base::HistogramTester histograms; + ExecutePwaInstallIcon(); + histograms.ExpectUniqueSample( + "WebApp.InstallConfirmation.CloseReason", + views::Widget::ClosedReason::kAcceptButtonClicked, 1); +} + // Tests that the plus icon updates its visibility when switching between // installable/non-installable tabs. IN_PROC_BROWSER_TEST_P(PwaInstallViewBrowserTest, @@ -360,7 +372,7 @@ EXPECT_FALSE(pwa_install_view_->GetVisible()); } -// Tests that the plus icon updates its visibility when tab crashes. +// Tests that the install icon updates its visibility when tab crashes. IN_PROC_BROWSER_TEST_P(PwaInstallViewBrowserTest, IconVisibilityAfterTabCrashed) { StartNavigateToUrl(GetInstallableAppURL());
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc index 8de3ef7..d798dd1 100644 --- a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc +++ b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
@@ -448,14 +448,14 @@ web_contents, url, std::move(closing_callback)); } -void PageInfoBubbleView::SecurityDetailsClicked(int event_flags) { +void PageInfoBubbleView::SecurityDetailsClicked(const ui::Event& event) { if (GetSecurityDescriptionType() == SecurityDescriptionType::SAFETY_TIP) { OpenHelpCenterFromSafetyTip(web_contents()); } else { web_contents()->OpenURL(content::OpenURLParams( GURL(chrome::kPageInfoHelpCenterURL), content::Referrer(), ui::DispositionFromEventFlags( - event_flags, WindowOpenDisposition::NEW_FOREGROUND_TAB), + event.flags(), WindowOpenDisposition::NEW_FOREGROUND_TAB), ui::PAGE_TRANSITION_LINK, false)); presenter_->RecordPageInfoAction( PageInfo::PAGE_INFO_CONNECTION_HELP_OPENED);
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view.h b/chrome/browser/ui/views/page_info/page_info_bubble_view.h index 0c307bca..8123ad6 100644 --- a/chrome/browser/ui/views/page_info/page_info_bubble_view.h +++ b/chrome/browser/ui/views/page_info/page_info_bubble_view.h
@@ -96,7 +96,7 @@ const GURL& url, PageInfoClosingCallback closing_callback); - void SecurityDetailsClicked(int event_flags); + void SecurityDetailsClicked(const ui::Event& event); void ResetDecisionsClicked(); protected:
diff --git a/chrome/browser/ui/views/safe_browsing/prompt_for_scanning_modal_dialog.cc b/chrome/browser/ui/views/safe_browsing/prompt_for_scanning_modal_dialog.cc index 079e7a0..5759252 100644 --- a/chrome/browser/ui/views/safe_browsing/prompt_for_scanning_modal_dialog.cc +++ b/chrome/browser/ui/views/safe_browsing/prompt_for_scanning_modal_dialog.cc
@@ -85,12 +85,12 @@ gfx::Range learn_more_range(offsets[1], message_text.length()); views::StyledLabel::RangeStyleInfo link_style = views::StyledLabel::RangeStyleInfo::CreateForLink(base::BindRepeating( - [](content::WebContents* web_contents, int event_flags) { + [](content::WebContents* web_contents, const ui::Event& event) { web_contents->OpenURL(content::OpenURLParams( GURL(chrome::kAdvancedProtectionDownloadLearnMoreURL), content::Referrer(), ui::DispositionFromEventFlags( - event_flags, WindowOpenDisposition::NEW_FOREGROUND_TAB), + event.flags(), WindowOpenDisposition::NEW_FOREGROUND_TAB), ui::PAGE_TRANSITION_LINK, /*is_renderer_initiated=*/false)); }, web_contents));
diff --git a/chrome/browser/ui/views/session_crashed_bubble_view.cc b/chrome/browser/ui/views/session_crashed_bubble_view.cc index 7ac583b..c83ea43f 100644 --- a/chrome/browser/ui/views/session_crashed_bubble_view.cc +++ b/chrome/browser/ui/views/session_crashed_bubble_view.cc
@@ -293,11 +293,12 @@ return uma_view; } -void SessionCrashedBubbleView::ExplainStatisticsLinkClicked(int event_flags) { +void SessionCrashedBubbleView::ExplainStatisticsLinkClicked( + const ui::Event& event) { browser_->OpenURL(content::OpenURLParams( GURL("https://support.google.com/chrome/answer/96817"), content::Referrer(), - ui::DispositionFromEventFlags(event_flags, + ui::DispositionFromEventFlags(event.flags(), WindowOpenDisposition::NEW_FOREGROUND_TAB), ui::PAGE_TRANSITION_LINK, false)); RecordBubbleHistogramValue(SESSION_CRASHED_BUBBLE_HELP);
diff --git a/chrome/browser/ui/views/session_crashed_bubble_view.h b/chrome/browser/ui/views/session_crashed_bubble_view.h index 909c6467..8e857b9f9 100644 --- a/chrome/browser/ui/views/session_crashed_bubble_view.h +++ b/chrome/browser/ui/views/session_crashed_bubble_view.h
@@ -57,7 +57,7 @@ std::unique_ptr<views::View> CreateUmaOptInView(); // Called when the user clicks the "statistics" link to get more information. - void ExplainStatisticsLinkClicked(int event_flags); + void ExplainStatisticsLinkClicked(const ui::Event& event); // Restore previous session after user selects so. void RestorePreviousSession();
diff --git a/chrome/browser/ui/views/sharing/sharing_dialog_view.cc b/chrome/browser/ui/views/sharing/sharing_dialog_view.cc index beac287..7553e1d 100644 --- a/chrome/browser/ui/views/sharing/sharing_dialog_view.cc +++ b/chrome/browser/ui/views/sharing/sharing_dialog_view.cc
@@ -357,7 +357,7 @@ return label; } -void SharingDialogView::HelpLinkClicked(int event_flags) { +void SharingDialogView::HelpLinkClicked() { std::move(data_.help_callback).Run(GetDialogType()); CloseBubble(); }
diff --git a/chrome/browser/ui/views/sharing/sharing_dialog_view.h b/chrome/browser/ui/views/sharing/sharing_dialog_view.h index 0e060cc..9ea368cd 100644 --- a/chrome/browser/ui/views/sharing/sharing_dialog_view.h +++ b/chrome/browser/ui/views/sharing/sharing_dialog_view.h
@@ -75,7 +75,7 @@ std::unique_ptr<views::StyledLabel> CreateHelpText(); // Called when the "help" link is clicked. - void HelpLinkClicked(int event_flags); + void HelpLinkClicked(); SharingDialogData data_;
diff --git a/chrome/browser/ui/views/sharing/sharing_dialog_view_unittest.cc b/chrome/browser/ui/views/sharing/sharing_dialog_view_unittest.cc index e23df02..566a517 100644 --- a/chrome/browser/ui/views/sharing/sharing_dialog_view_unittest.cc +++ b/chrome/browser/ui/views/sharing/sharing_dialog_view_unittest.cc
@@ -181,7 +181,7 @@ auto dialog_data = CreateDialogData(/*devices=*/0, /*apps=*/0); auto dialog = CreateDialogView(std::move(dialog_data)); - dialog->HelpLinkClicked(ui::EF_NONE); + dialog->HelpLinkClicked(); } TEST_F(SharingDialogViewTest, HelpTextClickedOnlyApps) { @@ -191,7 +191,7 @@ auto dialog_data = CreateDialogData(/*devices=*/0, /*apps=*/1); auto dialog = CreateDialogView(std::move(dialog_data)); - dialog->HelpLinkClicked(ui::EF_NONE); + dialog->HelpLinkClicked(); } TEST_F(SharingDialogViewTest, ThemeChangedEmptyList) {
diff --git a/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc b/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc index 95cdcfef1..ff2e5fe0 100644 --- a/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc +++ b/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc
@@ -257,12 +257,13 @@ GetWidget()->Close(); } -void ProfileSigninConfirmationDialogViews::LearnMoreClicked(int event_flags) { +void ProfileSigninConfirmationDialogViews::LearnMoreClicked( + const ui::Event& event) { NavigateParams params( browser_, GURL("https://support.google.com/chromebook/answer/1331549"), ui::PAGE_TRANSITION_LINK); params.disposition = ui::DispositionFromEventFlags( - event_flags, WindowOpenDisposition::NEW_POPUP); + event.flags(), WindowOpenDisposition::NEW_POPUP); params.window_action = NavigateParams::SHOW_WINDOW; Navigate(¶ms); }
diff --git a/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.h b/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.h index 3877bb0..d83079fab 100644 --- a/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.h +++ b/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.h
@@ -51,7 +51,7 @@ void ButtonPressed(views::Button*, const ui::Event& event) override; // Called when the "learn more" link is clicked. - void LearnMoreClicked(int event_flags); + void LearnMoreClicked(const ui::Event& event); // Weak ptr to parent view. Browser* const browser_;
diff --git a/chrome/browser/ui/views/tab_modal_confirm_dialog_views.cc b/chrome/browser/ui/views/tab_modal_confirm_dialog_views.cc index b02fc66..b4182f33 100644 --- a/chrome/browser/ui/views/tab_modal_confirm_dialog_views.cc +++ b/chrome/browser/ui/views/tab_modal_confirm_dialog_views.cc
@@ -105,8 +105,8 @@ GetWidget()->Close(); } -void TabModalConfirmDialogViews::LinkClicked(int event_flags) { - delegate_->LinkClicked(ui::DispositionFromEventFlags(event_flags)); +void TabModalConfirmDialogViews::LinkClicked(const ui::Event& event) { + delegate_->LinkClicked(ui::DispositionFromEventFlags(event.flags())); } views::View* TabModalConfirmDialogViews::GetInitiallyFocusedView() {
diff --git a/chrome/browser/ui/views/tab_modal_confirm_dialog_views.h b/chrome/browser/ui/views/tab_modal_confirm_dialog_views.h index ac10386..0106345 100644 --- a/chrome/browser/ui/views/tab_modal_confirm_dialog_views.h +++ b/chrome/browser/ui/views/tab_modal_confirm_dialog_views.h
@@ -50,7 +50,7 @@ void CancelTabModalDialog() override; void CloseDialog() override; - void LinkClicked(int event_flags); + void LinkClicked(const ui::Event& event); views::View* GetInitiallyFocusedView() override;
diff --git a/chrome/browser/ui/views/web_apps/pwa_confirmation_bubble_view.cc b/chrome/browser/ui/views/web_apps/pwa_confirmation_bubble_view.cc index f9c9eef..eb17b0c 100644 --- a/chrome/browser/ui/views/web_apps/pwa_confirmation_bubble_view.cc +++ b/chrome/browser/ui/views/web_apps/pwa_confirmation_bubble_view.cc
@@ -7,6 +7,7 @@ #include <utility> #include "base/i18n/message_formatter.h" +#include "base/metrics/histogram_functions.h" #include "base/strings/string16.h" #include "base/strings/string_util.h" #include "build/build_config.h" @@ -172,6 +173,13 @@ PWAConfirmationBubbleView::~PWAConfirmationBubbleView() = default; +bool PWAConfirmationBubbleView::OnCloseRequested( + views::Widget::ClosedReason close_reason) { + base::UmaHistogramEnumeration("WebApp.InstallConfirmation.CloseReason", + close_reason); + return LocationBarBubbleDelegateView::OnCloseRequested(close_reason); +} + views::View* PWAConfirmationBubbleView::GetInitiallyFocusedView() { return nullptr; }
diff --git a/chrome/browser/ui/views/web_apps/pwa_confirmation_bubble_view.h b/chrome/browser/ui/views/web_apps/pwa_confirmation_bubble_view.h index d32b360..58daea2f 100644 --- a/chrome/browser/ui/views/web_apps/pwa_confirmation_bubble_view.h +++ b/chrome/browser/ui/views/web_apps/pwa_confirmation_bubble_view.h
@@ -11,6 +11,7 @@ #include "chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.h" #include "chrome/common/web_application_info.h" #include "content/public/browser/web_contents.h" +#include "ui/views/widget/widget.h" namespace views { class Checkbox; @@ -31,6 +32,7 @@ ~PWAConfirmationBubbleView() override; // LocationBarBubbleDelegateView: + bool OnCloseRequested(views::Widget::ClosedReason close_reason) override; views::View* GetInitiallyFocusedView() override; void WindowClosing() override; bool Accept() override;
diff --git a/chrome/browser/ui/views/web_apps/pwa_confirmation_bubble_view_browsertest.cc b/chrome/browser/ui/views/web_apps/pwa_confirmation_bubble_view_browsertest.cc index 09a8204c..edb3b0b9 100644 --- a/chrome/browser/ui/views/web_apps/pwa_confirmation_bubble_view_browsertest.cc +++ b/chrome/browser/ui/views/web_apps/pwa_confirmation_bubble_view_browsertest.cc
@@ -10,6 +10,7 @@ #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" #include "base/test/bind_test_util.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_dialogs.h" @@ -114,3 +115,28 @@ GetCallbackAppInfoFromDialog(/*run_on_os_login_checked=*/false); EXPECT_FALSE(resulting_app_info->run_on_os_login); } + +IN_PROC_BROWSER_TEST_F(PWAConfirmationBubbleViewBrowserTest, + CancelledDialogReportsMetrics) { + auto app_info = GetAppInfo(); + base::RunLoop loop; + // Show the PWA install dialog. + chrome::ShowPWAInstallBubble( + browser()->tab_strip_model()->GetActiveWebContents(), std::move(app_info), + base::BindLambdaForTesting( + [&](bool accepted, + std::unique_ptr<WebApplicationInfo> app_info_callback) { + loop.Quit(); + })); + + PWAConfirmationBubbleView* bubble_dialog = + PWAConfirmationBubbleView::GetBubbleForTesting(); + + base::HistogramTester histograms; + bubble_dialog->CancelDialog(); + loop.Run(); + + histograms.ExpectUniqueSample( + "WebApp.InstallConfirmation.CloseReason", + views::Widget::ClosedReason::kCancelButtonClicked, 1); +}
diff --git a/chrome/browser/ui/web_applications/test/ssl_test_utils.cc b/chrome/browser/ui/web_applications/test/ssl_test_utils.cc index 7f4c6e3..e027590 100644 --- a/chrome/browser/ui/web_applications/test/ssl_test_utils.cc +++ b/chrome/browser/ui/web_applications/test/ssl_test_utils.cc
@@ -46,11 +46,7 @@ DCHECK(browser); ssl_test_util::CheckSecurityState( browser->tab_strip_model()->GetActiveWebContents(), - ssl_test_util::CertError::NONE, - base::FeatureList::IsEnabled( - security_state::features::kPassiveMixedContentWarning) - ? security_state::WARNING - : security_state::NONE, + ssl_test_util::CertError::NONE, security_state::WARNING, ssl_test_util::AuthState::DISPLAYED_INSECURE_CONTENT); }
diff --git a/chrome/browser/ui/web_applications/web_app_link_capturing_browsertest.cc b/chrome/browser/ui/web_applications/web_app_link_capturing_browsertest.cc index 32112b0..bd4d45b5 100644 --- a/chrome/browser/ui/web_applications/web_app_link_capturing_browsertest.cc +++ b/chrome/browser/ui/web_applications/web_app_link_capturing_browsertest.cc
@@ -6,6 +6,7 @@ #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_tabstrip.h" +#include "chrome/browser/ui/search/local_ntp_test_utils.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/web_applications/app_browser_controller.h" #include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h" @@ -67,6 +68,10 @@ } } + GURL NtpUrl() { + return local_ntp_test_utils::GetFinalNtpUrl(browser()->profile()); + } + protected: AppId app_id_; GURL app_url_{"https://example.org/dir/start.html"}; @@ -75,7 +80,6 @@ GURL in_scope_2_{"https://example.org/dir/page2.html"}; GURL origin_{"https://example.org/"}; GURL out_of_scope_{"https://other-domain.org/"}; - GURL new_tab_{"chrome://newtab/"}; private: base::test::ScopedFeatureList features_; @@ -121,7 +125,7 @@ NavigateMainBrowser(in_scope_1_); Browser* app_browser = BrowserList::GetInstance()->GetLastActive(); EXPECT_TRUE(AppBrowserController::IsForWebAppBrowser(app_browser, app_id_)); - ExpectTabs(browser(), {new_tab_}); + ExpectTabs(browser(), {NtpUrl()}); ExpectTabs(app_browser, {in_scope_1_}); EXPECT_EQ(reparent_web_contents, app_browser->tab_strip_model()->GetActiveWebContents()); @@ -130,7 +134,7 @@ // reparent. When there is already an app window open we should reparent into // it. chrome::AddTabAt(browser(), about_blank_, /*index=*/-1, /*foreground=*/true); - ExpectTabs(browser(), {new_tab_, about_blank_}); + ExpectTabs(browser(), {NtpUrl(), about_blank_}); reparent_web_contents = browser()->tab_strip_model()->GetActiveWebContents(); { auto observer = @@ -141,7 +145,7 @@ base::StringPrintf("location = '%s';", in_scope_2_.spec().c_str()))); observer->Wait(); } - ExpectTabs(browser(), {new_tab_}); + ExpectTabs(browser(), {NtpUrl()}); ExpectTabs(app_browser, {in_scope_1_, in_scope_2_}); EXPECT_EQ(reparent_web_contents, app_browser->tab_strip_model()->GetActiveWebContents());
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc index 80c304a..cb18c2ca 100644 --- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc +++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -178,7 +178,6 @@ #include "chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_ui.h" #include "chrome/browser/ui/webui/chromeos/cryptohome_ui.h" #include "chrome/browser/ui/webui/chromeos/drive_internals_ui.h" -#include "chrome/browser/ui/webui/chromeos/file_manager/file_manager_ui.h" #include "chrome/browser/ui/webui/chromeos/first_run/first_run_ui.h" #include "chrome/browser/ui/webui/chromeos/internet_config_dialog.h" #include "chrome/browser/ui/webui/chromeos/internet_detail_dialog.h" @@ -219,6 +218,8 @@ #if defined(OS_CHROMEOS) && !defined(OFFICIAL_BUILD) #include "chrome/browser/ui/webui/chromeos/emulator/device_emulator_ui.h" +#include "chromeos/components/file_manager/file_manager_ui.h" +#include "chromeos/components/file_manager/url_constants.h" #include "chromeos/components/sample_system_web_app_ui/sample_system_web_app_ui.h" #include "chromeos/components/sample_system_web_app_ui/url_constants.h" #include "chromeos/components/telemetry_extension_ui/telemetry_extension_ui.h" @@ -648,9 +649,6 @@ return &NewWebUI<chromeos::CryptohomeUI>; if (url.host_piece() == chrome::kChromeUIDriveInternalsHost) return &NewWebUI<chromeos::DriveInternalsUI>; - if (base::FeatureList::IsEnabled(chromeos::features::kFilesSWA) && - url.host_piece() == chrome::kChromeUIFileManagerHost) - return &NewWebUI<chromeos::file_manager::FileManagerUI>; if (url.host_piece() == chrome::kChromeUIFirstRunHost) return &NewWebUI<chromeos::FirstRunUI>; if (url.host_piece() == chromeos::kChromeUIHelpAppHost) @@ -735,6 +733,8 @@ return &NewWebUI<DeviceEmulatorUI>; } #endif // !defined(USE_REAL_DBUS_CLIENTS) + if (url.host_piece() == chromeos::file_manager::kChromeUIFileManagerHost) + return &NewWebUI<chromeos::file_manager::FileManagerUI>; if (url.host_piece() == chromeos::kChromeUISampleSystemWebAppHost) return &NewWebUI<chromeos::SampleSystemWebAppUI>; if (url.host_piece() == chromeos::kChromeUITelemetryExtensionHost) {
diff --git a/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_ui.cc b/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_ui.cc index c5c2c9bef..9a465126 100644 --- a/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_ui.cc +++ b/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_ui.cc
@@ -49,7 +49,6 @@ {"errorTitle", IDS_CROSTINI_INSTALLER_ERROR_TITLE}, {"loadTerminaError", IDS_CROSTINI_INSTALLER_LOAD_TERMINA_ERROR}, - {"startConciergeError", IDS_CROSTINI_INSTALLER_START_CONCIERGE_ERROR}, {"createDiskImageError", IDS_CROSTINI_INSTALLER_CREATE_DISK_IMAGE_ERROR}, {"startTerminaVmError", IDS_CROSTINI_INSTALLER_START_TERMINA_VM_ERROR}, {"startContainerError", IDS_CROSTINI_INSTALLER_START_CONTAINER_ERROR}, @@ -61,7 +60,6 @@ {"unknownError", IDS_CROSTINI_INSTALLER_UNKNOWN_ERROR}, {"loadTerminaMessage", IDS_CROSTINI_INSTALLER_LOAD_TERMINA_MESSAGE}, - {"startConciergeMessage", IDS_CROSTINI_INSTALLER_START_CONCIERGE_MESSAGE}, {"createDiskImageMessage", IDS_CROSTINI_INSTALLER_CREATE_DISK_IMAGE_MESSAGE}, {"startTerminaVmMessage",
diff --git a/chrome/browser/ui/webui/chromeos/file_manager/BUILD.gn b/chrome/browser/ui/webui/chromeos/file_manager/BUILD.gn deleted file mode 100644 index db7d34a..0000000 --- a/chrome/browser/ui/webui/chromeos/file_manager/BUILD.gn +++ /dev/null
@@ -1,9 +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. - -import("//mojo/public/tools/bindings/mojom.gni") - -mojom("mojo_bindings") { - sources = [ "file_manager.mojom" ] -}
diff --git a/chrome/browser/ui/webui/chromeos/file_manager/file_manager_ui.cc b/chrome/browser/ui/webui/chromeos/file_manager/file_manager_ui.cc deleted file mode 100644 index 88d3cb9..0000000 --- a/chrome/browser/ui/webui/chromeos/file_manager/file_manager_ui.cc +++ /dev/null
@@ -1,57 +0,0 @@ -// Copyright (c) 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/webui/chromeos/file_manager/file_manager_ui.h" - -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/webui/chromeos/file_manager/file_manager_page_handler.h" -#include "chrome/common/url_constants.h" -#include "chrome/grit/browser_resources.h" -#include "content/public/browser/web_ui.h" -#include "content/public/browser/web_ui_data_source.h" - -namespace chromeos { -namespace file_manager { - -FileManagerUI::FileManagerUI(content::WebUI* web_ui) - : MojoWebUIController(web_ui) { - content::WebUIDataSource* source = - content::WebUIDataSource::Create(chrome::kChromeUIFileManagerHost); - source->AddResourcePath("file_manager.css", IDR_FILE_MANAGER_CSS); - source->AddResourcePath("file_manager.js", IDR_FILE_MANAGER_JS); - source->AddResourcePath("file_manager.mojom-lite.js", - IDR_FILE_MANAGER_MOJO_LITE_JS); - source->AddResourcePath("browser_proxy.js", IDR_FILE_MANAGER_PROXY_JS); - - // Default content for chrome://file-manager: ensures unhandled URLs return - // 404 rather than content from SetDefaultResource(). - source->AddResourcePath("", IDR_FILE_MANAGER_HTML); - - Profile* profile = Profile::FromWebUI(web_ui); - content::WebUIDataSource::Add(profile, source); -} - -FileManagerUI::~FileManagerUI() = default; - -void FileManagerUI::BindInterface( - mojo::PendingReceiver<mojom::PageHandlerFactory> pending_receiver) { - if (page_factory_receiver_.is_bound()) { - page_factory_receiver_.reset(); - } - page_factory_receiver_.Bind(std::move(pending_receiver)); -} - -void FileManagerUI::CreatePageHandler( - mojo::PendingRemote<mojom::Page> pending_page, - mojo::PendingReceiver<mojom::PageHandler> pending_page_handler) { - DCHECK(pending_page.is_valid()); - - page_handler_ = std::make_unique<FileManagerPageHandler>( - std::move(pending_page_handler), std::move(pending_page)); -} - -WEB_UI_CONTROLLER_TYPE_IMPL(FileManagerUI) - -} // namespace file_manager -} // namespace chromeos
diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom b/chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom index 70df10d..7323af3 100644 --- a/chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom +++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom
@@ -377,6 +377,8 @@ OnVoiceSearchAction(VoiceSearchAction action); // Logs an error occurred while using voice search. OnVoiceSearchError(VoiceSearchError error); + // Logs that the modules have been shown at |time|. + OnModulesRendered(double time); // ======= REALBOX ======= // Queries autocomplete matches from the browser.
diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc index dee7b7e..f950231 100644 --- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc +++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc
@@ -922,6 +922,11 @@ LogEvent(event); } +void NewTabPageHandler::OnModulesRendered(double time) { + logger_->LogEvent(NTP_MODULES_SHOWN, + base::Time::FromJsTime(time) - ntp_navigation_start_time_); +} + void NewTabPageHandler::QueryAutocomplete(const base::string16& input, bool prevent_inline_autocomplete) { if (!autocomplete_controller_) {
diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.h b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.h index 1512ba16..025f694 100644 --- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.h +++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.h
@@ -122,6 +122,7 @@ void OnVoiceSearchAction( new_tab_page::mojom::VoiceSearchAction action) override; void OnVoiceSearchError(new_tab_page::mojom::VoiceSearchError error) override; + void OnModulesRendered(double time) override; void QueryAutocomplete(const base::string16& input, bool prevent_inline_autocomplete) override; void StopAutocomplete(bool clear_result) override;
diff --git a/chrome/browser/ui/webui/omnibox/omnibox.mojom b/chrome/browser/ui/webui/omnibox/omnibox.mojom index 8648487..2bd08370 100644 --- a/chrome/browser/ui/webui/omnibox/omnibox.mojom +++ b/chrome/browser/ui/webui/omnibox/omnibox.mojom
@@ -70,7 +70,7 @@ interface OmniboxPageHandler { // Registers the webui page. SetClientPage(pending_remote<OmniboxPage> page); - // Prompts a autocopmlete controller to process an omnibox query. + // Prompts an autocomplete controller to process an omnibox query. StartOmniboxQuery(string input_string, bool reset_autocomplete_controller, int32 cursor_position, @@ -83,14 +83,14 @@ interface OmniboxPage { // Notifies the page of an omnibox response from a autocomplete - // controller. |is_page_controller| indicates wether the response + // controller. |is_page_controller| indicates whether the response // originates from a query initiated from the page via // |StartOmniboxQuery| or from the browser omnibox. HandleNewAutocompleteResponse(OmniboxResponse response, bool is_page_controller); // Notifies the page a new omnibox query has begun. HandleNewAutocompleteQuery(bool is_page_controller, string input_text); - // Asyncronously notifies the page of the image data URLs for previous omnibox - // responses. + // Asynchronously notifies the page of the image data URLs for previous + // omnibox responses. HandleAnswerImageData(string image_url, string image_data); };
diff --git a/chrome/browser/ui/webui/snippets_internals/snippets_internals_page_handler.cc b/chrome/browser/ui/webui/snippets_internals/snippets_internals_page_handler.cc index aa0f46e..1f86b91c 100644 --- a/chrome/browser/ui/webui/snippets_internals/snippets_internals_page_handler.cc +++ b/chrome/browser/ui/webui/snippets_internals/snippets_internals_page_handler.cc
@@ -50,8 +50,10 @@ for (variations::IDCollectionKey key : {variations::GOOGLE_WEB_PROPERTIES_ANY_CONTEXT, + variations::GOOGLE_WEB_PROPERTIES_FIRST_PARTY, variations::GOOGLE_WEB_PROPERTIES_SIGNED_IN, - variations::GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT}) { + variations::GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT, + variations::GOOGLE_WEB_PROPERTIES_TRIGGER_FIRST_PARTY}) { const variations::VariationID id = variations::GetGoogleVariationID( key, trial->trial_name(), trial->group_name()); if (id != variations::EMPTY_ID) {
diff --git a/chrome/browser/util/BUILD.gn b/chrome/browser/util/BUILD.gn index 290dfd8..e8388828 100644 --- a/chrome/browser/util/BUILD.gn +++ b/chrome/browser/util/BUILD.gn
@@ -23,7 +23,6 @@ "//content/public/android:content_java", "//third_party/android_deps:androidx_annotation_annotation_java", "//third_party/android_deps:androidx_core_core_java", - "//third_party/android_deps:androidx_legacy_legacy_support_core_utils_java", "//ui/android:ui_full_java", "//url:gurl_java", ]
diff --git a/chrome/browser/web_applications/BUILD.gn b/chrome/browser/web_applications/BUILD.gn index 65b715d..9e1da36b 100644 --- a/chrome/browser/web_applications/BUILD.gn +++ b/chrome/browser/web_applications/BUILD.gn
@@ -118,7 +118,10 @@ ] if (!is_official_build) { - deps += [ "//chromeos/components/sample_system_web_app_ui" ] + deps += [ + "//chromeos/components/file_manager:file_manager_ui", + "//chromeos/components/sample_system_web_app_ui", + ] } }
diff --git a/chrome/browser/web_applications/system_web_app_manager.cc b/chrome/browser/web_applications/system_web_app_manager.cc index d368a83..6aa9111 100644 --- a/chrome/browser/web_applications/system_web_app_manager.cc +++ b/chrome/browser/web_applications/system_web_app_manager.cc
@@ -59,6 +59,7 @@ #include "extensions/common/constants.h" #if !defined(OFFICIAL_BUILD) +#include "chrome/browser/chromeos/web_applications/file_manager_web_app_info.h" #include "chrome/browser/chromeos/web_applications/sample_system_web_app_info.h" #include "chrome/browser/chromeos/web_applications/telemetry_extension_web_app_info.h" #endif // !defined(OFFICIAL_BUILD) @@ -195,6 +196,12 @@ } infos.emplace( + SystemAppType::FILE_MANAGER, + SystemAppInfo("File Manager", GURL("chrome://file-manager"), + base::BindRepeating(&CreateWebAppInfoForFileManager))); + infos.at(SystemAppType::FILE_MANAGER).capture_navigations = true; + + infos.emplace( SystemAppType::SAMPLE, SystemAppInfo( "Sample", GURL("chrome://sample-system-web-app/pwa.html"), @@ -326,6 +333,8 @@ case SystemAppType::TELEMETRY: return base::FeatureList::IsEnabled( chromeos::features::kTelemetryExtension); + case SystemAppType::FILE_MANAGER: + return base::FeatureList::IsEnabled(chromeos::features::kFilesSWA); case SystemAppType::SAMPLE: NOTREACHED(); return false;
diff --git a/chrome/browser/web_applications/system_web_app_manager.h b/chrome/browser/web_applications/system_web_app_manager.h index ddf6d55..add81c9 100644 --- a/chrome/browser/web_applications/system_web_app_manager.h +++ b/chrome/browser/web_applications/system_web_app_manager.h
@@ -57,6 +57,7 @@ SCANNING, DIAGNOSTICS, #if !defined(OFFICIAL_BUILD) + FILE_MANAGER, TELEMETRY, SAMPLE, #endif // !defined(OFFICIAL_BUILD)
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ImageFetchClient.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ImageFetchClient.java index f3e9a5a..dcebe16 100644 --- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ImageFetchClient.java +++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ImageFetchClient.java
@@ -37,6 +37,22 @@ * * @param url URL to request * @param responseConsumer The callback to call with the response + * @return Request ID that can be passed to cancel() + */ + default int sendCancelableRequest(String url, HttpResponseConsumer responseConsumer) { + return 0; + } + + /** + * Send a GET request. TODO(iwells): Remove when the caller switches to the cancelable version. */ default void sendRequest(String url, HttpResponseConsumer responseConsumer) {} + + /** + * Cancel a pending request. Causes the request's response callback to be called with an empty + * response body and net::Error::ERR_ABORTED. + * + * @param requestId ID of request to be canceled. + */ + default void cancel(int requestId) {} }
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index 45c4d4c..14b466a 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-master-1600106373-71253587ca194e48d78c58c419f94bf1bf8da7c5.profdata +chrome-linux-master-1600127994-a617f89793652b5fd810a69f7c568f33dff933e7.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index f9d791c55..24ded4da 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-master-1600084447-6a3b264d40de14a9dcaaf57db5d6240ab2f7fff3.profdata +chrome-mac-master-1600127994-515c383edf0ef93d8562747294461d0f81f3cc39.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index 35132db..1cab3b61 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-master-1600041484-a30af8f2a2acd0d94a4d04ce1984e089b193fca0.profdata +chrome-win64-master-1600084447-f1bad6c3f3b8af9e95e3b8f79a7a1df8147866eb.profdata
diff --git a/chrome/chrome_paks.gni b/chrome/chrome_paks.gni index 0cd6ab7..d94b5a1 100644 --- a/chrome/chrome_paks.gni +++ b/chrome/chrome_paks.gni
@@ -208,10 +208,12 @@ if (!is_official_build) { sources += [ + "$root_gen_dir/chromeos/chromeos_file_manager_resources.pak", "$root_gen_dir/chromeos/chromeos_sample_system_web_app_resources.pak", "$root_gen_dir/chromeos/chromeos_telemetry_extension_resources.pak", ] deps += [ + "//chromeos/resources:file_manager_resources", "//chromeos/resources:sample_system_web_app_resources", "//chromeos/resources:telemetry_extension_resources", ]
diff --git a/chrome/common/search/ntp_logging_events.h b/chrome/common/search/ntp_logging_events.h index a776c381..80dc2ee 100644 --- a/chrome/common/search/ntp_logging_events.h +++ b/chrome/common/search/ntp_logging_events.h
@@ -173,7 +173,10 @@ // Daily refresh was enabled by clicked 'Done' in the richer picker. NTP_BACKGROUND_DAILY_REFRESH_ENABLED = 82, - NTP_EVENT_TYPE_LAST = NTP_BACKGROUND_DAILY_REFRESH_ENABLED + // The NTP modules were shown. + NTP_MODULES_SHOWN = 83, + + NTP_EVENT_TYPE_LAST = NTP_MODULES_SHOWN }; // The different types of events that are logged for NTP search suggestions,
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc index 202d666..e1394cf 100644 --- a/chrome/common/webui_url_constants.cc +++ b/chrome/common/webui_url_constants.cc
@@ -241,7 +241,6 @@ const char kChromeUICryptohomeHost[] = "cryptohome"; const char kChromeUIDeviceEmulatorHost[] = "device-emulator"; const char kChromeUIDiscoverURL[] = "chrome://oobe/discover"; -const char kChromeUIFileManagerHost[] = "file-manager"; const char kChromeUIFirstRunHost[] = "first-run"; const char kChromeUIFirstRunURL[] = "chrome://first-run/"; const char kChromeUIIntenetConfigDialogURL[] =
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h index b97d699..ef5f63f 100644 --- a/chrome/common/webui_url_constants.h +++ b/chrome/common/webui_url_constants.h
@@ -236,7 +236,6 @@ extern const char kChromeUICryptohomeHost[]; extern const char kChromeUIDeviceEmulatorHost[]; extern const char kChromeUIDiscoverURL[]; -extern const char kChromeUIFileManagerHost[]; extern const char kChromeUIFirstRunHost[]; extern const char kChromeUIFirstRunURL[]; extern const char kChromeUIIntenetConfigDialogURL[];
diff --git a/chrome/credential_provider/gaiacp/dllmain.cc b/chrome/credential_provider/gaiacp/dllmain.cc index 323bfb7..5507c68d 100644 --- a/chrome/credential_provider/gaiacp/dllmain.cc +++ b/chrome/credential_provider/gaiacp/dllmain.cc
@@ -67,6 +67,9 @@ // Returns a class factory to create an object of the requested type. STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) { + // This is performed in here to avoid from doing substantial work in DLLMain. + _AtlModule.LogProcessDetails(); + // Check to see if the credential provider has crashed too much recently. // If it has then do not allow it to create any credential providers. if (!credential_provider::WriteToStartupSentinel()) {
diff --git a/chrome/credential_provider/gaiacp/gaia_credential_provider_module.cc b/chrome/credential_provider/gaiacp/gaia_credential_provider_module.cc index ef20858..afcf745 100644 --- a/chrome/credential_provider/gaiacp/gaia_credential_provider_module.cc +++ b/chrome/credential_provider/gaiacp/gaia_credential_provider_module.cc
@@ -104,6 +104,17 @@ } } +void CGaiaCredentialProviderModule::LogProcessDetails() { + wchar_t process_name[MAX_PATH] = {0}; + GetModuleFileName(nullptr, process_name, MAX_PATH); + + LOGFN(INFO) << "GCPW Initialized in " << process_name + << " GCPW Version: " << (CHROME_VERSION_STRING) + << " Windows Build: " + << base::win::OSInfo::GetInstance()->Kernel32BaseVersion() + << " Version:" << GetWindowsVersion(); +} + BOOL CGaiaCredentialProviderModule::DllMain(HINSTANCE /*hinstance*/, DWORD reason, LPVOID reserved) {
diff --git a/chrome/credential_provider/gaiacp/gaia_credential_provider_module.h b/chrome/credential_provider/gaiacp/gaia_credential_provider_module.h index 42d337c1..d6d3dba 100644 --- a/chrome/credential_provider/gaiacp/gaia_credential_provider_module.h +++ b/chrome/credential_provider/gaiacp/gaia_credential_provider_module.h
@@ -47,6 +47,9 @@ // once even if the function is called multiple times. void InitializeCrashReporting(); + // Logs the details of the module such as version, loading process. + void LogProcessDetails(); + private: std::unique_ptr<base::AtExitManager> exit_manager_; bool is_testing_ = false;
diff --git a/chrome/services/sharing/nearby/platform.cc b/chrome/services/sharing/nearby/platform.cc index f735430..fab0eeed1 100644 --- a/chrome/services/sharing/nearby/platform.cc +++ b/chrome/services/sharing/nearby/platform.cc
@@ -60,9 +60,9 @@ std::unique_ptr<SubmittableExecutor> ImplementationPlatform::CreateMultiThreadExecutor(int max_concurrency) { - // Chrome task runner does not support max_concurrency. - return std::make_unique<chrome::SubmittableExecutor>( - base::ThreadPool::CreateTaskRunner({base::MayBlock()})); + // Chrome TaskRunner does not support |max_concurrency|. Simply use our + // SingleThreadExecutor. + return CreateSingleThreadExecutor(); } std::unique_ptr<ScheduledExecutor>
diff --git a/chrome/services/sharing/nearby/platform_v2/ble_medium.cc b/chrome/services/sharing/nearby/platform_v2/ble_medium.cc index 6070f2e..5a4bf52 100644 --- a/chrome/services/sharing/nearby/platform_v2/ble_medium.cc +++ b/chrome/services/sharing/nearby/platform_v2/ble_medium.cc
@@ -12,19 +12,48 @@ BleMedium::BleMedium(bluetooth::mojom::Adapter* adapter) : adapter_(adapter) {} -BleMedium::~BleMedium() = default; +BleMedium::~BleMedium() { + for (auto& it : registered_advertisements_map_) { + // Note: this call is blocking. + it.second->Unregister(); + } +} bool BleMedium::StartAdvertising(const std::string& service_id, const ByteArray& advertisement) { - // TODO(b/154845685): Implement this method. - NOTIMPLEMENTED(); - return false; + StopAdvertising(service_id); + + auto service_uuid = device::BluetoothUUID(service_id); + mojo::PendingRemote<bluetooth::mojom::Advertisement> pending_advertisement; + bool success = adapter_->RegisterAdvertisement( + service_uuid, + std::vector<uint8_t>(advertisement.data(), + advertisement.data() + advertisement.size()), + &pending_advertisement); + + if (!success || !pending_advertisement.is_valid()) + return false; + + auto& remote_advertisement = + registered_advertisements_map_ + .emplace(service_uuid, std::move(pending_advertisement)) + .first->second; + remote_advertisement.set_disconnect_handler(base::BindOnce( + &BleMedium::AdvertisementReleased, base::Unretained(this), service_uuid)); + + return true; } bool BleMedium::StopAdvertising(const std::string& service_id) { - // TODO(b/154845685): Implement this method. - NOTIMPLEMENTED(); - return false; + auto it = + registered_advertisements_map_.find(device::BluetoothUUID(service_id)); + if (it == registered_advertisements_map_.end()) + return true; + + bool success = it->second->Unregister(); + registered_advertisements_map_.erase(it); + + return success; } bool BleMedium::StartScanning(const std::string& service_id, @@ -209,6 +238,11 @@ discovered_ble_peripherals_map_.erase(address); } +void BleMedium::AdvertisementReleased( + const device::BluetoothUUID& service_uuid) { + registered_advertisements_map_.erase(service_uuid); +} + bool BleMedium::IsScanning() { return adapter_observer_.is_bound() && discovery_session_.is_bound() && !discovered_peripheral_callbacks_map_.empty();
diff --git a/chrome/services/sharing/nearby/platform_v2/ble_medium.h b/chrome/services/sharing/nearby/platform_v2/ble_medium.h index eac2628..0b151590 100644 --- a/chrome/services/sharing/nearby/platform_v2/ble_medium.h +++ b/chrome/services/sharing/nearby/platform_v2/ble_medium.h
@@ -55,6 +55,9 @@ void DeviceChanged(bluetooth::mojom::DeviceInfoPtr device) override; void DeviceRemoved(bluetooth::mojom::DeviceInfoPtr device) override; + // A bluetooth::mojom::Advertisement message pipe was destroyed. + void AdvertisementReleased(const device::BluetoothUUID& service_uuid); + // Query if any service IDs are being scanned for. bool IsScanning(); @@ -72,6 +75,10 @@ // events we don't care about outside of discovery don't pile up. mojo::Receiver<bluetooth::mojom::AdapterObserver> adapter_observer_{this}; + // Keyed by service UUID of the advertisement. + std::map<device::BluetoothUUID, mojo::Remote<bluetooth::mojom::Advertisement>> + registered_advertisements_map_; + // Keyed by requested service UUID. Discovery is active as long as this map is // non-empty. std::map<device::BluetoothUUID, DiscoveredPeripheralCallback>
diff --git a/chrome/services/sharing/nearby/platform_v2/ble_medium_unittest.cc b/chrome/services/sharing/nearby/platform_v2/ble_medium_unittest.cc index 2347e72b..0ad91f2 100644 --- a/chrome/services/sharing/nearby/platform_v2/ble_medium_unittest.cc +++ b/chrome/services/sharing/nearby/platform_v2/ble_medium_unittest.cc
@@ -31,6 +31,10 @@ const char kDeviceServiceData1Str[] = "Device_Advertisement1"; const char kDeviceServiceData2Str[] = "Device_Advertisement2"; +std::vector<uint8_t> GetByteVector(const std::string& str) { + return std::vector<uint8_t>(str.begin(), str.end()); +} + } // namespace class BleMediumTest : public testing::Test { @@ -132,10 +136,6 @@ run_loop.Run(); } - std::vector<uint8_t> GetByteVector(const std::string& str) { - return std::vector<uint8_t>(str.begin(), str.end()); - } - void VerifyByteArrayEquals(const ByteArray& byte_array, const std::string& expected_value) { EXPECT_EQ(expected_value, @@ -219,7 +219,48 @@ }; TEST_F(BleMediumTest, TestAdvertising) { - // TODO(b/154845685): Write test. + ASSERT_FALSE(fake_adapter_->GetRegisteredAdvertisementServiceData( + device::BluetoothUUID(kServiceId1))); + ASSERT_FALSE(fake_adapter_->GetRegisteredAdvertisementServiceData( + device::BluetoothUUID(kServiceId2))); + + ble_medium_->StartAdvertising(kServiceId1, ByteArray(kDeviceServiceData1Str)); + EXPECT_EQ(GetByteVector(kDeviceServiceData1Str), + *fake_adapter_->GetRegisteredAdvertisementServiceData( + device::BluetoothUUID(kServiceId1))); + EXPECT_FALSE(fake_adapter_->GetRegisteredAdvertisementServiceData( + device::BluetoothUUID(kServiceId2))); + + ble_medium_->StartAdvertising(kServiceId2, ByteArray(kDeviceServiceData2Str)); + EXPECT_TRUE(fake_adapter_->GetRegisteredAdvertisementServiceData( + device::BluetoothUUID(kServiceId1))); + EXPECT_EQ(GetByteVector(kDeviceServiceData2Str), + *fake_adapter_->GetRegisteredAdvertisementServiceData( + device::BluetoothUUID(kServiceId2))); + + { + base::RunLoop run_loop; + fake_adapter_->SetAdvertisementDestroyedCallback(run_loop.QuitClosure()); + ble_medium_->StopAdvertising(kServiceId1); + run_loop.Run(); + } + + EXPECT_FALSE(fake_adapter_->GetRegisteredAdvertisementServiceData( + device::BluetoothUUID(kServiceId1))); + EXPECT_TRUE(fake_adapter_->GetRegisteredAdvertisementServiceData( + device::BluetoothUUID(kServiceId2))); + + { + base::RunLoop run_loop; + fake_adapter_->SetAdvertisementDestroyedCallback(run_loop.QuitClosure()); + ble_medium_->StopAdvertising(kServiceId2); + run_loop.Run(); + } + + EXPECT_FALSE(fake_adapter_->GetRegisteredAdvertisementServiceData( + device::BluetoothUUID(kServiceId1))); + EXPECT_FALSE(fake_adapter_->GetRegisteredAdvertisementServiceData( + device::BluetoothUUID(kServiceId2))); } TEST_F(BleMediumTest, TestScanning_OneService) {
diff --git a/chrome/services/sharing/nearby/platform_v2/bluetooth_server_socket.cc b/chrome/services/sharing/nearby/platform_v2/bluetooth_server_socket.cc index be629ca..be25b15 100644 --- a/chrome/services/sharing/nearby/platform_v2/bluetooth_server_socket.cc +++ b/chrome/services/sharing/nearby/platform_v2/bluetooth_server_socket.cc
@@ -13,11 +13,16 @@ BluetoothServerSocket::BluetoothServerSocket( mojo::PendingRemote<bluetooth::mojom::ServerSocket> server_socket) - : server_socket_(std::move(server_socket)) {} + : pending_server_socket_(std::move(server_socket)) {} BluetoothServerSocket::~BluetoothServerSocket() = default; std::unique_ptr<api::BluetoothSocket> BluetoothServerSocket::Accept() { + // We're now in the thread that BluetoothServerSocket primarily operates in. + // Bind |server_socket_| in this correct thread. See header documentation. + if (pending_server_socket_) + server_socket_.Bind(std::move(pending_server_socket_)); + bluetooth::mojom::AcceptConnectionResultPtr result; bool success = server_socket_->Accept(&result); @@ -31,7 +36,7 @@ } Exception BluetoothServerSocket::Close() { - // TODO(b/154849933): Implement this in a subsequent CL. + pending_server_socket_.reset(); server_socket_.reset(); return {Exception::kSuccess}; }
diff --git a/chrome/services/sharing/nearby/platform_v2/bluetooth_server_socket.h b/chrome/services/sharing/nearby/platform_v2/bluetooth_server_socket.h index 656673f..1ebd149 100644 --- a/chrome/services/sharing/nearby/platform_v2/bluetooth_server_socket.h +++ b/chrome/services/sharing/nearby/platform_v2/bluetooth_server_socket.h
@@ -31,6 +31,14 @@ Exception Close() override; private: + // BluetoothServerSocket is created on the main thread, but its public methods + // are used on a separate dedicated thread. mojo::Remote objects (namely, + // |server_socket_|) must be bound on the same thread they are used on, to + // prevent deadlock. So, we hold onto this mojo::PendingRemote + // |pending_server_socket_| until Accept() is called, at which point + // |server_socket_| is bound with it (it is acceptable to pass a + // mojo::PendingRemote around multiple threads). + mojo::PendingRemote<bluetooth::mojom::ServerSocket> pending_server_socket_; mojo::Remote<bluetooth::mojom::ServerSocket> server_socket_; };
diff --git a/chrome/services/sharing/nearby/platform_v2/bluetooth_server_socket_unittest.cc b/chrome/services/sharing/nearby/platform_v2/bluetooth_server_socket_unittest.cc index 2a05983..9ef2a9e0 100644 --- a/chrome/services/sharing/nearby/platform_v2/bluetooth_server_socket_unittest.cc +++ b/chrome/services/sharing/nearby/platform_v2/bluetooth_server_socket_unittest.cc
@@ -90,8 +90,19 @@ std::move(fake_server_socket), pending_server_socket.InitWithNewPipeAndPassReceiver()); - bluetooth_server_socket_ = std::make_unique<BluetoothServerSocket>( - std::move(pending_server_socket)); + // In production Nearby Connections code, BluetoothServerSocket is created + // on a thread separate from the thread it is later used on. Replicate this + // behavior by creating |bluetooth_server_socket_| on a dedicated thread. + base::RunLoop run_loop; + auto creation_task_runner = base::ThreadPool::CreateSingleThreadTaskRunner( + {base::MayBlock()}, base::SingleThreadTaskRunnerThreadMode::DEDICATED); + creation_task_runner->PostTask( + FROM_HERE, base::BindLambdaForTesting([&] { + bluetooth_server_socket_ = std::make_unique<BluetoothServerSocket>( + std::move(pending_server_socket)); + run_loop.Quit(); + })); + run_loop.Run(); } protected:
diff --git a/chrome/services/sharing/nearby/test_support/fake_adapter.cc b/chrome/services/sharing/nearby/test_support/fake_adapter.cc index 77a76c85..452affa6 100644 --- a/chrome/services/sharing/nearby/test_support/fake_adapter.cc +++ b/chrome/services/sharing/nearby/test_support/fake_adapter.cc
@@ -13,6 +13,21 @@ namespace { +class FakeAdvertisement : public mojom::Advertisement { + public: + explicit FakeAdvertisement(base::OnceClosure on_destroy_callback) + : on_destroy_callback_(std::move(on_destroy_callback)) {} + ~FakeAdvertisement() override { std::move(on_destroy_callback_).Run(); } + + private: + // mojom::Advertisement: + void Unregister(UnregisterCallback callback) override { + std::move(callback).Run(); + } + + base::OnceClosure on_destroy_callback_; +}; + class FakeDiscoverySession : public mojom::DiscoverySession { public: explicit FakeDiscoverySession(base::OnceClosure on_destroy_callback) @@ -88,6 +103,29 @@ std::move(callback).Run(); } +void FakeAdapter::RegisterAdvertisement( + const device::BluetoothUUID& service_uuid, + const std::vector<uint8_t>& service_data, + RegisterAdvertisementCallback callback) { + if (!should_advertisement_registration_succeed_) { + std::move(callback).Run(mojo::NullRemote()); + return; + } + + registered_advertisements_map_.insert({service_uuid, service_data}); + + auto advertisement = std::make_unique<FakeAdvertisement>( + base::BindOnce(&FakeAdapter::OnAdvertisementDestroyed, + base::Unretained(this), service_uuid)); + + mojo::PendingRemote<mojom::Advertisement> pending_advertisement; + mojo::MakeSelfOwnedReceiver( + std::move(advertisement), + pending_advertisement.InitWithNewPipeAndPassReceiver()); + + std::move(callback).Run(std::move(pending_advertisement)); +} + void FakeAdapter::SetDiscoverable(bool discoverable, SetDiscoverableCallback callback) { discoverable_ = discoverable; @@ -181,6 +219,17 @@ should_discovery_succeed_ = should_discovery_succeed; } +void FakeAdapter::SetAdvertisementDestroyedCallback( + base::OnceClosure callback) { + on_advertisement_destroyed_callback_ = std::move(callback); +} + +const std::vector<uint8_t>* FakeAdapter::GetRegisteredAdvertisementServiceData( + const device::BluetoothUUID& service_uuid) { + auto it = registered_advertisements_map_.find(service_uuid); + return it == registered_advertisements_map_.end() ? nullptr : &it->second; +} + void FakeAdapter::SetDiscoverySessionDestroyedCallback( base::OnceClosure callback) { on_discovery_session_destroyed_callback_ = std::move(callback); @@ -218,6 +267,14 @@ service_uuid); } +void FakeAdapter::OnAdvertisementDestroyed( + const device::BluetoothUUID& service_uuid) { + DCHECK(!registered_advertisements_map_.empty()); + registered_advertisements_map_.erase(service_uuid); + if (on_advertisement_destroyed_callback_) + std::move(on_advertisement_destroyed_callback_).Run(); +} + void FakeAdapter::OnDiscoverySessionDestroyed() { DCHECK(discovery_session_); discovery_session_ = nullptr;
diff --git a/chrome/services/sharing/nearby/test_support/fake_adapter.h b/chrome/services/sharing/nearby/test_support/fake_adapter.h index 4b4e15c..188759b 100644 --- a/chrome/services/sharing/nearby/test_support/fake_adapter.h +++ b/chrome/services/sharing/nearby/test_support/fake_adapter.h
@@ -27,6 +27,9 @@ void GetInfo(GetInfoCallback callback) override; void AddObserver(mojo::PendingRemote<mojom::AdapterObserver> observer, AddObserverCallback callback) override; + void RegisterAdvertisement(const device::BluetoothUUID& service_uuid, + const std::vector<uint8_t>& service_data, + RegisterAdvertisementCallback callback) override; void SetDiscoverable(bool discoverable, SetDiscoverableCallback callback) override; void SetName(const std::string& name, SetNameCallback callback) override; @@ -39,6 +42,9 @@ const device::BluetoothUUID& service_uuid, CreateRfcommServiceCallback callback) override; + void SetAdvertisementDestroyedCallback(base::OnceClosure callback); + const std::vector<uint8_t>* GetRegisteredAdvertisementServiceData( + const device::BluetoothUUID& service_uuid); void SetShouldDiscoverySucceed(bool should_discovery_succeed); void SetDiscoverySessionDestroyedCallback(base::OnceClosure callback); bool IsDiscoverySessionActive(); @@ -61,11 +67,18 @@ bool discovering_ = false; private: + void OnAdvertisementDestroyed(const device::BluetoothUUID& service_uuid); void OnDiscoverySessionDestroyed(); - mojom::DiscoverySession* discovery_session_ = nullptr; + bool should_advertisement_registration_succeed_ = true; + std::map<device::BluetoothUUID, std::vector<uint8_t>> + registered_advertisements_map_; + base::OnceClosure on_advertisement_destroyed_callback_; + bool should_discovery_succeed_ = true; + mojom::DiscoverySession* discovery_session_ = nullptr; base::OnceClosure on_discovery_session_destroyed_callback_; + std::set<std::pair<std::string, device::BluetoothUUID>> allowed_connections_for_address_and_uuid_pair_; std::set<std::pair<std::string, device::BluetoothUUID>>
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 6eb4883..bddbc4d 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -1273,6 +1273,7 @@ "../browser/storage/durable_storage_browsertest.cc", "../browser/storage_access_api/api_browsertest.cc", "../browser/subresource_filter/ad_tagging_browsertest.cc", + "../browser/subresource_filter/ads_intervention_manager_browsertest.cc", "../browser/subresource_filter/ruleset_browsertest.cc", "../browser/subresource_filter/subresource_filter_browser_test_harness.cc", "../browser/subresource_filter/subresource_filter_browser_test_harness.h", @@ -2718,6 +2719,8 @@ "../browser/enterprise/reporting/report_scheduler_browsertest.cc", "../browser/policy/cloud/chrome_browser_cloud_management_browsertest.cc", ] + + deps += [ "//components/crash/content/browser/error_reporting:mock_crash_endpoint" ] } else { # !is_chromeos sources -= [ "../browser/invalidation/profile_invalidation_provider_factory_browsertest.cc", @@ -3624,6 +3627,7 @@ "../browser/status_icons/status_tray_unittest.cc", "../browser/storage/durable_storage_permission_context_unittest.cc", "../browser/storage_access_api/storage_access_grant_permission_context_unittest.cc", + "../browser/subresource_filter/ads_intervention_manager_unittest.cc", "../browser/subresource_filter/subresource_filter_abusive_unittest.cc", "../browser/subresource_filter/subresource_filter_configuration_unittest.cc", "../browser/subresource_filter/subresource_filter_content_settings_manager_unittest.cc", @@ -5637,6 +5641,7 @@ sources += [ "../../ui/views/controls/webview/web_dialog_view_unittest.cc", "../../ui/views/controls/webview/webview_unittest.cc", + "../browser/ui/in_product_help/feature_promo_snooze_service_unittest.cc", "../browser/ui/media_router/media_router_ui_unittest.cc", "../browser/ui/views/accelerator_table_unittest.cc", "../browser/ui/views/accelerator_table_unittest_mac.mm",
diff --git a/chrome/test/android/BUILD.gn b/chrome/test/android/BUILD.gn index fb9ad051..cc999c43 100644 --- a/chrome/test/android/BUILD.gn +++ b/chrome/test/android/BUILD.gn
@@ -302,7 +302,6 @@ "//third_party/android_deps:androidx_appcompat_appcompat_java", "//third_party/android_deps:androidx_core_core_java", "//third_party/android_deps:androidx_fragment_fragment_java", - "//third_party/android_deps:androidx_legacy_legacy_support_v4_java", "//third_party/android_deps:androidx_lifecycle_lifecycle_common_java", "//third_party/android_deps:androidx_recyclerview_recyclerview_java", "//third_party/android_deps:com_google_code_findbugs_jsr305_java",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeJUnit4ClassRunner.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeJUnit4ClassRunner.java index f46a4c5..a51dd03 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeJUnit4ClassRunner.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeJUnit4ClassRunner.java
@@ -23,9 +23,9 @@ import org.chromium.chrome.browser.ChromeVersionInfo; import org.chromium.chrome.test.util.ChromeRestriction; import org.chromium.chrome.test.util.browser.Features; +import org.chromium.components.policy.test.annotations.Policies; import org.chromium.content_public.browser.test.ContentJUnit4ClassRunner; import org.chromium.content_public.browser.test.util.TestThreadUtils; -import org.chromium.policy.test.annotations.Policies; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method;
diff --git a/chrome/test/data/pdf/annotations_feature_enabled_test.js b/chrome/test/data/pdf/annotations_feature_enabled_test.js index 52dad0c9..838b87e 100644 --- a/chrome/test/data/pdf/annotations_feature_enabled_test.js +++ b/chrome/test/data/pdf/annotations_feature_enabled_test.js
@@ -68,12 +68,6 @@ chrome.test.assertEq(3, cameras.length); - if (updateEnabled) { - // TODO (https://crbug.com/1120279): Determine what the expectations - // below should be for the new UI and fix if needed to meet them. - return; - } - const expectations = [ {top: 44.25, left: -106.5, right: 718.5, bottom: -448.5}, {top: 23.25, left: -3.75, right: 408.75, bottom: -223.125}, @@ -82,7 +76,10 @@ for (const expectation of expectations) { const actual = cameras.shift(); - chrome.test.assertEq(expectation.top, actual.top); + const expectationTop = updateEnabled ? + Math.min(2.25, expectation.top - 21) : + expectation.top; + chrome.test.assertEq(expectationTop, actual.top); chrome.test.assertEq(expectation.left, actual.left); chrome.test.assertEq(expectation.bottom, actual.bottom); chrome.test.assertEq(expectation.right, actual.right); @@ -392,7 +389,7 @@ const toolbar = document.createElement('viewer-pdf-toolbar-new'); document.body.appendChild(toolbar); toolbar.toggleAnnotation(); - chrome.test.assertTrue(toolbar.annotationMode); + toolbar.annotationMode = true; await toolbar.addEventListener('display-annotations-changed', async e => { chrome.test.assertFalse(e.detail);
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn index dc99aab5..3ba36ed 100644 --- a/chrome/test/data/webui/BUILD.gn +++ b/chrome/test/data/webui/BUILD.gn
@@ -268,6 +268,7 @@ "$root_gen_dir/chrome/test/data/webui/cr_components/chromeos/network/network_nameservers_test.m.js", "$root_gen_dir/chrome/test/data/webui/cr_components/chromeos/network/network_password_input_test.m.js", "$root_gen_dir/chrome/test/data/webui/cr_components/chromeos/network/network_property_list_mojo_test.m.js", + "$root_gen_dir/chrome/test/data/webui/cr_components/chromeos/network/network_proxy_input_test.m.js", "$root_gen_dir/chrome/test/data/webui/cr_components/chromeos/network/network_select_test.m.js", "$root_gen_dir/chrome/test/data/webui/cr_components/chromeos/network/network_siminfo_test.m.js", "$root_gen_dir/chrome/test/data/webui/cr_elements/cr_searchable_drop_down_tests.m.js",
diff --git a/chrome/test/data/webui/bluetooth_internals_browsertest.js b/chrome/test/data/webui/bluetooth_internals_browsertest.js index 4dddc7b9..7bc01feb 100644 --- a/chrome/test/data/webui/bluetooth_internals_browsertest.js +++ b/chrome/test/data/webui/bluetooth_internals_browsertest.js
@@ -126,6 +126,11 @@ this.methodCalled('addObserver', observer); } + async registerAdvertisement() { + this.methodCalled('registerAdvertisement'); + return {advertisement: null}; + } + async setDiscoverable() { this.methodCalled('setDiscoverable'); return {success: true};
diff --git a/chrome/test/data/webui/chromeos/crostini_installer_app_test.js b/chrome/test/data/webui/chromeos/crostini_installer_app_test.js index 7afe8f9..617eea1 100644 --- a/chrome/test/data/webui/chromeos/crostini_installer_app_test.js +++ b/chrome/test/data/webui/chromeos/crostini_installer_app_test.js
@@ -149,7 +149,8 @@ expectEquals(fakeBrowserProxy.handler.getCallCount('install'), 1); expectTrue(getInstallButton().hidden); - fakeBrowserProxy.page.onProgressUpdate(InstallerState.kStartConcierge, 0.5); + fakeBrowserProxy.page.onProgressUpdate( + InstallerState.kCreateDiskImage, 0.5); await flushTasks(); expectTrue( !!app.$$('#installing-message > div').textContent.trim(),
diff --git a/chrome/test/data/webui/cr_components/chromeos/cr_components_chromeos_browsertest.js b/chrome/test/data/webui/cr_components/chromeos/cr_components_chromeos_browsertest.js index 507ea62..cc746ffb 100644 --- a/chrome/test/data/webui/cr_components/chromeos/cr_components_chromeos_browsertest.js +++ b/chrome/test/data/webui/cr_components/chromeos/cr_components_chromeos_browsertest.js
@@ -43,6 +43,7 @@ ['NetworkNameservers', 'network/network_nameservers_test.js', []], ['NetworkPasswordInput', 'network/network_password_input_test.js', []], ['NetworkPropertyListMojo', 'network/network_property_list_mojo_test.js', []], + ['NetworkProxyInput', 'network/network_proxy_input_test.js', []], ['NetworkSiminfo', 'network/network_siminfo_test.js', []], ].forEach(test => registerTest('NetworkComponents', 'os-settings', ...test));
diff --git a/chrome/test/data/webui/cr_components/chromeos/cr_components_chromeos_v3_browsertest.js b/chrome/test/data/webui/cr_components/chromeos/cr_components_chromeos_v3_browsertest.js index 84675bf..e7c58cd3 100644 --- a/chrome/test/data/webui/cr_components/chromeos/cr_components_chromeos_v3_browsertest.js +++ b/chrome/test/data/webui/cr_components/chromeos/cr_components_chromeos_v3_browsertest.js
@@ -25,6 +25,7 @@ ['NetworkNameservers', 'network/network_nameservers_test.m.js'], ['NetworkPasswordInput', 'network/network_password_input_test.m.js'], ['NetworkPropertyListMojo', 'network/network_property_list_mojo_test.m.js'], + ['NetworkProxyInput', 'network/network_proxy_input_test.m.js'], ['NetworkSelect', 'network/network_select_test.m.js'], ['NetworkSiminfo', 'network/network_siminfo_test.m.js'], ].forEach(test => registerTest('NetworkComponents', ...test));
diff --git a/chrome/test/data/webui/cr_components/chromeos/network/BUILD.gn b/chrome/test/data/webui/cr_components/chromeos/network/BUILD.gn index 5a744c3e..1eb1e489 100644 --- a/chrome/test/data/webui/cr_components/chromeos/network/BUILD.gn +++ b/chrome/test/data/webui/cr_components/chromeos/network/BUILD.gn
@@ -21,6 +21,7 @@ "network_nameservers_test.js", "network_password_input_test.js", "network_property_list_mojo_test.js", + "network_proxy_input_test.js", "network_select_test.js", "network_siminfo_test.js", ]
diff --git a/chrome/test/data/webui/cr_components/chromeos/network/network_proxy_input_test.js b/chrome/test/data/webui/cr_components/chromeos/network/network_proxy_input_test.js new file mode 100644 index 0000000..190362f0 --- /dev/null +++ b/chrome/test/data/webui/cr_components/chromeos/network/network_proxy_input_test.js
@@ -0,0 +1,33 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// clang-format off +// #import 'chrome://os-settings/strings.m.js'; +// #import 'chrome://resources/cr_components/chromeos/network/network_proxy_input.m.js'; +// +// #import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +// clang-format on + +suite('NetworkProxyInputTest', function() { + /** @type {!NetworkProxyInput|undefined} */ + let proxyInput; + + setup(function() { + proxyInput = document.createElement('network-proxy-input'); + document.body.appendChild(proxyInput); + Polymer.dom.flush(); + }); + + test('Editable inputs', function() { + assertFalse(proxyInput.editable); + assertTrue(proxyInput.$$('#host').readonly); + assertTrue(proxyInput.$$('#port').readonly); + + proxyInput.editable = true; + Polymer.dom.flush(); + + assertFalse(proxyInput.$$('#host').readonly); + assertFalse(proxyInput.$$('#port').readonly); + }); +});
diff --git a/chrome/test/data/webui/new_tab_page/app_test.js b/chrome/test/data/webui/new_tab_page/app_test.js index 31cdb0c..a761d4e 100644 --- a/chrome/test/data/webui/new_tab_page/app_test.js +++ b/chrome/test/data/webui/new_tab_page/app_test.js
@@ -456,11 +456,11 @@ } ]); await flushTasks(); // Wait for module descriptor resolution. - $$(app, '#modules').render(); // Assert. const modules = app.shadowRoot.querySelectorAll('ntp-module-wrapper'); assertEquals(2, modules.length); + assertEquals(1, testProxy.handler.getCallCount('onModulesRendered')); }); }); });
diff --git a/chromecast/browser/android/BUILD.gn b/chromecast/browser/android/BUILD.gn index 036cd58e..9c0cf707 100644 --- a/chromecast/browser/android/BUILD.gn +++ b/chromecast/browser/android/BUILD.gn
@@ -117,7 +117,6 @@ deps = [ "//base:base_java", "//chromecast/base:base_java", - "//third_party/android_deps:androidx_legacy_legacy_support_core_utils_java", "//third_party/android_deps:androidx_localbroadcastmanager_localbroadcastmanager_java", ] } @@ -192,7 +191,6 @@ "//third_party/android_deps:androidx_core_core_java", # TODO(slan): We may need to pass this in as a parameter. - "//third_party/android_deps:androidx_legacy_legacy_support_core_utils_java", "//third_party/android_deps:androidx_localbroadcastmanager_localbroadcastmanager_java", "//third_party/android_deps:androidx_slice_slice_builders_java", @@ -256,7 +254,6 @@ "//chromecast/base:base_java", "//chromecast/base:cast_base_test_utils_java", "//content/public/android:content_java", - "//third_party/android_deps:androidx_legacy_legacy_support_core_utils_java", "//third_party/android_deps:androidx_localbroadcastmanager_localbroadcastmanager_java", "//third_party/hamcrest:hamcrest_java", ]
diff --git a/chromecast/media/audio/audio_log.cc b/chromecast/media/audio/audio_log.cc index fbc5b2b..9c1d4a7 100644 --- a/chromecast/media/audio/audio_log.cc +++ b/chromecast/media/audio/audio_log.cc
@@ -188,7 +188,9 @@ } void AudioLogMessage::Cancel() { - buffer_->Cancel(); + if (buffer_) { + buffer_->Cancel(); + } } void InitializeAudioLog() {
diff --git a/chromecast/media/cma/backend/android/BUILD.gn b/chromecast/media/cma/backend/android/BUILD.gn index 13649df2..dd4f679 100644 --- a/chromecast/media/cma/backend/android/BUILD.gn +++ b/chromecast/media/cma/backend/android/BUILD.gn
@@ -74,7 +74,6 @@ "//chromecast/base:base_java", "//chromecast/public:volume_control_enums_java", "//third_party/android_deps:androidx_annotation_annotation_java", - "//third_party/android_deps:androidx_legacy_legacy_support_v13_java", ] annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ] }
diff --git a/chromeos/components/BUILD.gn b/chromeos/components/BUILD.gn index 0a1402c..678048a4 100644 --- a/chromeos/components/BUILD.gn +++ b/chromeos/components/BUILD.gn
@@ -57,6 +57,7 @@ if (!is_official_build) { deps += [ + "//chromeos/components/file_manager/resources:closure_compile", "//chromeos/components/sample_system_web_app_ui:closure_compile", "//chromeos/components/telemetry_extension_ui:closure_compile", ]
diff --git a/chromeos/components/cdm_factory_daemon/cdm_storage_adapter_unittest.cc b/chromeos/components/cdm_factory_daemon/cdm_storage_adapter_unittest.cc index 37985dc..714ce17 100644 --- a/chromeos/components/cdm_factory_daemon/cdm_storage_adapter_unittest.cc +++ b/chromeos/components/cdm_factory_daemon/cdm_storage_adapter_unittest.cc
@@ -84,8 +84,7 @@ }); cdm_storage_adapter_ = std::make_unique<CdmStorageAdapter>( mock_frame_interface_factory_.get(), - daemon_storage_mojo_ - .BindNewEndpointAndPassDedicatedReceiverForTesting()); + daemon_storage_mojo_.BindNewEndpointAndPassDedicatedReceiver()); task_environment_.RunUntilIdle(); }
diff --git a/chromeos/components/cdm_factory_daemon/content_decryption_module_adapter_unittest.cc b/chromeos/components/cdm_factory_daemon/content_decryption_module_adapter_unittest.cc index 9172c10..8417658 100644 --- a/chromeos/components/cdm_factory_daemon/content_decryption_module_adapter_unittest.cc +++ b/chromeos/components/cdm_factory_daemon/content_decryption_module_adapter_unittest.cc
@@ -130,7 +130,7 @@ ContentDecryptionModuleAdapterTest() { mojo::AssociatedRemote<cdm::mojom::ContentDecryptionModule> daemon_cdm_mojo; mock_daemon_cdm_ = std::make_unique<MockDaemonCdm>( - daemon_cdm_mojo.BindNewEndpointAndPassDedicatedReceiverForTesting()); + daemon_cdm_mojo.BindNewEndpointAndPassDedicatedReceiver()); cdm_adapter_ = base::WrapRefCounted<ContentDecryptionModuleAdapter>( new ContentDecryptionModuleAdapter( nullptr /* storage */, std::move(daemon_cdm_mojo),
diff --git a/chromeos/components/file_manager/BUILD.gn b/chromeos/components/file_manager/BUILD.gn new file mode 100644 index 0000000..14a08c17 --- /dev/null +++ b/chromeos/components/file_manager/BUILD.gn
@@ -0,0 +1,31 @@ +# Copyright 2020 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//mojo/public/tools/bindings/mojom.gni") + +assert(is_chromeos, "File Manager is Chrome OS only") +assert(!is_official_build, "File Manager is only built for unofficial builds") + +mojom("file_manager_mojom") { + sources = [ "file_manager.mojom" ] +} + +static_library("file_manager_ui") { + sources = [ + "file_manager_page_handler.cc", + "file_manager_page_handler.h", + "file_manager_ui.cc", + "file_manager_ui.h", + "url_constants.cc", + "url_constants.h", + ] + + deps = [ + ":file_manager_mojom", + "//chromeos/constants", + "//chromeos/resources:file_manager_resources", + "//content/public/browser", + "//ui/webui", + ] +}
diff --git a/chromeos/components/file_manager/DEPS b/chromeos/components/file_manager/DEPS new file mode 100644 index 0000000..4cfbff5 --- /dev/null +++ b/chromeos/components/file_manager/DEPS
@@ -0,0 +1,6 @@ +include_rules = [ + # Do not add chrome here (use a delegate instead). + "+chromeos/grit/chromeos_file_manager_resources.h", + "+content/public/browser", + "+ui/webui", +]
diff --git a/chrome/browser/ui/webui/chromeos/file_manager/OWNERS b/chromeos/components/file_manager/OWNERS similarity index 100% rename from chrome/browser/ui/webui/chromeos/file_manager/OWNERS rename to chromeos/components/file_manager/OWNERS
diff --git a/chrome/browser/ui/webui/chromeos/file_manager/file_manager.mojom b/chromeos/components/file_manager/file_manager.mojom similarity index 100% rename from chrome/browser/ui/webui/chromeos/file_manager/file_manager.mojom rename to chromeos/components/file_manager/file_manager.mojom
diff --git a/chrome/browser/ui/webui/chromeos/file_manager/file_manager_page_handler.cc b/chromeos/components/file_manager/file_manager_page_handler.cc similarity index 77% rename from chrome/browser/ui/webui/chromeos/file_manager/file_manager_page_handler.cc rename to chromeos/components/file_manager/file_manager_page_handler.cc index 52255d05a..ff83729 100644 --- a/chrome/browser/ui/webui/chromeos/file_manager/file_manager_page_handler.cc +++ b/chromeos/components/file_manager/file_manager_page_handler.cc
@@ -2,15 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/webui/chromeos/file_manager/file_manager_ui.h" +#include "chromeos/components/file_manager/file_manager_page_handler.h" #include "base/bind.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/webui/chromeos/file_manager/file_manager_page_handler.h" -#include "chrome/common/url_constants.h" -#include "chrome/grit/browser_resources.h" -#include "content/public/browser/web_ui.h" -#include "content/public/browser/web_ui_data_source.h" namespace chromeos { namespace file_manager {
diff --git a/chrome/browser/ui/webui/chromeos/file_manager/file_manager_page_handler.h b/chromeos/components/file_manager/file_manager_page_handler.h similarity index 79% rename from chrome/browser/ui/webui/chromeos/file_manager/file_manager_page_handler.h rename to chromeos/components/file_manager/file_manager_page_handler.h index 603c689..9cc7f316 100644 --- a/chrome/browser/ui/webui/chromeos/file_manager/file_manager_page_handler.h +++ b/chromeos/components/file_manager/file_manager_page_handler.h
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_FILE_MANAGER_FILE_MANAGER_PAGE_HANDLER_H_ -#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_FILE_MANAGER_FILE_MANAGER_PAGE_HANDLER_H_ +#ifndef CHROMEOS_COMPONENTS_FILE_MANAGER_FILE_MANAGER_PAGE_HANDLER_H_ +#define CHROMEOS_COMPONENTS_FILE_MANAGER_FILE_MANAGER_PAGE_HANDLER_H_ #include <memory> #include "base/macros.h" #include "base/timer/timer.h" -#include "chrome/browser/ui/webui/chromeos/file_manager/file_manager.mojom.h" +#include "chromeos/components/file_manager/file_manager.mojom.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/receiver.h" @@ -47,4 +47,4 @@ } // namespace file_manager } // namespace chromeos -#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_FILE_MANAGER_FILE_MANAGER_PAGE_HANDLER_H_ +#endif // CHROMEOS_COMPONENTS_FILE_MANAGER_FILE_MANAGER_PAGE_HANDLER_H_
diff --git a/chromeos/components/file_manager/file_manager_ui.cc b/chromeos/components/file_manager/file_manager_ui.cc new file mode 100644 index 0000000..b70e0d8 --- /dev/null +++ b/chromeos/components/file_manager/file_manager_ui.cc
@@ -0,0 +1,68 @@ +// Copyright (c) 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos/components/file_manager/file_manager_ui.h" + +#include "base/memory/ptr_util.h" +#include "chromeos/components/file_manager/file_manager_page_handler.h" +#include "chromeos/components/file_manager/url_constants.h" +#include "chromeos/grit/chromeos_file_manager_resources.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_ui.h" +#include "content/public/browser/web_ui_data_source.h" + +namespace chromeos { +namespace file_manager { + +FileManagerUI::FileManagerUI(content::WebUI* web_ui) + : MojoWebUIController(web_ui) { + auto source = base::WrapUnique(content::WebUIDataSource::Create( + chromeos::file_manager::kChromeUIFileManagerHost)); + // The HTML content loaded on chrome://file-manager. + source->AddResourcePath("", IDR_FILE_MANAGER_FILE_MANAGER_HTML); + + // The resources requested by chrome://file-manager HTML. + source->AddResourcePath("file_manager.css", + IDR_FILE_MANAGER_FILE_MANAGER_CSS); + source->AddResourcePath("file_manager.js", IDR_FILE_MANAGER_FILE_MANAGER_JS); + source->AddResourcePath("file_manager.mojom-lite.js", + IDR_FILE_MANAGER_MOJO_LITE_JS); + source->AddResourcePath("browser_proxy.js", + IDR_FILE_MANAGER_BROWSER_PROXY_JS); + +#if !DCHECK_IS_ON() + // If a user goes to an invalid url and non-DCHECK mode (DHECK = debug mode) + // is set, serve a default page so the user sees your default page instead + // of an unexpected error. But if DCHECK is set, the user will be a + // developer and be able to identify an error occurred. + source->SetDefaultResource(IDR_FILE_MANAGER_FILE_MANAGER_HTML); +#endif // !DCHECK_IS_ON() + + auto* browser_context = web_ui->GetWebContents()->GetBrowserContext(); + content::WebUIDataSource::Add(browser_context, source.release()); +} + +FileManagerUI::~FileManagerUI() = default; + +void FileManagerUI::BindInterface( + mojo::PendingReceiver<mojom::PageHandlerFactory> pending_receiver) { + if (page_factory_receiver_.is_bound()) { + page_factory_receiver_.reset(); + } + page_factory_receiver_.Bind(std::move(pending_receiver)); +} + +void FileManagerUI::CreatePageHandler( + mojo::PendingRemote<mojom::Page> pending_page, + mojo::PendingReceiver<mojom::PageHandler> pending_page_handler) { + DCHECK(pending_page.is_valid()); + + page_handler_ = std::make_unique<FileManagerPageHandler>( + std::move(pending_page_handler), std::move(pending_page)); +} + +WEB_UI_CONTROLLER_TYPE_IMPL(FileManagerUI) + +} // namespace file_manager +} // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/file_manager/file_manager_ui.h b/chromeos/components/file_manager/file_manager_ui.h similarity index 81% rename from chrome/browser/ui/webui/chromeos/file_manager/file_manager_ui.h rename to chromeos/components/file_manager/file_manager_ui.h index b33ab46..5d30f88 100644 --- a/chrome/browser/ui/webui/chromeos/file_manager/file_manager_ui.h +++ b/chromeos/components/file_manager/file_manager_ui.h
@@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_FILE_MANAGER_FILE_MANAGER_UI_H_ -#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_FILE_MANAGER_FILE_MANAGER_UI_H_ +#ifndef CHROMEOS_COMPONENTS_FILE_MANAGER_FILE_MANAGER_UI_H_ +#define CHROMEOS_COMPONENTS_FILE_MANAGER_FILE_MANAGER_UI_H_ #include <memory> -#include "chrome/browser/ui/webui/chromeos/file_manager/file_manager.mojom.h" +#include "chromeos/components/file_manager/file_manager.mojom.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/receiver.h" @@ -47,4 +47,4 @@ } // namespace file_manager } // namespace chromeos -#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_FILE_MANAGER_FILE_MANAGER_UI_H_ +#endif // CHROMEOS_COMPONENTS_FILE_MANAGER_FILE_MANAGER_UI_H_
diff --git a/chromeos/components/file_manager/resources/BUILD.gn b/chromeos/components/file_manager/resources/BUILD.gn new file mode 100644 index 0000000..5d64f74 --- /dev/null +++ b/chromeos/components/file_manager/resources/BUILD.gn
@@ -0,0 +1,17 @@ +# Copyright 2020 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//third_party/closure_compiler/compile_js.gni") + +js_library("file_manager_js") { + sources = [ + "browser_proxy.js", + "file_manager.js", + ] + deps = [ "//chromeos/components/file_manager:file_manager_mojom_js_library_for_compile" ] +} + +js_type_check("closure_compile") { + deps = [ ":file_manager_js" ] +}
diff --git a/chrome/browser/resources/chromeos/file_manager/browser_proxy.js b/chromeos/components/file_manager/resources/browser_proxy.js similarity index 100% rename from chrome/browser/resources/chromeos/file_manager/browser_proxy.js rename to chromeos/components/file_manager/resources/browser_proxy.js
diff --git a/chrome/browser/resources/chromeos/file_manager/file_manager.css b/chromeos/components/file_manager/resources/file_manager.css similarity index 98% rename from chrome/browser/resources/chromeos/file_manager/file_manager.css rename to chromeos/components/file_manager/resources/file_manager.css index 4a56066..2f32ae0 100644 --- a/chrome/browser/resources/chromeos/file_manager/file_manager.css +++ b/chromeos/components/file_manager/resources/file_manager.css
@@ -1,4 +1,3 @@ /* Copyright (c) 2020 The Chromium Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -
diff --git a/chrome/browser/resources/chromeos/file_manager/file_manager.html b/chromeos/components/file_manager/resources/file_manager.html similarity index 100% rename from chrome/browser/resources/chromeos/file_manager/file_manager.html rename to chromeos/components/file_manager/resources/file_manager.html
diff --git a/chrome/browser/resources/chromeos/file_manager/file_manager.js b/chromeos/components/file_manager/resources/file_manager.js similarity index 88% rename from chrome/browser/resources/chromeos/file_manager/file_manager.js rename to chromeos/components/file_manager/resources/file_manager.js index 31beeeb..8ed4391 100644 --- a/chrome/browser/resources/chromeos/file_manager/file_manager.js +++ b/chromeos/components/file_manager/resources/file_manager.js
@@ -20,6 +20,6 @@ console.log('eh? ' + something + '. what? ' + other); }); -document.addEventListener('DOMContentLoaded', function() { - alert('DOMContentLoaded'); +document.addEventListener('DOMContentLoaded', () => { + console.info('File manager launched ...'); });
diff --git a/chromeos/components/file_manager/resources/file_manager_resources.grd b/chromeos/components/file_manager/resources/file_manager_resources.grd new file mode 100644 index 0000000..4044b190 --- /dev/null +++ b/chromeos/components/file_manager/resources/file_manager_resources.grd
@@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> + <outputs> + <output filename="grit/chromeos_file_manager_resources.h" type="rc_header"> + <emit emit_type='prepend'></emit> + </output> + <output filename="grit/chromeos_file_manager_resources_map.cc" + type="resource_file_map_source" /> + <output filename="grit/chromeos_file_manager_resources_map.h" + type="resource_map_header" /> + <output filename="chromeos_file_manager_resources.pak" type="data_package" /> + </outputs> + <release seq="1"> + <includes> + <if expr="is_official_build == false"> + <!-- Privileged app host contents. --> + <include name="IDR_FILE_MANAGER_BROWSER_PROXY_JS" file="browser_proxy.js" type="BINDATA" /> + <include name="IDR_FILE_MANAGER_FILE_MANAGER_HTML" file="file_manager.html" type="BINDATA" /> + <include name="IDR_FILE_MANAGER_FILE_MANAGER_CSS" file="file_manager.css" type="BINDATA" /> + <include name="IDR_FILE_MANAGER_FILE_MANAGER_JS" file="file_manager.js" type="BINDATA" /> + <include name="IDR_FILE_MANAGER_ICON_192" file="icon192.png" type="BINDATA" /> + + <!-- Mojo resources --> + <include name="IDR_FILE_MANAGER_MOJO_LITE_JS" + file="$root_gen_dir\chromeos\components\file_manager\file_manager.mojom-lite.js" + use_base_dir="false" + type="BINDATA" /> + </if> + </includes> + </release> +</grit> +
diff --git a/chromeos/components/file_manager/resources/icon192.png b/chromeos/components/file_manager/resources/icon192.png new file mode 100644 index 0000000..b49fdee --- /dev/null +++ b/chromeos/components/file_manager/resources/icon192.png Binary files differ
diff --git a/chromeos/components/file_manager/url_constants.cc b/chromeos/components/file_manager/url_constants.cc new file mode 100644 index 0000000..c4be8375 --- /dev/null +++ b/chromeos/components/file_manager/url_constants.cc
@@ -0,0 +1,14 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos/components/file_manager/url_constants.h" + +namespace chromeos { +namespace file_manager { + +constexpr char kChromeUIFileManagerHost[] = "file-manager"; +constexpr char kChromeUIFileManagerURL[] = "chrome://file-manager"; + +} // namespace file_manager +} // namespace chromeos
diff --git a/chromeos/components/file_manager/url_constants.h b/chromeos/components/file_manager/url_constants.h new file mode 100644 index 0000000..143d697 --- /dev/null +++ b/chromeos/components/file_manager/url_constants.h
@@ -0,0 +1,17 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMEOS_COMPONENTS_FILE_MANAGER_URL_CONSTANTS_H_ +#define CHROMEOS_COMPONENTS_FILE_MANAGER_URL_CONSTANTS_H_ + +namespace chromeos { +namespace file_manager { + +extern const char kChromeUIFileManagerHost[]; +extern const char kChromeUIFileManagerURL[]; + +} // namespace file_manager +} // namespace chromeos + +#endif // CHROMEOS_COMPONENTS_FILE_MANAGER_URL_CONSTANTS_H_
diff --git a/chromeos/dbus/debug_daemon/debug_daemon_client.cc b/chromeos/dbus/debug_daemon/debug_daemon_client.cc index 4ae7156..878c339 100644 --- a/chromeos/dbus/debug_daemon/debug_daemon_client.cc +++ b/chromeos/dbus/debug_daemon/debug_daemon_client.cc
@@ -531,16 +531,6 @@ std::move(error_callback))); } - void StartConcierge(ConciergeCallback callback) override { - dbus::MethodCall method_call(debugd::kDebugdInterface, - debugd::kStartVmConcierge); - dbus::MessageWriter writer(&method_call); - debugdaemon_proxy_->CallMethod( - &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, - base::BindOnce(&DebugDaemonClientImpl::OnStartConcierge, - weak_ptr_factory_.GetWeakPtr(), std::move(callback))); - } - void StartPluginVmDispatcher(const std::string& owner_id, const std::string& lang, PluginVmDispatcherCallback callback) override { @@ -870,15 +860,6 @@ std::move(error_callback).Run(); } - void OnStartConcierge(ConciergeCallback callback, dbus::Response* response) { - bool result = false; - if (response) { - dbus::MessageReader reader(response); - reader.PopBool(&result); - } - std::move(callback).Run(result); - } - void OnStartPluginVmDispatcher(PluginVmDispatcherCallback callback, dbus::Response* response, dbus::ErrorResponse* error) {
diff --git a/chromeos/dbus/debug_daemon/debug_daemon_client.h b/chromeos/dbus/debug_daemon/debug_daemon_client.h index bed3e4f..d493c10 100644 --- a/chromeos/dbus/debug_daemon/debug_daemon_client.h +++ b/chromeos/dbus/debug_daemon/debug_daemon_client.h
@@ -235,14 +235,6 @@ CupsRemovePrinterCallback callback, base::OnceClosure error_callback) = 0; - // A callback to handle the result of StartConcierge. - using ConciergeCallback = base::OnceCallback<void(bool success)>; - // Calls debugd::kStartVmConcierge, which starts the Concierge service. - // |callback| is called when the method finishes. If the |callback| is called - // with true, it is guaranteed that the service is ready to accept requests. - // It is not necessary for ConciergeClient to use WaitForServiceToBeAvailable. - virtual void StartConcierge(ConciergeCallback callback) = 0; - // A callback to handle the result of // StartPluginVmDispatcher/StopPluginVmDispatcher. using PluginVmDispatcherCallback = base::OnceCallback<void(bool success)>;
diff --git a/chromeos/dbus/debug_daemon/fake_debug_daemon_client.cc b/chromeos/dbus/debug_daemon/fake_debug_daemon_client.cc index a4d66a5e..5bda3a2 100644 --- a/chromeos/dbus/debug_daemon/fake_debug_daemon_client.cc +++ b/chromeos/dbus/debug_daemon/fake_debug_daemon_client.cc
@@ -257,11 +257,6 @@ FROM_HERE, base::BindOnce(std::move(callback), has_printer)); } -void FakeDebugDaemonClient::StartConcierge(ConciergeCallback callback) { - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), true)); -} - void FakeDebugDaemonClient::StartPluginVmDispatcher( const std::string& /* owner_id */, const std::string& /* lang */,
diff --git a/chromeos/dbus/debug_daemon/fake_debug_daemon_client.h b/chromeos/dbus/debug_daemon/fake_debug_daemon_client.h index 798a642a..069b356 100644 --- a/chromeos/dbus/debug_daemon/fake_debug_daemon_client.h +++ b/chromeos/dbus/debug_daemon/fake_debug_daemon_client.h
@@ -88,7 +88,6 @@ void CupsRemovePrinter(const std::string& name, CupsRemovePrinterCallback callback, base::OnceClosure error_callback) override; - void StartConcierge(ConciergeCallback callback) override; void StartPluginVmDispatcher(const std::string& owner_id, const std::string& lang, PluginVmDispatcherCallback callback) override;
diff --git a/chromeos/resources/BUILD.gn b/chromeos/resources/BUILD.gn index 8226d82..ea4e295 100644 --- a/chromeos/resources/BUILD.gn +++ b/chromeos/resources/BUILD.gn
@@ -66,6 +66,29 @@ ] } +# Resources used by chrome://file-manager +grit("file_manager_resources") { + source = "../components/file_manager/resources/file_manager_resources.grd" + + outputs = [ + "grit/chromeos_file_manager_resources.h", + "grit/chromeos_file_manager_resources_map.cc", + "grit/chromeos_file_manager_resources_map.h", + "chromeos_file_manager_resources.pak", + ] + output_dir = "$root_gen_dir/chromeos" + + grit_flags = [ + "-E", + "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir), + ] + + deps = [ + "//chromeos/components/file_manager:file_manager_mojom_js", + "//mojo/public/js:bindings_lite", + ] +} + # Resources used by chrome://help-app, and parts of the sandboxed app it hosts # that do not come from the app bundle (below). grit("help_app_resources") {
diff --git a/components/BUILD.gn b/components/BUILD.gn index 0dcf6da..ebf7e34 100644 --- a/components/BUILD.gn +++ b/components/BUILD.gn
@@ -301,9 +301,10 @@ "//components/webcrypto:unit_tests", ] - if (!is_fuchsia) { + if (!is_fuchsia) { # !iOS and !Fuchsia deps += [ "//components/crash/content/browser:unit_tests", + "//components/crash/content/browser/error_reporting:unit_tests", "//components/crash/core/app:unit_tests", "//components/data_reduction_proxy/core/browser:unit_tests", "//components/data_reduction_proxy/core/common:unit_tests",
diff --git a/components/arc/arc_util.cc b/components/arc/arc_util.cc index 9b62fe38..d831266 100644 --- a/components/arc/arc_util.cc +++ b/components/arc/arc_util.cc
@@ -67,13 +67,7 @@ LOG(ERROR) << "SetVmCpuRestriction for ARCVM failed"; } -void DoSetArcVmCpuRestriction(CpuRestrictionState cpu_restriction_state, - bool concierge_started) { - if (!concierge_started) { - LOG(ERROR) << "Concierge D-Bus service is not available"; - return; - } - +void SetArcVmCpuRestriction(CpuRestrictionState cpu_restriction_state) { auto* client = chromeos::DBusThreadManager::Get()->GetConciergeClient(); if (!client) { LOG(ERROR) << "ConciergeClient is not available"; @@ -97,17 +91,6 @@ base::BindOnce(&OnSetArcVmCpuRestriction)); } -void SetArcVmCpuRestriction(CpuRestrictionState cpu_restriction_state) { - auto* client = chromeos::DBusThreadManager::Get()->GetDebugDaemonClient(); - if (!client) { - LOG(WARNING) << "DebugDaemonClient is not available"; - return; - } - // TODO(wvk): Call StartConcierge() only when the service is not running. - client->StartConcierge( - base::BindOnce(&DoSetArcVmCpuRestriction, cpu_restriction_state)); -} - void SetArcContainerCpuRestriction(CpuRestrictionState cpu_restriction_state) { if (!chromeos::SessionManagerClient::Get()) { LOG(WARNING) << "SessionManagerClient is not available";
diff --git a/components/arc/session/arc_vm_client_adapter.cc b/components/arc/session/arc_vm_client_adapter.cc index d25be35..d112e43 100644 --- a/components/arc/session/arc_vm_client_adapter.cc +++ b/components/arc/session/arc_vm_client_adapter.cc
@@ -527,14 +527,6 @@ weak_factory_.GetWeakPtr(), std::move(callback))); } - void UpgradeArc(UpgradeParams params, - chromeos::VoidDBusMethodCallback callback) override { - VLOG(1) << "Starting Concierge service"; - GetDebugDaemonClient()->StartConcierge(base::BindOnce( - &ArcVmClientAdapter::OnConciergeStarted, weak_factory_.GetWeakPtr(), - std::move(params), std::move(callback))); - } - void StopArcInstance(bool on_shutdown, bool should_backup_log) override { if (on_shutdown) { // Do nothing when |on_shutdown| is true because either vm_concierge.conf @@ -675,14 +667,8 @@ should_notify_observers_ = true; } - void OnConciergeStarted(UpgradeParams params, - chromeos::VoidDBusMethodCallback callback, - bool success) { - if (!success) { - LOG(ERROR) << "Failed to start Concierge service for arcvm"; - std::move(callback).Run(false); - return; - } + void UpgradeArc(UpgradeParams params, + chromeos::VoidDBusMethodCallback callback) override { VLOG(2) << "Checking file system status"; base::ThreadPool::PostTaskAndReplyWithResult( FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
diff --git a/components/arc/session/arc_vm_client_adapter_unittest.cc b/components/arc/session/arc_vm_client_adapter_unittest.cc index 6a469e4..0cc55878 100644 --- a/components/arc/session/arc_vm_client_adapter_unittest.cc +++ b/components/arc/session/arc_vm_client_adapter_unittest.cc
@@ -97,11 +97,6 @@ TestDebugDaemonClient() = default; ~TestDebugDaemonClient() override = default; - void StartConcierge(ConciergeCallback callback) override { - start_concierge_called_ = true; - std::move(callback).Run(start_concierge_result_); - } - void BackupArcBugReport(const std::string& userhash, chromeos::VoidDBusMethodCallback callback) override { backup_arc_bug_report_called_ = true; @@ -115,14 +110,7 @@ backup_arc_bug_report_result_ = result; } - bool start_concierge_called() const { return start_concierge_called_; } - void set_start_concierge_result(bool result) { - start_concierge_result_ = result; - } - private: - bool start_concierge_called_ = false; - bool start_concierge_result_ = true; bool backup_arc_bug_report_called_ = false; bool backup_arc_bug_report_result_ = true; @@ -313,14 +301,6 @@ } protected: - bool GetStartConciergeCalled() { - return GetTestDebugDaemonClient()->start_concierge_called(); - } - - void SetStartConciergeResponse(bool response) { - GetTestDebugDaemonClient()->set_start_concierge_result(response); - } - void SetValidUserInfo() { SetUserInfo(kUserIdHash, kSerialNumber); } void SetUserInfo(const std::string& hash, const std::string& serial) { @@ -755,7 +735,6 @@ InjectUpstartStartJobFailure(kArcVmServerProxyJobName); UpgradeArc(false); - EXPECT_TRUE(GetStartConciergeCalled()); EXPECT_FALSE(GetTestConciergeClient()->start_arc_vm_called()); EXPECT_FALSE(arc_instance_stopped_called()); @@ -781,7 +760,6 @@ // Upgrade should still succeed. UpgradeArc(true); - EXPECT_TRUE(GetStartConciergeCalled()); EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called()); EXPECT_FALSE(arc_instance_stopped_called()); } @@ -796,7 +774,6 @@ EnableAdbOverUsbForTesting(); UpgradeArc(false); - EXPECT_TRUE(GetStartConciergeCalled()); EXPECT_FALSE(GetTestConciergeClient()->start_arc_vm_called()); EXPECT_FALSE(arc_instance_stopped_called()); @@ -821,7 +798,6 @@ InjectUpstartStartJobFailure(kArcCreateDataJobName); UpgradeArc(false); - EXPECT_TRUE(GetStartConciergeCalled()); EXPECT_FALSE(GetTestConciergeClient()->start_arc_vm_called()); EXPECT_FALSE(arc_instance_stopped_called()); @@ -847,7 +823,6 @@ InjectUpstartStartJobFailure(kArcVmMountMyFilesJobName); UpgradeArc(false); - EXPECT_TRUE(GetStartConciergeCalled()); EXPECT_FALSE(GetTestConciergeClient()->start_arc_vm_called()); EXPECT_FALSE(arc_instance_stopped_called()); @@ -874,30 +849,6 @@ InjectUpstartStartJobFailure(kArcVmMountRemovableMediaJobName); UpgradeArc(false); - EXPECT_TRUE(GetStartConciergeCalled()); - EXPECT_FALSE(GetTestConciergeClient()->start_arc_vm_called()); - EXPECT_FALSE(arc_instance_stopped_called()); - - // Try to stop the VM. StopVm will fail in this case because - // no VM is running. - vm_tools::concierge::StopVmResponse response; - response.set_success(false); - GetTestConciergeClient()->set_stop_vm_response(response); - adapter()->StopArcInstance(/*on_shutdown=*/false, - /*should_backup_log=*/false); - run_loop()->Run(); - EXPECT_TRUE(GetTestConciergeClient()->stop_vm_called()); - EXPECT_TRUE(arc_instance_stopped_called()); -} - -// Tests that UpgradeArc() handles StartConcierge() failures properly. -TEST_F(ArcVmClientAdapterTest, UpgradeArc_StartConciergeFailure) { - SetValidUserInfo(); - StartMiniArc(); - // Inject failure to StartConcierge(). - SetStartConciergeResponse(false); - UpgradeArc(false); - EXPECT_TRUE(GetStartConciergeCalled()); EXPECT_FALSE(GetTestConciergeClient()->start_arc_vm_called()); EXPECT_FALSE(arc_instance_stopped_called()); @@ -921,7 +872,6 @@ StartMiniArc(); UpgradeArc(false); - EXPECT_TRUE(GetStartConciergeCalled()); EXPECT_FALSE(GetTestConciergeClient()->start_arc_vm_called()); EXPECT_FALSE(arc_instance_stopped_called()); @@ -945,7 +895,6 @@ StartMiniArc(); UpgradeArc(false); - EXPECT_TRUE(GetStartConciergeCalled()); EXPECT_FALSE(GetTestConciergeClient()->start_arc_vm_called()); EXPECT_FALSE(arc_instance_stopped_called()); @@ -971,7 +920,6 @@ GetTestConciergeClient()->set_start_vm_response(start_vm_response); UpgradeArc(false); - EXPECT_TRUE(GetStartConciergeCalled()); EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called()); EXPECT_FALSE(arc_instance_stopped_called()); @@ -994,7 +942,6 @@ GetTestConciergeClient()->set_start_vm_response(base::nullopt); UpgradeArc(false); - EXPECT_TRUE(GetStartConciergeCalled()); EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called()); EXPECT_FALSE(arc_instance_stopped_called()); @@ -1015,7 +962,6 @@ SetValidUserInfo(); StartMiniArc(); UpgradeArc(true); - EXPECT_TRUE(GetStartConciergeCalled()); EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called()); EXPECT_FALSE(arc_instance_stopped_called()); @@ -1040,7 +986,6 @@ UpgradeParams params(GetPopulatedUpgradeParams()); UpgradeArcWithParams(true, std::move(params)); - EXPECT_TRUE(GetStartConciergeCalled()); EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called()); EXPECT_FALSE(arc_instance_stopped_called()); } @@ -1064,7 +1009,6 @@ params.preferred_languages = {"en_US"}; UpgradeArcWithParams(true, std::move(params)); - EXPECT_TRUE(GetStartConciergeCalled()); EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called()); EXPECT_FALSE(arc_instance_stopped_called()); } @@ -1084,7 +1028,6 @@ params.demo_session_apps_path = base::FilePath(kDemoImage); UpgradeArcWithParams(true, std::move(params)); - EXPECT_TRUE(GetStartConciergeCalled()); EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called()); EXPECT_FALSE(arc_instance_stopped_called()); @@ -1108,7 +1051,6 @@ StartMiniArcWithParams(true, std::move(start_params)); UpgradeParams params(GetPopulatedUpgradeParams()); UpgradeArcWithParams(true, std::move(params)); - EXPECT_TRUE(GetStartConciergeCalled()); EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called()); EXPECT_FALSE(arc_instance_stopped_called()); EXPECT_TRUE( @@ -1141,7 +1083,6 @@ SetValidUserInfo(); StartMiniArc(); UpgradeArc(true); - EXPECT_TRUE(GetStartConciergeCalled()); EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called()); EXPECT_FALSE(arc_instance_stopped_called()); @@ -1156,7 +1097,6 @@ SetValidUserInfo(); StartMiniArc(); UpgradeArc(true); - EXPECT_TRUE(GetStartConciergeCalled()); EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called()); EXPECT_FALSE(arc_instance_stopped_called()); @@ -1171,7 +1111,6 @@ SetValidUserInfo(); StartMiniArc(); UpgradeArc(true); - EXPECT_TRUE(GetStartConciergeCalled()); EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called()); EXPECT_FALSE(arc_instance_stopped_called()); @@ -1194,7 +1133,6 @@ SetValidUserInfo(); StartMiniArc(); UpgradeArc(true); - EXPECT_TRUE(GetStartConciergeCalled()); EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called()); EXPECT_FALSE(arc_instance_stopped_called());
diff --git a/components/autofill/core/browser/autofill_download_manager.cc b/components/autofill/core/browser/autofill_download_manager.cc index b13a360..d50a485 100644 --- a/components/autofill/core/browser/autofill_download_manager.cc +++ b/components/autofill/core/browser/autofill_download_manager.cc
@@ -1062,7 +1062,8 @@ delete active_experiments_; active_experiments_ = new std::vector<variations::VariationID>( variations_ids_provider->GetVariationsVector( - variations::GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT)); + {variations::GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT, + variations::GOOGLE_WEB_PROPERTIES_TRIGGER_FIRST_PARTY})); base::EraseIf(*active_experiments_, [](variations::VariationID id) { return !IsAutofillExperimentId(id); });
diff --git a/components/autofill/core/browser/autofill_manager_unittest.cc b/components/autofill/core/browser/autofill_manager_unittest.cc index 6a29dfd..748e5d2 100644 --- a/components/autofill/core/browser/autofill_manager_unittest.cc +++ b/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -112,17 +112,15 @@ ON_CALL(*this, GetChannel()) .WillByDefault(Return(version_info::Channel::UNKNOWN)); } - - ~MockAutofillClient() override {} + MockAutofillClient(const MockAutofillClient&) = delete; + MockAutofillClient& operator=(const MockAutofillClient&) = delete; + ~MockAutofillClient() override = default; MOCK_METHOD0(ShouldShowSigninPromo, bool()); MOCK_CONST_METHOD0(GetChannel, version_info::Channel()); MOCK_METHOD2(ConfirmSaveUpiIdLocally, void(const std::string& upi_id, base::OnceCallback<void(bool user_decision)> callback)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockAutofillClient); }; class MockAutofillDownloadManager : public TestAutofillDownloadManager { @@ -130,6 +128,9 @@ MockAutofillDownloadManager(AutofillDriver* driver, AutofillDownloadManager::Observer* observer) : TestAutofillDownloadManager(driver, observer) {} + MockAutofillDownloadManager(const MockAutofillDownloadManager&) = delete; + MockAutofillDownloadManager& operator=(const MockAutofillDownloadManager&) = + delete; MOCK_METHOD6(StartUploadRequest, bool(const FormStructure&, @@ -138,9 +139,6 @@ const std::string&, bool, PrefService*)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockAutofillDownloadManager); }; void ExpectFilledField(const char* expected_label, @@ -305,7 +303,9 @@ class MockAutofillDriver : public TestAutofillDriver { public: - MockAutofillDriver() {} + MockAutofillDriver() = default; + MockAutofillDriver(const MockAutofillDriver&) = delete; + MockAutofillDriver& operator=(const MockAutofillDriver&) = delete; // Mock methods to enable testability. MOCK_METHOD3(SendFormDataToRenderer, @@ -315,16 +315,13 @@ MOCK_METHOD1(SendAutofillTypePredictionsToRenderer, void(const std::vector<FormStructure*>& forms)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockAutofillDriver); }; } // namespace class AutofillManagerTest : public testing::Test { public: - AutofillManagerTest() {} + AutofillManagerTest() = default; void SetUp() override { autofill_client_.SetPrefs(test::PrefServiceForTesting()); @@ -5575,10 +5572,9 @@ : public AutofillManagerTest, public ::testing::WithParamInterface< std::tuple<ProfileMatchingTypesTestCase, - int, // AutofillDataModel::ValidityState - bool, // AutofillDataModel::ValidationSource - bool>> // kAutofillEnableSupportForMoreStructureInNames -{ + int, // AutofillDataModel::ValidityState + bool, // AutofillDataModel::ValidationSource + bool>> { // kAutofillEnableSupportForMoreStructureInNames protected: void SetUp() override { AutofillManagerTest::SetUp(); @@ -5763,7 +5759,7 @@ for (auto type : expected_possible_types) { if (GroupTypeOfServerFieldType(type) != CREDIT_CARD) { for (auto& profile : profiles) { - ASSERT_TRUE(test_case.field_types.size() > 0); + ASSERT_GT(test_case.field_types.size(), 0U); if (type == UNKNOWN_TYPE) { // An UNKNOWN type is always UNVALIDATED validity_state = AutofillDataModel::UNVALIDATED; @@ -6154,9 +6150,8 @@ (possible_types.count(NAME_LAST_SECOND) || possible_types.count(NAME_LAST_FIRST) || possible_types.count(NAME_FULL))); - } - // Or even all three. - else if (StructuredNames() && possible_types.size() == 3) { + } else if (StructuredNames() && possible_types.size() == 3) { + // Or even all three. EXPECT_TRUE(possible_types.count(NAME_FULL) && possible_types.count(NAME_LAST) && (possible_types.count(NAME_LAST_SECOND) ||
diff --git a/components/autofill/core/browser/autofill_test_utils.cc b/components/autofill/core/browser/autofill_test_utils.cc index 59461e39..67cdd64 100644 --- a/components/autofill/core/browser/autofill_test_utils.cc +++ b/components/autofill/core/browser/autofill_test_utils.cc
@@ -487,7 +487,6 @@ "2109" /* Mastercard */, NextMonth().c_str(), NextYear().c_str(), "1"); credit_card.SetNetworkForMaskedCard(kMasterCard); - credit_card.set_instrument_id(1); return credit_card; } @@ -708,7 +707,6 @@ card.set_record_type(CreditCard::MASKED_SERVER_CARD); card.SetNumber(card.LastFourDigits()); card.SetNetworkForMaskedCard(card.network()); - card.set_instrument_id(card.instrument_id()); } table->SetServerCreditCards(as_masked_cards);
diff --git a/components/autofill/core/browser/personal_data_manager.cc b/components/autofill/core/browser/personal_data_manager.cc index f8c3ba0..5ffd0f6 100644 --- a/components/autofill/core/browser/personal_data_manager.cc +++ b/components/autofill/core/browser/personal_data_manager.cc
@@ -404,7 +404,8 @@ DCHECK(pending_profiles_query_ || pending_server_profiles_query_ || pending_creditcards_query_ || pending_server_creditcards_query_ || pending_server_creditcard_cloud_token_data_query_ || - pending_customer_data_query_ || pending_upi_ids_query_); + pending_customer_data_query_ || pending_upi_ids_query_ || + pending_offer_data_query_); if (!result) { // Error from the web database. @@ -422,6 +423,8 @@ pending_customer_data_query_ = 0; else if (h == pending_upi_ids_query_) pending_upi_ids_query_ = 0; + else if (h == pending_offer_data_query_) + pending_offer_data_query_ = 0; } else { switch (result->GetType()) { case AUTOFILL_PROFILES_RESULT: @@ -474,6 +477,12 @@ static_cast<WDResult<std::vector<std::string>>*>(result.get()) ->GetValue(); break; + case AUTOFILL_OFFER_DATA: + DCHECK_EQ(h, pending_offer_data_query_) + << "received autofill offer data from invalid request."; + ReceiveLoadedDbValues(h, result.get(), &pending_offer_data_query_, + &autofill_offer_data_); + break; default: NOTREACHED(); } @@ -911,6 +920,7 @@ server_profiles_.clear(); payments_customer_data_.reset(); server_credit_card_cloud_token_data_.clear(); + autofill_offer_data_.clear(); } void PersonalDataManager::ClearAllLocalData() { @@ -1151,12 +1161,25 @@ return result; } +std::vector<AutofillOfferData*> PersonalDataManager::GetCreditCardOffers() + const { + if (!IsAutofillWalletImportEnabled()) + return {}; + + std::vector<AutofillOfferData*> result; + result.reserve(autofill_offer_data_.size()); + for (const auto& data : autofill_offer_data_) + result.push_back(data.get()); + return result; +} + void PersonalDataManager::Refresh() { LoadProfiles(); LoadCreditCards(); LoadCreditCardCloudTokenData(); LoadPaymentsCustomerData(); LoadUpiIds(); + LoadCreditCardOffers(); } std::vector<AutofillProfile*> PersonalDataManager::GetProfilesToSuggest() @@ -1699,6 +1722,16 @@ database_helper_->GetLocalDatabase()->GetAllUpiIds(this); } +void PersonalDataManager::LoadCreditCardOffers() { + if (!database_helper_->GetServerDatabase()) + return; + + CancelPendingServerQuery(&pending_offer_data_query_); + + pending_offer_data_query_ = + database_helper_->GetServerDatabase()->GetCreditCardOffers(this); +} + void PersonalDataManager::CancelPendingLocalQuery( WebDataServiceBase::Handle* handle) { if (*handle) { @@ -1728,6 +1761,7 @@ CancelPendingServerQuery(&pending_server_creditcards_query_); CancelPendingServerQuery(&pending_customer_data_query_); CancelPendingServerQuery(&pending_server_creditcard_cloud_token_data_query_); + CancelPendingServerQuery(&pending_offer_data_query_); } bool PersonalDataManager::HasPendingQueriesForTesting() { @@ -2591,7 +2625,8 @@ pending_server_profiles_query_ != 0 || pending_server_creditcards_query_ != 0 || pending_server_creditcard_cloud_token_data_query_ != 0 || - pending_customer_data_query_ != 0 || pending_upi_ids_query_ != 0; + pending_customer_data_query_ != 0 || pending_upi_ids_query_ != 0 || + pending_offer_data_query_ != 0; } void PersonalDataManager::MigrateUserOptedInWalletSyncTransportIfNeeded() {
diff --git a/components/autofill/core/browser/personal_data_manager.h b/components/autofill/core/browser/personal_data_manager.h index 42d68aa..9317043 100644 --- a/components/autofill/core/browser/personal_data_manager.h +++ b/components/autofill/core/browser/personal_data_manager.h
@@ -20,6 +20,7 @@ #include "base/strings/string16.h" #include "build/build_config.h" #include "components/autofill/core/browser/autofill_profile_validator.h" +#include "components/autofill/core/browser/data_model/autofill_offer_data.h" #include "components/autofill/core/browser/data_model/autofill_profile.h" #include "components/autofill/core/browser/data_model/credit_card.h" #include "components/autofill/core/browser/data_model/credit_card_cloud_token_data.h" @@ -261,6 +262,9 @@ virtual std::vector<CreditCardCloudTokenData*> GetCreditCardCloudTokenData() const; + // Returns the credit card offer data. + virtual std::vector<AutofillOfferData*> GetCreditCardOffers() const; + // Updates the validity states of |profiles| according to server validity map. void UpdateProfilesServerValidityMapsIfNeeded( const std::vector<AutofillProfile*>& profiles); @@ -541,6 +545,9 @@ // Loads the saved UPI IDs from the web database. virtual void LoadUpiIds(); + // Loads the offer data from the web database. + virtual void LoadCreditCardOffers(); + // Cancels a pending query to the local web database. |handle| is a pointer // to the query handle. void CancelPendingLocalQuery(WebDataServiceBase::Handle* handle); @@ -606,6 +613,9 @@ std::vector<std::unique_ptr<CreditCardCloudTokenData>> server_credit_card_cloud_token_data_; + // Offer data for user's credit cards. + std::vector<std::unique_ptr<AutofillOfferData>> autofill_offer_data_; + // When the manager makes a request from WebDataServiceBase, the database // is queried on another sequence, we record the query handle until we // get called back. We store handles for both profile and credit card queries @@ -618,6 +628,7 @@ 0; WebDataServiceBase::Handle pending_customer_data_query_ = 0; WebDataServiceBase::Handle pending_upi_ids_query_ = 0; + WebDataServiceBase::Handle pending_offer_data_query_ = 0; // The observers. base::ObserverList<PersonalDataManagerObserver>::Unchecked observers_;
diff --git a/components/autofill/core/browser/webdata/autofill_sync_bridge_util.cc b/components/autofill/core/browser/webdata/autofill_sync_bridge_util.cc index 48dc9b3..badd7f1 100644 --- a/components/autofill/core/browser/webdata/autofill_sync_bridge_util.cc +++ b/components/autofill/core/browser/webdata/autofill_sync_bridge_util.cc
@@ -103,7 +103,6 @@ static_cast<CreditCard::Issuer>(card.card_issuer().issuer())); if (!card.nickname().empty()) result.SetNickname(base::UTF8ToUTF16(card.nickname())); - result.set_instrument_id(card.instrument_id()); return result; } @@ -248,7 +247,6 @@ wallet_card->set_nickname(base::UTF16ToUTF8(card.nickname())); wallet_card->mutable_card_issuer()->set_issuer( static_cast<sync_pb::CardIssuer::Issuer>(card.card_issuer())); - wallet_card->set_instrument_id(card.instrument_id()); } void SetAutofillWalletSpecificsFromPaymentsCustomerData(
diff --git a/components/autofill/core/browser/webdata/autofill_table.cc b/components/autofill/core/browser/webdata/autofill_table.cc index 0e069ec..10e5914 100644 --- a/components/autofill/core/browser/webdata/autofill_table.cc +++ b/components/autofill/core/browser/webdata/autofill_table.cc
@@ -25,6 +25,7 @@ #include "base/time/time.h" #include "components/autofill/core/browser/autofill_type.h" #include "components/autofill/core/browser/data_model/autofill_metadata.h" +#include "components/autofill/core/browser/data_model/autofill_offer_data.h" #include "components/autofill/core/browser/data_model/autofill_profile.h" #include "components/autofill/core/browser/data_model/credit_card.h" #include "components/autofill/core/browser/data_model/credit_card_cloud_token_data.h" @@ -590,7 +591,8 @@ InitServerAddressesTable() && InitServerAddressMetadataTable() && InitAutofillSyncMetadataTable() && InitModelTypeStateTable() && InitPaymentsCustomerDataTable() && InitPaymentsUPIVPATable() && - InitServerCreditCardCloudTokenDataTable()); + InitServerCreditCardCloudTokenDataTable() && InitOfferDataTable() && + InitOfferEligibleInstrumentTable() && InitOfferMerchantDomainTable()); } bool AutofillTable::IsSyncable() { @@ -1432,8 +1434,7 @@ "metadata.billing_address_id," // 10 "bank_name," // 11 "nickname," // 12 - "card_issuer," // 13 - "instrument_id " // 14 + "card_issuer " // 13 "FROM masked_credit_cards masked " "LEFT OUTER JOIN unmasked_credit_cards USING (id) " "LEFT OUTER JOIN server_card_metadata metadata USING (id)")); @@ -1479,7 +1480,6 @@ card->SetNickname(s.ColumnString16(index++)); card->set_card_issuer( static_cast<CreditCard::Issuer>(s.ColumnInt(index++))); - card->set_instrument_id(s.ColumnInt64(index++)); credit_cards->push_back(std::move(card)); } return s.Succeeded(); @@ -1730,18 +1730,17 @@ // Add all the masked cards. sql::Statement masked_insert( db_->GetUniqueStatement("INSERT INTO masked_credit_cards(" - "id," // 0 - "network," // 1 - "status," // 2 - "name_on_card," // 3 - "last_four," // 4 - "exp_month," // 5 - "exp_year," // 6 - "bank_name," // 7 - "nickname," // 8 - "card_issuer," // 9 - "instrument_id)" // 10 - "VALUES (?,?,?,?,?,?,?,?,?,?,?)")); + "id," // 0 + "network," // 1 + "status," // 2 + "name_on_card," // 3 + "last_four," // 4 + "exp_month," // 5 + "exp_year," // 6 + "bank_name," // 7 + "nickname," // 8 + "card_issuer)" // 9 + "VALUES (?,?,?,?,?,?,?,?,?,?)")); int index; for (const CreditCard& card : credit_cards) { DCHECK_EQ(CreditCard::MASKED_SERVER_CARD, card.record_type()); @@ -1758,7 +1757,6 @@ masked_insert.BindString(index++, card.bank_name()); masked_insert.BindString16(index++, card.nickname()); masked_insert.BindInt(index++, static_cast<int>(card.card_issuer())); - masked_insert.BindInt(index++, card.instrument_id()); masked_insert.Run(); masked_insert.Reset(true); } @@ -1926,6 +1924,127 @@ return s.Succeeded(); } +void AutofillTable::SetCreditCardOffers( + const std::vector<AutofillOfferData>& autofill_offer_data) { + sql::Transaction transaction(db_); + if (!transaction.Begin()) + return; + + // Delete all old values. + sql::Statement delete_offers( + db_->GetUniqueStatement("DELETE FROM offer_data")); + sql::Statement delete_offer_eligible_instruments( + db_->GetUniqueStatement("DELETE FROM offer_eligible_instrument")); + sql::Statement delete_offer_merchant_domains( + db_->GetUniqueStatement("DELETE FROM offer_merchant_domain")); + delete_offers.Run(); + delete_offer_eligible_instruments.Run(); + delete_offer_merchant_domains.Run(); + + // Insert new values. + sql::Statement insert_offers( + db_->GetUniqueStatement("INSERT INTO offer_data(" + "offer_id, " // 0 + "offer_reward_amount, " // 1 + "expiry, " // 2 + "offer_details_url) " // 3 + "VALUES (?,?,?,?)")); + + for (const AutofillOfferData& data : autofill_offer_data) { + insert_offers.BindInt64(0, data.offer_id); + insert_offers.BindString(1, data.offer_reward_amount); + insert_offers.BindInt64( + 2, data.expiry.ToDeltaSinceWindowsEpoch().InMilliseconds()); + insert_offers.BindString(3, data.offer_details_url.spec()); + insert_offers.Run(); + insert_offers.Reset(true); + + for (const int64_t instrument_id : data.eligible_instrument_id) { + // Insert new offer_eligible_instrument values. + sql::Statement insert_offer_eligible_instruments( + db_->GetUniqueStatement("INSERT INTO offer_eligible_instrument(" + "offer_id, " // 0 + "instrument_id) " // 1 + "VALUES (?,?)")); + insert_offer_eligible_instruments.BindInt64(0, data.offer_id); + insert_offer_eligible_instruments.BindInt64(1, instrument_id); + insert_offer_eligible_instruments.Run(); + insert_offer_eligible_instruments.Reset(true); + } + + for (const GURL& merchant_domain : data.merchant_domain) { + // Insert new offer_merchant_domain values. + sql::Statement insert_offer_merchant_domains( + db_->GetUniqueStatement("INSERT INTO offer_merchant_domain(" + "offer_id, " // 0 + "merchant_domain) " // 1 + "VALUES (?,?)")); + insert_offer_merchant_domains.BindInt64(0, data.offer_id); + insert_offer_merchant_domains.BindString(1, merchant_domain.spec()); + insert_offer_merchant_domains.Run(); + insert_offer_merchant_domains.Reset(true); + } + } + transaction.Commit(); +} + +bool AutofillTable::GetCreditCardOffers( + std::vector<std::unique_ptr<AutofillOfferData>>* autofill_offer_data) { + autofill_offer_data->clear(); + + sql::Statement s( + db_->GetUniqueStatement("SELECT " + "offer_id, " // 0 + "offer_reward_amount, " // 1 + "expiry, " // 2 + "offer_details_url " // 3 + "FROM offer_data")); + + while (s.Step()) { + int index = 0; + std::unique_ptr<AutofillOfferData> data = + std::make_unique<AutofillOfferData>(); + data->offer_id = s.ColumnInt64(index++); + data->offer_reward_amount = s.ColumnString(index++); + data->expiry = base::Time::FromDeltaSinceWindowsEpoch( + base::TimeDelta::FromMilliseconds(s.ColumnInt64(index++))); + data->offer_details_url = GURL(s.ColumnString(index++)); + + sql::Statement s_offer_eligible_instrument( + db_->GetUniqueStatement("SELECT " + "offer_id, " // 0 + "instrument_id " // 1 + "FROM offer_eligible_instrument " + "WHERE offer_id = ?")); + s_offer_eligible_instrument.BindInt64(0, data->offer_id); + while (s_offer_eligible_instrument.Step()) { + const int64_t instrument_id = s_offer_eligible_instrument.ColumnInt64(1); + if (instrument_id != 0) { + data->eligible_instrument_id.push_back(instrument_id); + } + } + + sql::Statement s_offer_merchant_domain( + db_->GetUniqueStatement("SELECT " + "offer_id, " // 0 + "merchant_domain " // 1 + "FROM offer_merchant_domain " + "WHERE offer_id = ?")); + s_offer_merchant_domain.BindInt64(0, data->offer_id); + while (s_offer_merchant_domain.Step()) { + const std::string merchant_domain = + s_offer_merchant_domain.ColumnString(1); + if (!merchant_domain.empty()) { + data->merchant_domain.emplace_back(GURL(merchant_domain)); + } + } + + autofill_offer_data->emplace_back(std::move(data)); + } + + return s.Succeeded(); +} + bool AutofillTable::InsertUpiId(const std::string& upi_id) { sql::Transaction transaction(db_); if (!transaction.Begin()) @@ -1992,6 +2111,21 @@ cloud_token_data.Run(); changed |= db_->GetLastChangeCount() > 0; + sql::Statement autofill_offer_data( + db_->GetUniqueStatement("DELETE FROM offer_data")); + autofill_offer_data.Run(); + changed |= db_->GetLastChangeCount() > 0; + + sql::Statement autofill_offer_eligible_instrument( + db_->GetUniqueStatement("DELETE FROM offer_eligible_instrument")); + autofill_offer_eligible_instrument.Run(); + changed |= db_->GetLastChangeCount() > 0; + + sql::Statement autofill_offer_merchant_domain( + db_->GetUniqueStatement("DELETE FROM offer_merchant_domain")); + autofill_offer_merchant_domain.Run(); + changed |= db_->GetLastChangeCount() > 0; + transaction.Commit(); return changed; } @@ -3244,18 +3378,17 @@ DCHECK_GT(db_->transaction_nesting(), 0); sql::Statement masked_insert( db_->GetUniqueStatement("INSERT INTO masked_credit_cards(" - "id," // 0 - "network," // 1 - "status," // 2 - "name_on_card," // 3 - "last_four," // 4 - "exp_month," // 5 - "exp_year," // 6 - "bank_name," // 7 - "nickname," // 8 - "card_issuer," // 9 - "instrument_id)" // 10 - "VALUES (?,?,?,?,?,?,?,?,?,?,?)")); + "id," // 0 + "network," // 1 + "status," // 2 + "name_on_card," // 3 + "last_four," // 4 + "exp_month," // 5 + "exp_year," // 6 + "bank_name," // 7 + "nickname," // 8 + "card_issuer)" // 9 + "VALUES (?,?,?,?,?,?,?,?,?,?)")); int index; for (const CreditCard& card : credit_cards) { DCHECK_EQ(CreditCard::MASKED_SERVER_CARD, card.record_type()); @@ -3272,7 +3405,6 @@ masked_insert.BindString(index++, card.bank_name()); masked_insert.BindString16(index++, card.nickname()); masked_insert.BindInt(index++, static_cast<int>(card.card_issuer())); - masked_insert.BindInt(index++, card.instrument_id()); masked_insert.Run(); masked_insert.Reset(true); @@ -3624,4 +3756,43 @@ return true; } +bool AutofillTable::InitOfferDataTable() { + if (!db_->DoesTableExist("offer_data")) { + if (!db_->Execute("CREATE TABLE offer_data ( " + "offer_id UNSIGNED LONG, " + "offer_reward_amount VARCHAR, " + "expiry UNSIGNED LONG, " + "offer_details_url VARCHAR, " + "merchant_domain VARCHAR)")) { + NOTREACHED(); + return false; + } + } + return true; +} + +bool AutofillTable::InitOfferEligibleInstrumentTable() { + if (!db_->DoesTableExist("offer_eligible_instrument")) { + if (!db_->Execute("CREATE TABLE offer_eligible_instrument ( " + "offer_id UNSIGNED LONG," + "instrument_id UNSIGNED LONG)")) { + NOTREACHED(); + return false; + } + } + return true; +} + +bool AutofillTable::InitOfferMerchantDomainTable() { + if (!db_->DoesTableExist("offer_merchant_domain")) { + if (!db_->Execute("CREATE TABLE offer_merchant_domain ( " + "offer_id UNSIGNED LONG," + "merchant_domain VARCHAR)")) { + NOTREACHED(); + return false; + } + } + return true; +} + } // namespace autofill
diff --git a/components/autofill/core/browser/webdata/autofill_table.h b/components/autofill/core/browser/webdata/autofill_table.h index 3b62eb2..51ae7ecd 100644 --- a/components/autofill/core/browser/webdata/autofill_table.h +++ b/components/autofill/core/browser/webdata/autofill_table.h
@@ -31,6 +31,7 @@ class AutofillChange; class AutofillEntry; struct AutofillMetadata; +struct AutofillOfferData; class AutofillProfile; class AutofillTableEncryptor; class AutofillTableTest; @@ -352,6 +353,36 @@ // https://en.wikipedia.org/wiki/Unified_Payments_Interface // // vpa_id A string representing the UPI ID (a.k.a. VPA) value. +// +// offer_data The data for credit card offers which will be presented +// in payments autofill flows. +// +// offer_id The unique server ID for this offer data. +// offer_reward_amount +// The string including the reward details of the offer. +// Could be either percentage cashback (XXX%) or fixed +// amount cashback (XXX$). +// expiry The timestamp when the offer will go expired. Expired +// offers will not be shown in the frontend. +// offer_details_url The link leading to the offer details page on Gpay app. +// +// offer_eligible_instrument +// Contains the mapping of credit cards and card linked +// offers. +// +// offer_id Int 64 to identify the relevant offer. Matches the +// offer_id in the offer_data table. +// instrument_id The new form of instrument id of the card. Will not be +// used for now. +// +// offer_merchant_domain +// Contains the mapping of merchant domains and card linked +// offers. +// +// offer_id Int 64 to identify the relevant offer. Matches the +// offer_id in the offer_data table. +// merchant_domain List of domain names for merchant websites on which +// this offer would apply. class AutofillTable : public WebDatabaseTable, public syncer::SyncMetadataStore { @@ -520,6 +551,13 @@ bool GetPaymentsCustomerData( std::unique_ptr<PaymentsCustomerData>* customer_data) const; + // |autofill_offer_data| must include all existing offers, since table will + // be completely overwritten. + void SetCreditCardOffers( + const std::vector<AutofillOfferData>& autofill_offer_data); + bool GetCreditCardOffers( + std::vector<std::unique_ptr<AutofillOfferData>>* autofill_offer_data); + // Adds |upi_id| to the saved UPI IDs. bool InsertUpiId(const std::string& upi_id); @@ -728,6 +766,9 @@ bool InitPaymentsCustomerDataTable(); bool InitPaymentsUPIVPATable(); bool InitServerCreditCardCloudTokenDataTable(); + bool InitOfferDataTable(); + bool InitOfferEligibleInstrumentTable(); + bool InitOfferMerchantDomainTable(); std::unique_ptr<AutofillTableEncryptor> autofill_table_encryptor_;
diff --git a/components/autofill/core/browser/webdata/autofill_table_unittest.cc b/components/autofill/core/browser/webdata/autofill_table_unittest.cc index e8d7597c..a0df43ad 100644 --- a/components/autofill/core/browser/webdata/autofill_table_unittest.cc +++ b/components/autofill/core/browser/webdata/autofill_table_unittest.cc
@@ -24,6 +24,7 @@ #include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/browser/autofill_type.h" #include "components/autofill/core/browser/data_model/autofill_metadata.h" +#include "components/autofill/core/browser/data_model/autofill_offer_data.h" #include "components/autofill/core/browser/data_model/autofill_profile.h" #include "components/autofill/core/browser/data_model/credit_card.h" #include "components/autofill/core/browser/data_model/credit_card_cloud_token_data.h" @@ -138,8 +139,10 @@ class AutofillTableTest : public testing::Test { public: - AutofillTableTest() {} - ~AutofillTableTest() override {} + AutofillTableTest() = default; + AutofillTableTest(const AutofillTableTest&) = delete; + AutofillTableTest& operator=(const AutofillTableTest&) = delete; + ~AutofillTableTest() override = default; protected: void SetUp() override { @@ -160,9 +163,6 @@ std::unique_ptr<AutofillTable> table_; std::unique_ptr<WebDatabase> db_; base::test::ScopedFeatureList scoped_feature_list_; - - private: - DISALLOW_COPY_AND_ASSIGN(AutofillTableTest); }; TEST_F(AutofillTableTest, Autofill) { @@ -2447,7 +2447,6 @@ inputs[0].SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("1")); inputs[0].SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2020")); inputs[0].SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111111111111111")); - inputs[0].set_instrument_id(321); inputs.push_back(CreditCard(CreditCard::MASKED_SERVER_CARD, "b456")); inputs[1].SetRawInfo(CREDIT_CARD_NAME_FULL, ASCIIToUTF16("Rick Roman")); @@ -2459,7 +2458,6 @@ base::string16 nickname = ASCIIToUTF16("Grocery card"); inputs[1].SetNickname(nickname); inputs[1].set_card_issuer(CreditCard::Issuer::GOOGLE); - inputs[1].set_instrument_id(123); test::SetServerCreditCards(table_.get(), inputs); @@ -2490,9 +2488,6 @@ EXPECT_EQ(CreditCard::Issuer::ISSUER_UNKNOWN, outputs[0]->card_issuer()); EXPECT_EQ(CreditCard::Issuer::GOOGLE, outputs[1]->card_issuer()); - - EXPECT_EQ(321, outputs[0]->instrument_id()); - EXPECT_EQ(123, outputs[1]->instrument_id()); } TEST_F(AutofillTableTest, SetGetRemoveServerCardMetadata) { @@ -2702,7 +2697,6 @@ inputs[0].SetNetworkForMaskedCard(kVisaCard); inputs[0].SetServerStatus(CreditCard::EXPIRED); inputs[0].SetNickname(ASCIIToUTF16("Grocery card")); - inputs[0].set_instrument_id(1); table_->SetServerCardsData(inputs); // Make sure the card was added correctly. @@ -3236,8 +3230,10 @@ class GetFormValuesTest : public testing::TestWithParam<GetFormValuesTestCase> { public: - GetFormValuesTest() {} - ~GetFormValuesTest() override {} + GetFormValuesTest() = default; + GetFormValuesTest(const GetFormValuesTest&) = delete; + GetFormValuesTest& operator=(const GetFormValuesTest&) = delete; + ~GetFormValuesTest() override = default; protected: void SetUp() override { @@ -3257,9 +3253,6 @@ base::ScopedTempDir temp_dir_; std::unique_ptr<AutofillTable> table_; std::unique_ptr<WebDatabase> db_; - - private: - DISALLOW_COPY_AND_ASSIGN(GetFormValuesTest); }; TEST_P(GetFormValuesTest, GetFormValuesForElementName_SubstringMatchEnabled) { @@ -3336,11 +3329,11 @@ : public AutofillTableTest, public testing::WithParamInterface<syncer::ModelType> { public: - AutofillTableTestPerModelType() {} - ~AutofillTableTestPerModelType() override {} - - private: - DISALLOW_COPY_AND_ASSIGN(AutofillTableTestPerModelType); + AutofillTableTestPerModelType() = default; + AutofillTableTestPerModelType(const AutofillTableTestPerModelType&) = delete; + AutofillTableTestPerModelType& operator=( + const AutofillTableTestPerModelType&) = delete; + ~AutofillTableTestPerModelType() override = default; }; TEST_P(AutofillTableTestPerModelType, AutofillNoMetadata) { @@ -3620,4 +3613,101 @@ ASSERT_THAT(upi_ids, UnorderedElementsAre(upi_id1, upi_id2)); } +TEST_F(AutofillTableTest, SetAndGetCreditCardOfferData) { + // Create test data. + AutofillOfferData credit_card_offer_1; + AutofillOfferData credit_card_offer_2; + AutofillOfferData credit_card_offer_3; + + // Set Offer ID. + credit_card_offer_1.offer_id = 1; + credit_card_offer_2.offer_id = 2; + credit_card_offer_3.offer_id = 3; + + // Set reward amounts. + credit_card_offer_1.offer_reward_amount = "$5"; + credit_card_offer_2.offer_reward_amount = "10%"; + credit_card_offer_3.offer_reward_amount = "5%"; + + // Set expiry. + credit_card_offer_1.expiry = base::Time::FromDoubleT(1000); + credit_card_offer_2.expiry = base::Time::FromDoubleT(2000); + credit_card_offer_3.expiry = base::Time::FromDoubleT(3000); + + // Set details URL. + credit_card_offer_1.offer_details_url = + GURL("https://www.offer_1_example.com/"); + credit_card_offer_2.offer_details_url = + GURL("https://www.offer_2_example.com/"); + credit_card_offer_3.offer_details_url = + GURL("https://www.offer_3_example.com/"); + + // Set merchant domains for offer 1. + credit_card_offer_1.merchant_domain.emplace_back( + GURL("https://www.merchant_domain_1_1.com/")); + credit_card_offer_1.merchant_domain.emplace_back( + GURL("https://www.merchant_domain_1_2.com/")); + credit_card_offer_1.merchant_domain.emplace_back( + GURL("https://www.merchant_domain_1_3.com/")); + // Set merchant domains for offer 2. + credit_card_offer_2.merchant_domain.emplace_back( + GURL("https://www.merchant_domain_2_1.com/")); + // Set merchant domains for offer 3. + credit_card_offer_3.merchant_domain.emplace_back( + GURL("https://www.merchant_domain_3_1.com/")); + credit_card_offer_3.merchant_domain.emplace_back( + GURL("https://www.merchant_domain_3_2.com/")); + + // Set eligible instrument ID for offer 1. + credit_card_offer_1.eligible_instrument_id.push_back(10); + credit_card_offer_1.eligible_instrument_id.push_back(11); + // Set eligible instrument ID for offer 2. + credit_card_offer_2.eligible_instrument_id.push_back(20); + credit_card_offer_2.eligible_instrument_id.push_back(21); + credit_card_offer_2.eligible_instrument_id.push_back(22); + // Set eligible instrument ID for offer 3. + credit_card_offer_3.eligible_instrument_id.push_back(30); + + // Create vector of offer data. + std::vector<AutofillOfferData> autofill_offer_data; + autofill_offer_data.push_back(credit_card_offer_1); + autofill_offer_data.push_back(credit_card_offer_2); + autofill_offer_data.push_back(credit_card_offer_3); + + table_->SetCreditCardOffers(autofill_offer_data); + + std::vector<std::unique_ptr<AutofillOfferData>> output_offer_data; + + EXPECT_TRUE(table_->GetCreditCardOffers(&output_offer_data)); + EXPECT_EQ(autofill_offer_data.size(), output_offer_data.size()); + + for (const auto& data : autofill_offer_data) { + // Find output data with corresponding Offer ID. + size_t output_index = 0; + while (output_index < output_offer_data.size()) { + if (data.offer_id == output_offer_data[output_index]->offer_id) { + break; + } + output_index++; + } + + // Expect to find matching Offer ID's. + EXPECT_NE(output_index, output_offer_data.size()); + + // All corresponding fields must be equal. + EXPECT_EQ(data.offer_id, output_offer_data[output_index]->offer_id); + EXPECT_EQ(data.offer_reward_amount, + output_offer_data[output_index]->offer_reward_amount); + EXPECT_EQ(data.expiry, output_offer_data[output_index]->expiry); + EXPECT_EQ(data.offer_details_url.spec(), + output_offer_data[output_index]->offer_details_url.spec()); + ASSERT_THAT(data.merchant_domain, + testing::UnorderedElementsAreArray( + output_offer_data[output_index]->merchant_domain)); + ASSERT_THAT(data.eligible_instrument_id, + testing::UnorderedElementsAreArray( + output_offer_data[output_index]->eligible_instrument_id)); + } +} + } // namespace autofill
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc index 0af9de6e..3d4b6c1f 100644 --- a/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc +++ b/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc
@@ -882,7 +882,6 @@ EXPECT_EQ(card.billing_address_id(), cards[0]->billing_address_id()); EXPECT_EQ(card.nickname(), cards[0]->nickname()); EXPECT_EQ(card.card_issuer(), cards[0]->card_issuer()); - EXPECT_EQ(card.instrument_id(), cards[0]->instrument_id()); // Also make sure that those types are not empty, to exercice all the code // paths. @@ -891,7 +890,6 @@ EXPECT_NE(0, card.expiration_month()); EXPECT_NE(0, card.expiration_year()); EXPECT_FALSE(card.nickname().empty()); - EXPECT_NE(0, card.instrument_id()); } // Test that all field values for a cloud token data sent from the server are
diff --git a/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc b/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc index 59d3423..24f183c 100644 --- a/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc +++ b/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc
@@ -9,6 +9,7 @@ #include "base/location.h" #include "base/notreached.h" #include "base/single_thread_task_runner.h" +#include "components/autofill/core/browser/data_model/autofill_offer_data.h" #include "components/autofill/core/browser/data_model/autofill_profile.h" #include "components/autofill/core/browser/data_model/credit_card.h" #include "components/autofill/core/browser/data_model/credit_card_cloud_token_data.h" @@ -567,6 +568,16 @@ AUTOFILL_CLOUDTOKEN_RESULT, std::move(cloud_token_data)); } +std::unique_ptr<WDTypedResult> AutofillWebDataBackendImpl::GetCreditCardOffers( + WebDatabase* db) { + DCHECK(owning_task_runner()->RunsTasksInCurrentSequence()); + std::vector<std::unique_ptr<AutofillOfferData>> offers; + AutofillTable::FromWebDatabase(db)->GetCreditCardOffers(&offers); + return std::make_unique< + WDResult<std::vector<std::unique_ptr<AutofillOfferData>>>>( + AUTOFILL_OFFER_DATA, std::move(offers)); +} + WebDatabase::State AutofillWebDataBackendImpl::ClearAllServerData( WebDatabase* db) { DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
diff --git a/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h b/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h index e2e3c00..5525d4a 100644 --- a/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h +++ b/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h
@@ -33,7 +33,7 @@ class AutofillWebDataServiceObserverOnDBSequence; class CreditCard; -// Backend implentation for the AutofillWebDataService. This class runs on the +// Backend implementation for the AutofillWebDataService. This class runs on the // DB sequence, as it handles reads and writes to the WebDatabase, and functions // in it should only be called from that sequence. Most functions here are just // the implementations of the corresponding functions in the Autofill @@ -198,6 +198,9 @@ // Returns the CreditCardCloudTokenData from the database. std::unique_ptr<WDTypedResult> GetCreditCardCloudTokenData(WebDatabase* db); + // Returns Credit Card Offers Data from the database. + std::unique_ptr<WDTypedResult> GetCreditCardOffers(WebDatabase* db); + WebDatabase::State ClearAllServerData(WebDatabase* db); WebDatabase::State ClearAllLocalData(WebDatabase* db);
diff --git a/components/autofill/core/browser/webdata/autofill_webdata_service.cc b/components/autofill/core/browser/webdata/autofill_webdata_service.cc index 9168b76..6487f6b 100644 --- a/components/autofill/core/browser/webdata/autofill_webdata_service.cc +++ b/components/autofill/core/browser/webdata/autofill_webdata_service.cc
@@ -10,6 +10,7 @@ #include "base/location.h" #include "base/single_thread_task_runner.h" #include "base/stl_util.h" +#include "components/autofill/core/browser/data_model/autofill_offer_data.h" #include "components/autofill/core/browser/data_model/autofill_profile.h" #include "components/autofill/core/browser/data_model/credit_card.h" #include "components/autofill/core/browser/geo/autofill_country.h" @@ -276,6 +277,15 @@ consumer); } +WebDataServiceBase::Handle AutofillWebDataService::GetCreditCardOffers( + WebDataServiceConsumer* consumer) { + return wdbs_->ScheduleDBTaskWithResult( + FROM_HERE, + base::BindOnce(&AutofillWebDataBackendImpl::GetCreditCardOffers, + autofill_backend_), + consumer); +} + void AutofillWebDataService::ClearAllServerData() { wdbs_->ScheduleDBTask( FROM_HERE, base::BindOnce(&AutofillWebDataBackendImpl::ClearAllServerData, @@ -383,8 +393,7 @@ consumer); } -AutofillWebDataService::~AutofillWebDataService() { -} +AutofillWebDataService::~AutofillWebDataService() = default; void AutofillWebDataService::NotifyAutofillMultipleChangedOnUISequence() { DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
diff --git a/components/autofill/core/browser/webdata/autofill_webdata_service.h b/components/autofill/core/browser/webdata/autofill_webdata_service.h index d71da82..9165888 100644 --- a/components/autofill/core/browser/webdata/autofill_webdata_service.h +++ b/components/autofill/core/browser/webdata/autofill_webdata_service.h
@@ -159,6 +159,13 @@ WebDataServiceBase::Handle GetCreditCardCloudTokenData( WebDataServiceConsumer* consumer); + // Initiates the request for credit card offer data. The method + // OnWebDataServiceRequestDone of |consumer| gets called when the request is + // finished, with the offer data included in the argument |result|. The + // consumer owns the data. + WebDataServiceBase::Handle GetCreditCardOffers( + WebDataServiceConsumer* consumer); + void ClearAllServerData(); void ClearAllLocalData();
diff --git a/components/blocked_content/safe_browsing_triggered_popup_blocker_unittest.cc b/components/blocked_content/safe_browsing_triggered_popup_blocker_unittest.cc index 973e35e..dc9c2d0 100644 --- a/components/blocked_content/safe_browsing_triggered_popup_blocker_unittest.cc +++ b/components/blocked_content/safe_browsing_triggered_popup_blocker_unittest.cc
@@ -64,6 +64,9 @@ subresource_filter::ActivationDecision* decision) override { return initial_activation_level; } + void OnAdsViolationTriggered( + content::RenderFrameHost*, + subresource_filter::mojom::AdsViolation) override {} // content::RenderViewHostTestHarness: void SetUp() override {
diff --git a/components/browser_sync/profile_sync_components_factory_impl.cc b/components/browser_sync/profile_sync_components_factory_impl.cc index 61942d7..9c1ceb1 100644 --- a/components/browser_sync/profile_sync_components_factory_impl.cc +++ b/components/browser_sync/profile_sync_components_factory_impl.cc
@@ -134,7 +134,7 @@ DCHECK(sync_client_); } -ProfileSyncComponentsFactoryImpl::~ProfileSyncComponentsFactoryImpl() {} +ProfileSyncComponentsFactoryImpl::~ProfileSyncComponentsFactoryImpl() = default; syncer::DataTypeController::TypeVector ProfileSyncComponentsFactoryImpl::CreateCommonDataTypeControllers(
diff --git a/components/browser_sync/profile_sync_components_factory_impl.h b/components/browser_sync/profile_sync_components_factory_impl.h index 054f328..01909fd0 100644 --- a/components/browser_sync/profile_sync_components_factory_impl.h +++ b/components/browser_sync/profile_sync_components_factory_impl.h
@@ -9,7 +9,6 @@ #include <string> #include "base/compiler_specific.h" -#include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/sequenced_task_runner.h" #include "components/sync/base/model_type.h" @@ -57,6 +56,10 @@ const scoped_refptr<password_manager::PasswordStore>& account_password_store, sync_bookmarks::BookmarkSyncService* bookmark_sync_service); + ProfileSyncComponentsFactoryImpl(const ProfileSyncComponentsFactoryImpl&) = + delete; + ProfileSyncComponentsFactoryImpl& operator=( + const ProfileSyncComponentsFactoryImpl&) = delete; ~ProfileSyncComponentsFactoryImpl() override; // Creates and returns enabled datatypes and their controllers. @@ -124,8 +127,6 @@ const scoped_refptr<password_manager::PasswordStore> profile_password_store_; const scoped_refptr<password_manager::PasswordStore> account_password_store_; sync_bookmarks::BookmarkSyncService* const bookmark_sync_service_; - - DISALLOW_COPY_AND_ASSIGN(ProfileSyncComponentsFactoryImpl); }; } // namespace browser_sync
diff --git a/components/browser_ui/android/bottomsheet/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheet.java b/components/browser_ui/android/bottomsheet/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheet.java index e7510d27..efcf562 100644 --- a/components/browser_ui/android/bottomsheet/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheet.java +++ b/components/browser_ui/android/bottomsheet/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheet.java
@@ -23,6 +23,7 @@ import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; +import org.chromium.base.Log; import org.chromium.base.MathUtils; import org.chromium.base.ObserverList; import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent.HeightMode; @@ -44,6 +45,8 @@ */ class BottomSheet extends FrameLayout implements BottomSheetSwipeDetector.SwipeableBottomSheet, View.OnLayoutChangeListener { + private static final String TAG = "BottomSheet"; + /** * The base duration of the settling animation of the sheet. 218 ms is a spec for material * design (this is the minimum time a user is guaranteed to pay attention to something). @@ -217,6 +220,9 @@ * Called when the activity containing the {@link BottomSheet} is destroyed. */ void destroy() { + Log.i(TAG, + "Sheet destroyed: state: " + mCurrentState + + ", content null: " + (getCurrentSheetContent() == null)); mIsDestroyed = true; mIsTouchEnabled = false; mObservers.clear(); @@ -496,6 +502,11 @@ // If the desired content is already showing, do nothing. if (mSheetContent == content) return; + Log.i(TAG, + "Setting sheet content: state: " + mCurrentState + + ", content null: " + (content == null)); + if (content == null) Thread.dumpStack(); + // Remove this as listener from previous content layout and size changes. if (mSheetContent != null) { mSheetContent.setContentSizeListener(null); @@ -601,6 +612,9 @@ if (mIsDestroyed) return; mSettleAnimator = null; + Log.i(TAG, + "Ending settle animation: target: " + targetState + + ", content null: " + (getCurrentSheetContent() == null)); setInternalCurrentState(targetState, reason); mTargetState = SheetState.NONE; } @@ -616,6 +630,10 @@ } }); + Log.i(TAG, + "Starting settle animation: target: " + targetState + + ", content null: " + (getCurrentSheetContent() == null)); + setInternalCurrentState(SheetState.SCROLLING, reason); mSettleAnimator.start(); } @@ -864,6 +882,10 @@ void setSheetState(@SheetState int state, boolean animate, @StateChangeReason int reason) { assert state != SheetState.NONE; + Log.i(TAG, + "Setting sheet state: state: " + mCurrentState + + ", content null: " + (getCurrentSheetContent() == null)); + // Setting state to SCROLLING is not a valid operation. This can happen only when // we're already in the scrolling state. Make it no-op. if (state == SheetState.SCROLLING) { @@ -918,6 +940,10 @@ private void setInternalCurrentState(@SheetState int state, @StateChangeReason int reason) { if (state == mCurrentState) return; + if (getCurrentSheetContent() == null && state != SheetState.HIDDEN) { + Log.i(TAG, "Content null while open!"); + } + // TODO(mdjones): This shouldn't be able to happen, but does occasionally during layout. // Fix the race condition that is making this happen. if (state == SheetState.NONE) {
diff --git a/components/content_capture/browser/content_capture_receiver_test.cc b/components/content_capture/browser/content_capture_receiver_test.cc index cefc77bf..298fc00 100644 --- a/components/content_capture/browser/content_capture_receiver_test.cc +++ b/components/content_capture/browser/content_capture_receiver_test.cc
@@ -47,8 +47,7 @@ mojo::PendingAssociatedReceiver<mojom::ContentCaptureReceiver> GetPendingAssociatedReceiver() { - return content_capture_receiver_ - .BindNewEndpointAndPassDedicatedReceiverForTesting(); + return content_capture_receiver_.BindNewEndpointAndPassDedicatedReceiver(); } private:
diff --git a/components/crash/content/browser/error_reporting/BUILD.gn b/components/crash/content/browser/error_reporting/BUILD.gn new file mode 100644 index 0000000..1f31c8c --- /dev/null +++ b/components/crash/content/browser/error_reporting/BUILD.gn
@@ -0,0 +1,60 @@ +# 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. + +# Error reporting is not enabled on Fuchsia, so there is no consent checking +# function. TODO(crbug.com/753619): Enable crash reporting on Fuchsia. +assert(!is_fuchsia) + +# Javascript Error reporting is not currently used on iOS +assert(!is_ios) + +static_library("error_reporting") { + sources = [ + "javascript_error_report.cc", + "javascript_error_report.h", + "send_javascript_error_report.cc", + "send_javascript_error_report.h", + ] + + deps = [ + "//base", + "//components/crash/core/app", + "//components/feedback", + "//content/public/browser", + "//net", + "//services/network:network_service", + "//services/network/public/cpp", + ] +} + +source_set("mock_crash_endpoint") { + testonly = true + sources = [ + "mock_crash_endpoint.cc", + "mock_crash_endpoint.h", + ] + deps = [ + ":error_reporting", + "//base", + "//components/crash/core/app", + "//net", + "//net:test_support", + "//testing/gtest", + "//url", + ] +} + +source_set("unit_tests") { + testonly = true + sources = [ "send_javascript_error_report_unittest.cc" ] + deps = [ + ":error_reporting", + ":mock_crash_endpoint", + "//base", + "//components/crash/core/app", + "//content/test:test_support", + "//net:test_support", + "//testing/gtest", + ] +}
diff --git a/components/crash/content/browser/error_reporting/DEPS b/components/crash/content/browser/error_reporting/DEPS new file mode 100644 index 0000000..3d71d06 --- /dev/null +++ b/components/crash/content/browser/error_reporting/DEPS
@@ -0,0 +1,5 @@ +include_rules = [ + "+components/feedback", + "+net", + "+services/network", +]
diff --git a/components/crash/content/browser/error_reporting/OWNERS b/components/crash/content/browser/error_reporting/OWNERS new file mode 100644 index 0000000..986c32b --- /dev/null +++ b/components/crash/content/browser/error_reporting/OWNERS
@@ -0,0 +1,4 @@ +iby@chromium.org +mutexlox@chromium.org + +# COMPONENT: Internals>CrashReporting
diff --git a/components/crash/content/browser/error_reporting/javascript_error_report.cc b/components/crash/content/browser/error_reporting/javascript_error_report.cc new file mode 100644 index 0000000..8614f47 --- /dev/null +++ b/components/crash/content/browser/error_reporting/javascript_error_report.cc
@@ -0,0 +1,16 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/crash/content/browser/error_reporting/javascript_error_report.h" + +JavaScriptErrorReport::JavaScriptErrorReport() = default; +JavaScriptErrorReport::JavaScriptErrorReport(const JavaScriptErrorReport& rhs) = + default; +JavaScriptErrorReport::JavaScriptErrorReport( + JavaScriptErrorReport&& rhs) noexcept = default; +JavaScriptErrorReport::~JavaScriptErrorReport() = default; +JavaScriptErrorReport& JavaScriptErrorReport::operator=( + const JavaScriptErrorReport& rhs) = default; +JavaScriptErrorReport& JavaScriptErrorReport::operator=( + JavaScriptErrorReport&& rhs) noexcept = default;
diff --git a/components/crash/content/browser/error_reporting/javascript_error_report.h b/components/crash/content/browser/error_reporting/javascript_error_report.h new file mode 100644 index 0000000..49f1bed --- /dev/null +++ b/components/crash/content/browser/error_reporting/javascript_error_report.h
@@ -0,0 +1,49 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_CRASH_CONTENT_BROWSER_ERROR_REPORTING_JAVASCRIPT_ERROR_REPORT_H_ +#define COMPONENTS_CRASH_CONTENT_BROWSER_ERROR_REPORTING_JAVASCRIPT_ERROR_REPORT_H_ + +#include <string> + +#include "base/optional.h" + +// A report about a JavaScript error that we might want to send back to Google +// so it can be fixed. Fill in the fields and then call +// SendJavaScriptErrorReport. +struct JavaScriptErrorReport { + JavaScriptErrorReport(); + JavaScriptErrorReport(const JavaScriptErrorReport& rhs); + JavaScriptErrorReport(JavaScriptErrorReport&& rhs) noexcept; + ~JavaScriptErrorReport(); + JavaScriptErrorReport& operator=(const JavaScriptErrorReport& rhs); + JavaScriptErrorReport& operator=(JavaScriptErrorReport&& rhs) noexcept; + + // The error message. Must be present + std::string message; + + // URL where the error occurred. Must be the full URL, containing the protocol + // (e.g. http://www.example.com). + std::string url; + + // Name of the product where the error occurred. If empty, use the product + // variant of Chrome that is hosting the extension. (e.g. "Chrome" or + // "Chrome_ChromeOS"). + std::string product; + + // Version of the product where the error occurred. If empty, use the version + // of Chrome that is hosting the extension (e.g. "73.0.3683.75"). + std::string version; + + // Line number where the error occurred. Not sent if not present. + base::Optional<int> line_number; + + // Column number where the error occurred. Not sent if not present. + base::Optional<int> column_number; + + // String containing the stack trace for the error. Not sent if not present. + base::Optional<std::string> stack_trace; +}; + +#endif // COMPONENTS_CRASH_CONTENT_BROWSER_ERROR_REPORTING_JAVASCRIPT_ERROR_REPORT_H_
diff --git a/extensions/browser/api/crash_report_private/mock_crash_endpoint.cc b/components/crash/content/browser/error_reporting/mock_crash_endpoint.cc similarity index 72% rename from extensions/browser/api/crash_report_private/mock_crash_endpoint.cc rename to components/crash/content/browser/error_reporting/mock_crash_endpoint.cc index 9a23cc3..2e8aae4 100644 --- a/extensions/browser/api/crash_report_private/mock_crash_endpoint.cc +++ b/components/crash/content/browser/error_reporting/mock_crash_endpoint.cc
@@ -2,12 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "extensions/browser/api/crash_report_private/mock_crash_endpoint.h" +#include "components/crash/content/browser/error_reporting/mock_crash_endpoint.h" #include "base/run_loop.h" #include "base/threading/scoped_blocking_call.h" +#include "build/build_config.h" +#include "components/crash/content/browser/error_reporting/send_javascript_error_report.h" #include "components/crash/core/app/crash_reporter_client.h" -#include "extensions/browser/api/crash_report_private/crash_report_private_api.h" #include "net/http/http_status_code.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "net/test/embedded_test_server/http_request.h" @@ -30,27 +31,31 @@ FROM_HERE, base::BlockingType::MAY_BLOCK); return owner_->consented_; } +#if defined(OS_POSIX) && !defined(OS_MAC) void GetProductNameAndVersion(std::string* product_name, std::string* version, std::string* channel) override { - *product_name = "Chrome (Chrome OS)"; + *product_name = "Chrome_ChromeOS"; *version = "1.2.3.4"; *channel = "Stable"; } - +#endif private: MockCrashEndpoint* owner_; }; +MockCrashEndpoint::Report::Report(std::string query_value, + std::string content_value) + : query(std::move(query_value)), content(std::move(content_value)) {} + MockCrashEndpoint::MockCrashEndpoint( net::test_server::EmbeddedTestServer* test_server) : test_server_(test_server) { - test_server->RegisterRequestHandler( - base::Bind(&MockCrashEndpoint::HandleRequest, base::Unretained(this))); + test_server->RegisterRequestHandler(base::BindRepeating( + &MockCrashEndpoint::HandleRequest, base::Unretained(this))); EXPECT_TRUE(test_server->Start()); - extensions::api::SetCrashEndpointForTesting( - test_server->GetURL(kTestCrashEndpoint).spec()); + SetCrashEndpointForTesting(test_server->GetURL(kTestCrashEndpoint).spec()); client_ = std::make_unique<Client>(this); crash_reporter::SetCrashReporterClient(client_.get()); } @@ -59,15 +64,15 @@ crash_reporter::SetCrashReporterClient(nullptr); } -const MockCrashEndpoint::Report MockCrashEndpoint::WaitForReport() { - if (!last_report_.query.empty()) { - return std::move(last_report_); +MockCrashEndpoint::Report MockCrashEndpoint::WaitForReport() { + if (last_report_) { + return *last_report_; } base::RunLoop run_loop; on_report_ = run_loop.QuitClosure(); run_loop.Run(); on_report_.Reset(); - return std::move(last_report_); + return *last_report_; } std::unique_ptr<net::test_server::HttpResponse> @@ -77,7 +82,7 @@ return nullptr; } - last_report_ = {absolute_url.query(), request.content}; + last_report_ = Report(absolute_url.query(), request.content); auto http_response = std::make_unique<net::test_server::BasicHttpResponse>(); http_response->set_code(net::HTTP_OK); http_response->set_content("123");
diff --git a/extensions/browser/api/crash_report_private/mock_crash_endpoint.h b/components/crash/content/browser/error_reporting/mock_crash_endpoint.h similarity index 71% rename from extensions/browser/api/crash_report_private/mock_crash_endpoint.h rename to components/crash/content/browser/error_reporting/mock_crash_endpoint.h index 029f219..53b1184 100644 --- a/extensions/browser/api/crash_report_private/mock_crash_endpoint.h +++ b/components/crash/content/browser/error_reporting/mock_crash_endpoint.h
@@ -2,13 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef EXTENSIONS_BROWSER_API_CRASH_REPORT_PRIVATE_MOCK_CRASH_ENDPOINT_H_ -#define EXTENSIONS_BROWSER_API_CRASH_REPORT_PRIVATE_MOCK_CRASH_ENDPOINT_H_ +#ifndef COMPONENTS_CRASH_CONTENT_BROWSER_ERROR_REPORTING_MOCK_CRASH_ENDPOINT_H_ +#define COMPONENTS_CRASH_CONTENT_BROWSER_ERROR_REPORTING_MOCK_CRASH_ENDPOINT_H_ #include <memory> #include <string> #include "base/callback.h" +#include "base/optional.h" +#include "url/gurl.h" namespace net { namespace test_server { @@ -22,6 +24,7 @@ class MockCrashEndpoint { public: struct Report { + Report(std::string query_value, std::string content_value); std::string query; std::string content; }; @@ -32,9 +35,10 @@ ~MockCrashEndpoint(); // Returns the last received report, or waits for a query and returns it. - const Report WaitForReport(); + Report WaitForReport(); - const Report& last_report() const { return last_report_; } + // Returns the last report received, if any. + const base::Optional<Report>& last_report() const { return last_report_; } // Configures whether the mock crash reporter client has user-consent for // submitting crash reports. @@ -48,9 +52,9 @@ net::test_server::EmbeddedTestServer* test_server_; std::unique_ptr<Client> client_; - Report last_report_; + base::Optional<Report> last_report_; bool consented_ = true; base::RepeatingClosure on_report_; }; -#endif // EXTENSIONS_BROWSER_API_CRASH_REPORT_PRIVATE_MOCK_CRASH_ENDPOINT_H_ +#endif // COMPONENTS_CRASH_CONTENT_BROWSER_ERROR_REPORTING_MOCK_CRASH_ENDPOINT_H_
diff --git a/components/crash/content/browser/error_reporting/send_javascript_error_report.cc b/components/crash/content/browser/error_reporting/send_javascript_error_report.cc new file mode 100644 index 0000000..d39c58a --- /dev/null +++ b/components/crash/content/browser/error_reporting/send_javascript_error_report.cc
@@ -0,0 +1,327 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/crash/content/browser/error_reporting/send_javascript_error_report.h" + +#include <memory> +#include <string> +#include <tuple> +#include <utility> +#include <vector> + +#include "base/callback.h" +#include "base/callback_helpers.h" +#include "base/logging.h" +#include "base/memory/scoped_refptr.h" +#include "base/no_destructor.h" +#include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/stringprintf.h" +#include "base/system/sys_info.h" +#include "base/task/task_traits.h" +#include "base/task/thread_pool.h" +#include "build/build_config.h" +#include "components/crash/content/browser/error_reporting/javascript_error_report.h" +#include "components/crash/core/app/client_upload_info.h" +#include "components/feedback/redaction_tool.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/storage_partition.h" +#include "net/base/escape.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" +#include "services/network/public/cpp/simple_url_loader.h" + +namespace { + +#if defined(GOOGLE_CHROME_BUILD) +constexpr char kCrashEndpointUrl[] = "https://clients2.google.com/cr/report"; +#else +constexpr char kCrashEndpointUrl[] = ""; +#endif + +constexpr int kCrashEndpointResponseMaxSizeInBytes = 1024; + +std::string& GetCrashEndpoint() { + static base::NoDestructor<std::string> crash_endpoint(kCrashEndpointUrl); + return *crash_endpoint; +} + +struct OsVersionOverride { + OsVersionOverride(int32_t major_override, + int32_t minor_override, + int32_t bugfix_override) + : major(major_override), minor(minor_override), bugfix(bugfix_override) {} + int32_t major; + int32_t minor; + int32_t bugfix; +}; + +// If return value is set, use that as the major/minor/bugfix OS version +// numbers. This is used as dependency injection during testing. +base::Optional<OsVersionOverride>& GetOsVersionOverrides() { + static base::NoDestructor<base::Optional<OsVersionOverride>> testing_override; + return *testing_override; +} + +void OnRequestComplete(std::unique_ptr<network::SimpleURLLoader> url_loader, + base::ScopedClosureRunner callback_runner, + std::unique_ptr<std::string> response_body) { + if (response_body) { + // TODO(iby): Update the crash log (uploads.log) + DVLOG(1) << "Uploaded crash report. ID: " << *response_body; + } else { + LOG(ERROR) << "Failed to upload crash report"; + } + // callback_runner will implicitly run the callback when we reach this line. +} + +// Sometimes, the stack trace will contain an error message as the first line, +// which confuses the Crash server. This function deletes it if it is present. +void RemoveErrorMessageFromStackTrace(const std::string& error_message, + std::string& stack_trace) { + // Keep the original stack trace if the error message is not present. + const auto error_message_index = stack_trace.find(error_message); + if (error_message_index == std::string::npos) { + return; + } + + // If the stack trace only contains one line, then delete the whole trace. + const auto first_line_end_index = stack_trace.find('\n'); + if (first_line_end_index == std::string::npos) { + stack_trace.clear(); + return; + } + + // Otherwise, delete the first line. + stack_trace = stack_trace.substr(first_line_end_index + 1); +} + +std::string RedactErrorMessage(const std::string& message) { + return feedback::RedactionTool(/*first_party_extension_ids=*/nullptr) + .Redact(message); +} + +// Returns the redacted, fixed-up error report if the user consented to have it +// sent. Returns base::nullopt if the user did not consent or we otherwise +// should not send the report. All the MayBlock work should be done in here. +base::Optional<JavaScriptErrorReport> CheckConsentAndRedact( + JavaScriptErrorReport error_report) { + if (!crash_reporter::GetClientCollectStatsConsent()) { + return base::nullopt; + } + + // Remove error message from stack trace before redaction, since redaction + // might change the error message enough that we don't find it. + if (error_report.stack_trace) { + RemoveErrorMessageFromStackTrace(error_report.message, + *error_report.stack_trace); + } + + error_report.message = RedactErrorMessage(error_report.message); + // TODO(https://crbug.com/1121816): Also redact stack trace, but don't + // completely remove the URL (only query & fragment). + return error_report; +} + +using ParameterMap = std::map<std::string, std::string>; + +std::string BuildPostRequestQueryString(const ParameterMap& params) { + std::vector<std::string> query_parts; + for (const auto& kv : params) { + query_parts.push_back(base::StrCat( + {kv.first, "=", + net::EscapeQueryParamValue(kv.second, /*use_plus=*/false)})); + } + return base::JoinString(query_parts, "&"); +} + +struct PlatformInfo { + std::string product_name; + std::string version; + std::string channel; + std::string os_version; +}; + +PlatformInfo GetPlatformInfo() { + PlatformInfo info; + + // TODO(https://crbug.com/1121816): Get correct product_name for non-POSIX + // platforms. +#if defined(OS_POSIX) && !defined(OS_APPLE) + crash_reporter::GetClientProductNameAndVersion(&info.product_name, + &info.version, &info.channel); +#endif + int32_t os_major_version = 0; + int32_t os_minor_version = 0; + int32_t os_bugfix_version = 0; + const base::Optional<OsVersionOverride>& version_override = + GetOsVersionOverrides(); + if (version_override) { + os_major_version = version_override->major; + os_minor_version = version_override->minor; + os_bugfix_version = version_override->bugfix; + } else { + base::SysInfo::OperatingSystemVersionNumbers( + &os_major_version, &os_minor_version, &os_bugfix_version); + } + + info.os_version = base::StringPrintf("%d.%d.%d", os_major_version, + os_minor_version, os_bugfix_version); + return info; +} + +void SendReport(const GURL& url, + const std::string& body, + base::ScopedClosureRunner callback_runner, + network::SharedURLLoaderFactory* loader_factory) { + auto resource_request = std::make_unique<network::ResourceRequest>(); + resource_request->method = "POST"; + resource_request->url = url; + + const auto traffic_annotation = + net::DefineNetworkTrafficAnnotation("javascript_report_error", R"( + semantics { + sender: "JavaScript error reporter" + description: + "Chrome can send JavaScript errors that occur within built-in " + "component extensions. If enabled, the error message, along " + "with information about Chrome and the operating system, is sent to " + "Google." + trigger: + "A JavaScript error occurs in a Chrome component extension (an " + "extension bundled with the Chrome browser, not downloaded " + "separately)." + data: + "The JavaScript error message, the version and channel of Chrome, " + "the URL of the extension, the line and column number where the " + "error occurred, and a stack trace of the error." + destination: GOOGLE_OWNED_SERVICE + } + policy { + cookies_allowed: NO + setting: + "You can enable or disable this feature via 'Automatically send " + "usage statistics and crash reports to Google' in Chromium's " + "settings under Advanced, Privacy. (This is in System Settings on " + "Chromebooks.) This feature is enabled by default." + chrome_policy { + MetricsReportingEnabled { + policy_options {mode: MANDATORY} + MetricsReportingEnabled: false + } + } + })"); + + DVLOG(1) << "Sending crash report: " << resource_request->url; + + auto url_loader = network::SimpleURLLoader::Create( + std::move(resource_request), traffic_annotation); + + if (!body.empty()) { + url_loader->AttachStringForUpload(body, "text/plain"); + } + + network::SimpleURLLoader* loader = url_loader.get(); + loader->DownloadToString( + loader_factory, + base::BindOnce(&OnRequestComplete, std::move(url_loader), + std::move(callback_runner)), + kCrashEndpointResponseMaxSizeInBytes); +} + +// Finishes sending process once the MayBlock processing is done. On UI thread. +void OnConsentCheckCompleted( + base::ScopedClosureRunner callback_runner, + scoped_refptr<network::SharedURLLoaderFactory> loader_factory, + base::Optional<JavaScriptErrorReport> error_report) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (!error_report) { + // User didn't consent. This isn't an error so don't log an error. + return; + } + + std::string& crash_endpoint_string = GetCrashEndpoint(); + if (crash_endpoint_string.empty()) { + LOG(WARNING) << "Not sending error reports to Google for browsers that are " + "not Google Chrome"; + return; + } + + // TODO(https://crbug.com/986166): Use crash_reporter for Chrome OS. + const auto platform = GetPlatformInfo(); + + const GURL source(error_report->url); + const auto product = error_report->product.empty() ? platform.product_name + : error_report->product; + const auto version = + error_report->version.empty() ? platform.version : error_report->version; + + ParameterMap params; + params["prod"] = net::EscapeQueryParamValue(product, /*use_plus=*/false); + params["ver"] = net::EscapeQueryParamValue(version, /*use_plus=*/false); + params["type"] = "JavascriptError"; + params["error_message"] = error_report->message; + params["browser"] = "Chrome"; + params["browser_version"] = platform.version; + params["channel"] = platform.channel; + // TODO(https://crbug.com/1121816): Handle non-ChromeOS platforms. + params["os"] = "ChromeOS"; + params["os_version"] = platform.os_version; + params["full_url"] = source.spec(); + params["url"] = source.path(); + params["src"] = source.spec(); + if (error_report->line_number) + params["line"] = base::NumberToString(*error_report->line_number); + if (error_report->column_number) + params["column"] = base::NumberToString(*error_report->column_number); + + const GURL url(base::StrCat( + {crash_endpoint_string, "?", BuildPostRequestQueryString(params)})); + std::string body; + if (error_report->stack_trace) { + body = std::move(*error_report->stack_trace); + } + + SendReport(url, body, std::move(callback_runner), loader_factory.get()); +} + +} // namespace + +void SendJavaScriptErrorReport(JavaScriptErrorReport error_report, + base::OnceClosure completion_callback, + content::BrowserContext* browser_context) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + base::ScopedClosureRunner callback_runner(std::move(completion_callback)); + + // loader_factory must be created on UI thread. Get it now while we still + // know the browser_context pointer is valid. + scoped_refptr<network::SharedURLLoaderFactory> loader_factory = + content::BrowserContext::GetDefaultStoragePartition(browser_context) + ->GetURLLoaderFactoryForBrowserProcess(); + + // Consent check needs to be done on a blockable thread. We must return to + // this thread (the UI thread) to use the loader_factory. + base::ThreadPool::PostTaskAndReplyWithResult( + FROM_HERE, {base::MayBlock()}, + base::BindOnce(&CheckConsentAndRedact, std::move(error_report)), + base::BindOnce(&OnConsentCheckCompleted, std::move(callback_runner), + std::move(loader_factory))); +} + +void SetCrashEndpointForTesting(const std::string& endpoint) { + GetCrashEndpoint() = endpoint; +} + +// The weird "{" comment is to get the +// CheckNoProductionCodeUsingTestOnlyFunctions PRESUBMIT to be quiet. +void SetOsVersionForTesting(int32_t os_major_version, // { + int32_t os_minor_version, + int32_t os_bugfix_version) { + GetOsVersionOverrides().emplace(os_major_version, os_minor_version, + os_bugfix_version); +} + +void ClearOsVersionTestingOverride() { + GetOsVersionOverrides().reset(); +}
diff --git a/components/crash/content/browser/error_reporting/send_javascript_error_report.h b/components/crash/content/browser/error_reporting/send_javascript_error_report.h new file mode 100644 index 0000000..9eacc65 --- /dev/null +++ b/components/crash/content/browser/error_reporting/send_javascript_error_report.h
@@ -0,0 +1,37 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_CRASH_CONTENT_BROWSER_ERROR_REPORTING_SEND_JAVASCRIPT_ERROR_REPORT_H_ +#define COMPONENTS_CRASH_CONTENT_BROWSER_ERROR_REPORTING_SEND_JAVASCRIPT_ERROR_REPORT_H_ + +#include <stdint.h> + +#include <string> + +#include "base/callback_forward.h" + +namespace content { +class BrowserContext; +} +struct JavaScriptErrorReport; + +// Sends a report of an error in JavaScript (such as an unhandled exception) to +// Google's error collection service. This should be called on the UI thread; +// it will return after the report sending is started. |completion_callback| is +// called when the report send completes or fails. +void SendJavaScriptErrorReport(JavaScriptErrorReport error_report, + base::OnceClosure completion_callback, + content::BrowserContext* browser_context); + +// Override the URL we send the crashes to. +void SetCrashEndpointForTesting(const std::string& endpoint); + +// Override the OS Version. +void SetOsVersionForTesting(int32_t os_major_version, + int32_t os_minor_version, + int32_t os_bugfix_version); +// Go back to the default behavior of getting the OS version from the OS. +void ClearOsVersionTestingOverride(); + +#endif // COMPONENTS_CRASH_CONTENT_BROWSER_ERROR_REPORTING_SEND_JAVASCRIPT_ERROR_REPORT_H_
diff --git a/components/crash/content/browser/error_reporting/send_javascript_error_report_unittest.cc b/components/crash/content/browser/error_reporting/send_javascript_error_report_unittest.cc new file mode 100644 index 0000000..7e18c8a --- /dev/null +++ b/components/crash/content/browser/error_reporting/send_javascript_error_report_unittest.cc
@@ -0,0 +1,224 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/crash/content/browser/error_reporting/send_javascript_error_report.h" + +#include <memory> +#include <utility> + +#include "base/callback.h" +#include "base/callback_helpers.h" +#include "build/build_config.h" +#include "components/crash/content/browser/error_reporting/javascript_error_report.h" +#include "components/crash/content/browser/error_reporting/mock_crash_endpoint.h" +#include "content/public/test/browser_task_environment.h" +#include "content/public/test/test_browser_context.h" +#include "net/test/embedded_test_server/embedded_test_server.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using ::testing::AllOf; +using ::testing::HasSubstr; + +class SendJavaScriptErrorReportTest : public ::testing::Test { + public: + SendJavaScriptErrorReportTest() + : task_environment_(content::BrowserTaskEnvironment::IO_MAINLOOP), + run_loop_quit_(run_loop_.QuitClosure()) {} + + void SetUp() override { + test_server_ = std::make_unique<net::test_server::EmbeddedTestServer>(); + endpoint_ = std::make_unique<MockCrashEndpoint>(test_server_.get()); + SetOsVersionForTesting(7, 20, 1); + } + + void TearDown() override { ClearOsVersionTestingOverride(); } + + void FinishCallback() { + finish_callback_was_called_ = true; + run_loop_quit_.Run(); + } + + protected: + content::BrowserTaskEnvironment task_environment_; + base::RunLoop run_loop_; + base::RepeatingClosure run_loop_quit_; + content::TestBrowserContext browser_context_; + std::unique_ptr<net::test_server::EmbeddedTestServer> test_server_; + std::unique_ptr<MockCrashEndpoint> endpoint_; + bool finish_callback_was_called_ = false; +}; + +TEST_F(SendJavaScriptErrorReportTest, Basic) { + JavaScriptErrorReport report; + report.message = "Hello World"; + report.url = "https://www.chromium.org/Home"; + + SendJavaScriptErrorReport( + std::move(report), + base::BindOnce(&SendJavaScriptErrorReportTest::FinishCallback, + base::Unretained(this)), + &browser_context_); + run_loop_.Run(); + EXPECT_TRUE(finish_callback_was_called_); + + const base::Optional<MockCrashEndpoint::Report>& actual_report = + endpoint_->last_report(); + ASSERT_TRUE(actual_report); + EXPECT_THAT(actual_report->query, HasSubstr("error_message=Hello%20World")); + EXPECT_THAT(actual_report->query, HasSubstr("type=JavascriptError")); + // TODO(iby) research why URL is repeated... + EXPECT_THAT(actual_report->query, + HasSubstr("src=https%3A%2F%2Fwww.chromium.org%2FHome")); + EXPECT_THAT(actual_report->query, + HasSubstr("full_url=https%3A%2F%2Fwww.chromium.org%2FHome")); + EXPECT_THAT(actual_report->query, HasSubstr("url=%2FHome")); + // This is from SetOsVersionForTesting(7, 20, 1) in SetUp(). + EXPECT_THAT(actual_report->query, HasSubstr("os_version=7.20.1")); + EXPECT_THAT(actual_report->query, HasSubstr("browser=Chrome")); + // These are from MockCrashEndpoint::Client::GetProductNameAndVersion, which + // is only defined for non-MAC POSIX systems. TODO(https://crbug.com/1121816): + // Get this info for non-POSIX platforms. +#if defined(OS_POSIX) && !defined(OS_MAC) + EXPECT_THAT(actual_report->query, HasSubstr("prod=Chrome_ChromeOS")); + EXPECT_THAT(actual_report->query, HasSubstr("ver=1.2.3.4")); + EXPECT_THAT(actual_report->query, HasSubstr("browser_version=1.2.3.4")); + EXPECT_THAT(actual_report->query, HasSubstr("channel=Stable")); +#endif + EXPECT_EQ(actual_report->content, ""); +} + +TEST_F(SendJavaScriptErrorReportTest, AllFields) { + JavaScriptErrorReport report; + report.message = "Hello World"; + report.url = "https://www.chromium.org/Home"; + report.product = "Unit test"; + report.version = "6.2.3.4"; + report.line_number = 83; + report.column_number = 14; + report.stack_trace = "bad_func(1, 2)\nonclick()\n"; + + SendJavaScriptErrorReport( + std::move(report), + base::BindOnce(&SendJavaScriptErrorReportTest::FinishCallback, + base::Unretained(this)), + &browser_context_); + run_loop_.Run(); + EXPECT_TRUE(finish_callback_was_called_); + + const base::Optional<MockCrashEndpoint::Report>& actual_report = + endpoint_->last_report(); + ASSERT_TRUE(actual_report); + EXPECT_THAT(actual_report->query, HasSubstr("error_message=Hello%20World")); + EXPECT_THAT(actual_report->query, HasSubstr("type=JavascriptError")); + // TODO(iby) research why URL is repeated... + EXPECT_THAT(actual_report->query, + HasSubstr("src=https%3A%2F%2Fwww.chromium.org%2FHome")); + EXPECT_THAT(actual_report->query, + HasSubstr("full_url=https%3A%2F%2Fwww.chromium.org%2FHome")); + EXPECT_THAT(actual_report->query, HasSubstr("url=%2FHome")); + // This is from SetOsVersionForTesting(7, 20, 1) in SetUp(). + EXPECT_THAT(actual_report->query, HasSubstr("os_version=7.20.1")); + EXPECT_THAT(actual_report->query, HasSubstr("browser=Chrome")); + // product is double-escaped. The first time, it transforms to Unit%20test, + // then the % is turned into %25. + EXPECT_THAT(actual_report->query, HasSubstr("prod=Unit%2520test")); + EXPECT_THAT(actual_report->query, HasSubstr("ver=6.2.3.4")); + EXPECT_THAT(actual_report->query, HasSubstr("line=83")); + EXPECT_THAT(actual_report->query, HasSubstr("column=14")); + // These are from MockCrashEndpoint::Client::GetProductNameAndVersion, which + // is only defined for non-MAC POSIX systems. TODO(https://crbug.com/1121816): + // Get this info for non-POSIX platforms. +#if defined(OS_POSIX) && !defined(OS_MAC) + EXPECT_THAT(actual_report->query, HasSubstr("browser_version=1.2.3.4")); + EXPECT_THAT(actual_report->query, HasSubstr("channel=Stable")); +#endif + EXPECT_EQ(actual_report->content, "bad_func(1, 2)\nonclick()\n"); +} + +TEST_F(SendJavaScriptErrorReportTest, NoConsent) { + endpoint_->set_consented(false); + JavaScriptErrorReport report; + report.message = "Hello World"; + report.url = "https://www.chromium.org/Home"; + + SendJavaScriptErrorReport( + std::move(report), + base::BindOnce(&SendJavaScriptErrorReportTest::FinishCallback, + base::Unretained(this)), + &browser_context_); + run_loop_.Run(); + EXPECT_TRUE(finish_callback_was_called_); + + EXPECT_FALSE(endpoint_->last_report()); +} + +TEST_F(SendJavaScriptErrorReportTest, StackTraceWithErrorMessage) { + JavaScriptErrorReport report; + report.message = "Hello World"; + report.url = "https://www.chromium.org/Home"; + report.stack_trace = "Hello World\nbad_func(1, 2)\nonclick()\n"; + + SendJavaScriptErrorReport( + std::move(report), + base::BindOnce(&SendJavaScriptErrorReportTest::FinishCallback, + base::Unretained(this)), + &browser_context_); + run_loop_.Run(); + EXPECT_TRUE(finish_callback_was_called_); + + const base::Optional<MockCrashEndpoint::Report>& actual_report = + endpoint_->last_report(); + ASSERT_TRUE(actual_report); + EXPECT_THAT(actual_report->query, HasSubstr("error_message=Hello%20World")); + EXPECT_EQ(actual_report->content, "bad_func(1, 2)\nonclick()\n"); +} + +TEST_F(SendJavaScriptErrorReportTest, RedactMessage) { + JavaScriptErrorReport report; + report.message = "alpha@beta.org says hi to gamma@omega.co.uk"; + report.url = "https://www.chromium.org/Home"; + report.stack_trace = + "alpha@beta.org says hi to gamma@omega.co.uk\n" + "bad_func(1, 2)\nonclick()\n"; + + SendJavaScriptErrorReport( + std::move(report), + base::BindOnce(&SendJavaScriptErrorReportTest::FinishCallback, + base::Unretained(this)), + &browser_context_); + run_loop_.Run(); + EXPECT_TRUE(finish_callback_was_called_); + + const base::Optional<MockCrashEndpoint::Report>& actual_report = + endpoint_->last_report(); + ASSERT_TRUE(actual_report); + // Escaped version of "<email: 1> says hi to <email: 2>" + EXPECT_THAT(actual_report->query, + HasSubstr("error_message=%3Cemail%3A%201%3E%20says%20hi%20to%20" + "%3Cemail%3A%202%3E")); + // Redacted messages still need to be removed from stack trace. + EXPECT_EQ(actual_report->content, "bad_func(1, 2)\nonclick()\n"); +} + +TEST_F(SendJavaScriptErrorReportTest, NonGoogleChrome) { + JavaScriptErrorReport report; + report.message = "Hello World"; + report.url = "https://www.chromium.org/Home"; + // We use a blank URL in non-GOOGLE_CHROME_BUILDs to avoid uploading reports + // from those browsers. + SetCrashEndpointForTesting(""); + + SendJavaScriptErrorReport( + std::move(report), + base::BindOnce(&SendJavaScriptErrorReportTest::FinishCallback, + base::Unretained(this)), + &browser_context_); + run_loop_.Run(); + EXPECT_TRUE(finish_callback_was_called_); + + const base::Optional<MockCrashEndpoint::Report>& actual_report = + endpoint_->last_report(); + EXPECT_FALSE(actual_report); +}
diff --git a/components/exo/drag_drop_operation.cc b/components/exo/drag_drop_operation.cc index 5224320..bd95b7d 100644 --- a/components/exo/drag_drop_operation.cc +++ b/components/exo/drag_drop_operation.cc
@@ -17,6 +17,9 @@ #include "ui/base/dragdrop/os_exchange_data.h" #include "ui/display/display.h" #include "ui/display/screen.h" +#include "ui/gfx/geometry/point.h" +#include "ui/gfx/geometry/point_conversions.h" +#include "ui/gfx/geometry/point_f.h" #include "ui/gfx/transform_util.h" #if defined(OS_CHROMEOS) @@ -79,7 +82,7 @@ DataSource* source, Surface* origin, Surface* icon, - const gfx::Point& drag_start_point, + const gfx::PointF& drag_start_point, ui::mojom::DragEventSource event_source) { auto* dnd_op = new DragDropOperation(source, origin, icon, drag_start_point, event_source); @@ -89,7 +92,7 @@ DragDropOperation::DragDropOperation(DataSource* source, Surface* origin, Surface* icon, - const gfx::Point& drag_start_point, + const gfx::PointF& drag_start_point, ui::mojom::DragEventSource event_source) : SurfaceTreeHost("ExoDragDropOperation"), source_(std::make_unique<ScopedDataSource>(source, this)), @@ -242,11 +245,13 @@ base::WeakPtr<DragDropOperation> weak_ptr = weak_ptr_factory_.GetWeakPtr(); started_by_this_object_ = true; + gfx::Point drag_start_point = gfx::ToFlooredPoint(drag_start_point_); + // This triggers a nested run loop that terminates when the drag and drop // operation is completed. int op = drag_drop_controller_->StartDragAndDrop( std::move(os_exchange_data_), origin_->get()->window()->GetRootWindow(), - origin_->get()->window(), drag_start_point_, dnd_operations, + origin_->get()->window(), drag_start_point, dnd_operations, event_source_); // The instance deleted during StartDragAndDrop's nested RunLoop.
diff --git a/components/exo/drag_drop_operation.h b/components/exo/drag_drop_operation.h index 436cec3..cf6da01 100644 --- a/components/exo/drag_drop_operation.h +++ b/components/exo/drag_drop_operation.h
@@ -13,6 +13,7 @@ #include "components/exo/wm_helper.h" #include "ui/aura/client/drag_drop_client_observer.h" #include "ui/base/dragdrop/mojom/drag_drop_types.mojom-forward.h" +#include "ui/gfx/geometry/point_f.h" namespace ash { class DragDropController; @@ -50,7 +51,7 @@ DataSource* source, Surface* origin, Surface* icon, - const gfx::Point& drag_start_point, + const gfx::PointF& drag_start_point, ui::mojom::DragEventSource event_source); // Abort the operation if it hasn't been started yet, otherwise do nothing. @@ -78,7 +79,7 @@ DragDropOperation(DataSource* source, Surface* origin, Surface* icon, - const gfx::Point& drag_start_point, + const gfx::PointF& drag_start_point, ui::mojom::DragEventSource event_source); ~DragDropOperation() override; @@ -97,7 +98,7 @@ std::unique_ptr<ScopedDataSource> source_; std::unique_ptr<ScopedSurface> icon_; std::unique_ptr<ScopedSurface> origin_; - gfx::Point drag_start_point_; + gfx::PointF drag_start_point_; std::unique_ptr<ui::OSExchangeData> os_exchange_data_; #if defined(OS_CHROMEOS) ash::DragDropController* drag_drop_controller_;
diff --git a/components/exo/drag_drop_operation_unittest.cc b/components/exo/drag_drop_operation_unittest.cc index 4cccc4c..e0e30b8 100644 --- a/components/exo/drag_drop_operation_unittest.cc +++ b/components/exo/drag_drop_operation_unittest.cc
@@ -17,6 +17,7 @@ #include "components/exo/test/exo_test_base.h" #include "ui/aura/client/drag_drop_client.h" #include "ui/base/dragdrop/mojom/drag_drop_types.mojom-shared.h" +#include "ui/gfx/geometry/point_f.h" namespace exo { namespace { @@ -103,8 +104,8 @@ icon_surface->Attach(buffer.get()); auto operation = DragDropOperation::Create( - data_source.get(), origin_surface.get(), icon_surface.get(), gfx::Point(), - ui::mojom::DragEventSource::kMouse); + data_source.get(), origin_surface.get(), icon_surface.get(), + gfx::PointF(), ui::mojom::DragEventSource::kMouse); icon_surface->Commit(); base::RunLoop run_loop;
diff --git a/components/exo/pointer.cc b/components/exo/pointer.cc index f66f306e..6c446e3 100644 --- a/components/exo/pointer.cc +++ b/components/exo/pointer.cc
@@ -346,7 +346,7 @@ if (event->type() == ui::ET_MOUSE_CAPTURE_CHANGED) return; - seat_->SetLastLocation(event->root_location()); + seat_->SetLastPointerLocation(event->root_location_f()); Surface* target = GetEffectiveTargetForEvent(event); gfx::PointF location_in_target = event->location_f();
diff --git a/components/exo/seat.cc b/components/exo/seat.cc index 209c3fef..c7881a30 100644 --- a/components/exo/seat.cc +++ b/components/exo/seat.cc
@@ -5,6 +5,7 @@ #include "components/exo/seat.h" #include <memory> +#include "ui/gfx/geometry/point_f.h" #if defined(OS_CHROMEOS) #include "ash/shell.h" @@ -98,11 +99,11 @@ ui::mojom::DragEventSource event_source) { // DragDropOperation manages its own lifetime. drag_drop_operation_ = DragDropOperation::Create( - source, origin, icon, last_location_, event_source); + source, origin, icon, last_pointer_location_, event_source); } -void Seat::SetLastLocation(const gfx::Point& last_location) { - last_location_ = last_location; +void Seat::SetLastPointerLocation(const gfx::PointF& last_pointer_location) { + last_pointer_location_ = last_pointer_location; } void Seat::AbortPendingDragOperation() {
diff --git a/components/exo/seat.h b/components/exo/seat.h index 32ca40c9..2a6940e5 100644 --- a/components/exo/seat.h +++ b/components/exo/seat.h
@@ -80,7 +80,7 @@ // Sets the last location in screen coordinates, irrespective of mouse or // touch. - void SetLastLocation(const gfx::Point& last_location); + void SetLastPointerLocation(const gfx::PointF& last_pointer_location); // Abort any drag operations that haven't been started yet. void AbortPendingDragOperation(); @@ -159,7 +159,7 @@ // True while Seat is updating clipboard data to selection source. bool changing_clipboard_data_to_selection_source_; - gfx::Point last_location_; + gfx::PointF last_pointer_location_; bool shutdown_ = false;
diff --git a/components/exo/shell_surface.cc b/components/exo/shell_surface.cc index 1be1612..6c14def 100644 --- a/components/exo/shell_surface.cc +++ b/components/exo/shell_surface.cc
@@ -6,6 +6,7 @@ #include "ash/public/cpp/shell_window_ids.h" #include "ash/public/cpp/window_state_type.h" +#include "ash/scoped_animation_disabler.h" #include "ash/shell.h" #include "ash/wm/desks/desks_util.h" #include "ash/wm/toplevel_window_event_handler.h" @@ -37,43 +38,6 @@ } // namespace //////////////////////////////////////////////////////////////////////////////// -// ShellSurface, ScopedAnimationsDisabled: - -// Helper class used to temporarily disable animations. Restores the -// animations disabled property when instance is destroyed. -class ShellSurface::ScopedAnimationsDisabled { - public: - explicit ScopedAnimationsDisabled(ShellSurface* shell_surface); - ~ScopedAnimationsDisabled(); - - private: - ShellSurface* const shell_surface_; - bool saved_animations_disabled_ = false; - - DISALLOW_COPY_AND_ASSIGN(ScopedAnimationsDisabled); -}; - -ShellSurface::ScopedAnimationsDisabled::ScopedAnimationsDisabled( - ShellSurface* shell_surface) - : shell_surface_(shell_surface) { - if (shell_surface_->widget_) { - aura::Window* window = shell_surface_->widget_->GetNativeWindow(); - saved_animations_disabled_ = - window->GetProperty(aura::client::kAnimationsDisabledKey); - window->SetProperty(aura::client::kAnimationsDisabledKey, true); - } -} - -ShellSurface::ScopedAnimationsDisabled::~ScopedAnimationsDisabled() { - if (shell_surface_->widget_) { - aura::Window* window = shell_surface_->widget_->GetNativeWindow(); - DCHECK_EQ(window->GetProperty(aura::client::kAnimationsDisabledKey), true); - window->SetProperty(aura::client::kAnimationsDisabledKey, - saved_animations_disabled_); - } -} - -//////////////////////////////////////////////////////////////////////////////// // ShellSurface, Config: // Surface state associated with each configure request. @@ -448,8 +412,8 @@ nullptr, base::TimeDelta::FromMilliseconds( kMaximizedOrFullscreenOrPinnedLockTimeoutMs)); } else { - scoped_animations_disabled_ = - std::make_unique<ScopedAnimationsDisabled>(this); + animations_disabler_ = std::make_unique<ash::ScopedAnimationDisabler>( + widget_->GetNativeWindow()); } } } @@ -467,7 +431,7 @@ } // Re-enable animations if they were disabled in pre state change handler. - scoped_animations_disabled_.reset(); + animations_disabler_.reset(); } ////////////////////////////////////////////////////////////////////////////////
diff --git a/components/exo/shell_surface.h b/components/exo/shell_surface.h index bbaeb51..c04db233 100644 --- a/components/exo/shell_surface.h +++ b/components/exo/shell_surface.h
@@ -12,6 +12,10 @@ #include "components/exo/shell_surface_base.h" #include "ui/base/ui_base_types.h" +namespace ash { +class ScopedAnimationDisabler; +} // namespace ash + namespace ui { class CompositorLock; } // namespace ui @@ -122,7 +126,6 @@ bool OnPreWidgetCommit() override; private: - class ScopedAnimationsDisabled; struct Config; // Helper class used to coalesce a number of changes into one "configure" @@ -161,7 +164,7 @@ void EndDrag(); - std::unique_ptr<ScopedAnimationsDisabled> scoped_animations_disabled_; + std::unique_ptr<ash::ScopedAnimationDisabler> animations_disabler_; std::unique_ptr<ui::CompositorLock> configure_compositor_lock_; ConfigureCallback configure_callback_;
diff --git a/components/exo/touch.cc b/components/exo/touch.cc index c1dc6b3..e5174f4 100644 --- a/components/exo/touch.cc +++ b/components/exo/touch.cc
@@ -60,7 +60,7 @@ // ui::EventHandler overrides: void Touch::OnTouchEvent(ui::TouchEvent* event) { - seat_->SetLastLocation(event->root_location()); + seat_->SetLastPointerLocation(event->root_location_f()); bool send_details = false;
diff --git a/components/favicon/core/favicon_handler_unittest.cc b/components/favicon/core/favicon_handler_unittest.cc index d87b86dc..94bb249 100644 --- a/components/favicon/core/favicon_handler_unittest.cc +++ b/components/favicon/core/favicon_handler_unittest.cc
@@ -13,7 +13,6 @@ #include "base/bind.h" #include "base/bind_helpers.h" -#include "base/macros.h" #include "base/run_loop.h" #include "base/strings/stringprintf.h" #include "base/test/metrics/histogram_tester.h" @@ -129,8 +128,9 @@ }; // |downloads| must not be nullptr and must outlive this object. - explicit FakeImageDownloader(URLVector* downloads) - : downloads_(downloads), next_download_id_(1) {} + explicit FakeImageDownloader(URLVector* downloads) : downloads_(downloads) {} + FakeImageDownloader(const FakeImageDownloader&) = delete; + FakeImageDownloader& operator=(const FakeImageDownloader&) = delete; // Implementation of FaviconHalder::Delegate's DownloadImage(). If a given // URL is not known (i.e. not previously added via Add()), it produces 404s. @@ -204,7 +204,7 @@ private: URLVector* downloads_; - int next_download_id_; + int next_download_id_ = 1; // URL to disable automatic callbacks for. GURL manual_callback_url_; @@ -214,8 +214,6 @@ // Registered responses. std::map<GURL, Response> responses_; - - DISALLOW_COPY_AND_ASSIGN(FakeImageDownloader); }; // Fake that implements the calls to FaviconHandler::Delegate's @@ -229,6 +227,8 @@ // |downloads| must not be nullptr and must outlive this object. explicit FakeManifestDownloader(URLVector* downloads) : downloads_(downloads) {} + FakeManifestDownloader(const FakeManifestDownloader&) = delete; + FakeManifestDownloader& operator=(const FakeManifestDownloader&) = delete; // Implementation of FaviconHalder::Delegate's DownloadManifest(). If a given // URL is not known (i.e. not previously added via Add()), it produces 404s. @@ -267,7 +267,7 @@ // Returns whether an ongoing download exists for a url previously selected // via SetRunCallbackManuallyForUrl(). - bool HasPendingManualCallback() { return !manual_callbacks_.empty(); } + bool HasPendingManualCallback() const { return !manual_callbacks_.empty(); } // Triggers responses for downloads previously selected for manual triggering // via SetRunCallbackManuallyForUrl(). @@ -290,8 +290,6 @@ // Registered responses. std::map<GURL, Response> responses_; - - DISALLOW_COPY_AND_ASSIGN(FakeManifestDownloader); }; class MockDelegate : public FaviconHandler::Delegate { @@ -352,6 +350,8 @@ public: FakeFaviconService() : manual_callback_task_runner_(new base::TestSimpleTaskRunner()) {} + FakeFaviconService(const FakeFaviconService&) = delete; + FakeFaviconService& operator=(const FakeFaviconService&) = delete; // Stores favicon with bitmap data in |results| at |page_url| and |icon_url|. void Store(const GURL& page_url, @@ -452,8 +452,6 @@ // Callback for GetFaviconForPageOrIconURL() request for // |manual_callback_url_|. scoped_refptr<base::TestSimpleTaskRunner> manual_callback_task_runner_; - - DISALLOW_COPY_AND_ASSIGN(FakeFaviconService); }; // MockFaviconService subclass that delegates DB reads to FakeFaviconService. @@ -470,13 +468,14 @@ .WillByDefault( Invoke(&fake_, &FakeFaviconService::UpdateFaviconMappingsAndFetch)); } + MockFaviconServiceWithFake(const MockFaviconServiceWithFake&) = delete; + MockFaviconServiceWithFake& operator=(const MockFaviconServiceWithFake&) = + delete; FakeFaviconService* fake() { return &fake_; } private: FakeFaviconService fake_; - - DISALLOW_COPY_AND_ASSIGN(MockFaviconServiceWithFake); }; class FaviconHandlerTest : public testing::Test { @@ -1822,6 +1821,13 @@ FaviconHandlerManifestsEnabledTest() = default; + public: + FaviconHandlerManifestsEnabledTest( + const FaviconHandlerManifestsEnabledTest&) = delete; + FaviconHandlerManifestsEnabledTest& operator=( + const FaviconHandlerManifestsEnabledTest&) = delete; + + protected: // Exercises the handler for the simplest case where all types are kTouchIcon // and no sizes are provided, using a FaviconHandler of type TOUCH_LARGETS. std::unique_ptr<FaviconHandler> RunHandlerWithSimpleTouchIconCandidates( @@ -1839,8 +1845,6 @@ // Avoid accidental use of kFavicon type, since Web Manifests are handled by // the FaviconHandler of type TOUCH_LARGEST. using FaviconHandlerTest::RunHandlerWithSimpleFaviconCandidates; - - DISALLOW_COPY_AND_ASSIGN(FaviconHandlerManifestsEnabledTest); }; // Test that favicon mappings are deleted when a manifest previously cached in
diff --git a/components/feed/core/v2/feed_stream.cc b/components/feed/core/v2/feed_stream.cc index 58f773e..7bd5bc07 100644 --- a/components/feed/core/v2/feed_stream.cc +++ b/components/feed/core/v2/feed_stream.cc
@@ -627,10 +627,14 @@ delegate_->ClearAll(); } -void FeedStream::FetchImage( +ImageFetchId FeedStream::FetchImage( const GURL& url, base::OnceCallback<void(NetworkResponse)> callback) { - image_fetcher_->Fetch(url, std::move(callback)); + return image_fetcher_->Fetch(url, std::move(callback)); +} + +void FeedStream::CancelImageFetch(ImageFetchId id) { + image_fetcher_->Cancel(id); } void FeedStream::UploadAction(
diff --git a/components/feed/core/v2/feed_stream.h b/components/feed/core/v2/feed_stream.h index 59390e3..b3c2690 100644 --- a/components/feed/core/v2/feed_stream.h +++ b/components/feed/core/v2/feed_stream.h
@@ -129,8 +129,10 @@ bool IsArticlesListVisible() override; std::string GetClientInstanceId() override; void ExecuteRefreshTask() override; - void FetchImage(const GURL& url, - base::OnceCallback<void(NetworkResponse)> callback) override; + ImageFetchId FetchImage( + const GURL& url, + base::OnceCallback<void(NetworkResponse)> callback) override; + void CancelImageFetch(ImageFetchId id) override; void LoadMore(SurfaceId surface_id, base::OnceCallback<void(bool)> callback) override; void ExecuteOperations(
diff --git a/components/feed/core/v2/feed_stream_unittest.cc b/components/feed/core/v2/feed_stream_unittest.cc index 9439fd7..96fc8a13 100644 --- a/components/feed/core/v2/feed_stream_unittest.cc +++ b/components/feed/core/v2/feed_stream_unittest.cc
@@ -264,12 +264,18 @@ explicit TestImageFetcher( scoped_refptr<::network::SharedURLLoaderFactory> url_loader_factory) : ImageFetcher(url_loader_factory) {} - void Fetch(const GURL& url, - base::OnceCallback<void(NetworkResponse)> callback) override { + ImageFetchId Fetch( + const GURL& url, + base::OnceCallback<void(NetworkResponse)> callback) override { // Emulate a response. NetworkResponse response = {"dummyresponse", 200}; std::move(callback).Run(std::move(response)); + return id_generator_.GenerateNextId(); } + void Cancel(ImageFetchId id) override {} + + private: + ImageFetchId::Generator id_generator_; }; class TestFeedNetwork : public FeedNetwork {
diff --git a/components/feed/core/v2/image_fetcher.cc b/components/feed/core/v2/image_fetcher.cc index 6315070..49c4bc60 100644 --- a/components/feed/core/v2/image_fetcher.cc +++ b/components/feed/core/v2/image_fetcher.cc
@@ -6,6 +6,7 @@ #include "components/feed/core/v2/metrics_reporter.h" #include "components/feed/core/v2/public/types.h" +#include "net/base/net_errors.h" #include "net/http/http_request_headers.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/cpp/simple_url_loader.h" @@ -18,7 +19,7 @@ ImageFetcher::~ImageFetcher() = default; -void ImageFetcher::Fetch(const GURL& url, ImageCallback callback) { +ImageFetchId ImageFetcher::Fetch(const GURL& url, ImageCallback callback) { net::NetworkTrafficAnnotationTag traffic_annotation = net::DefineNetworkTrafficAnnotation("interest_feedv2_image_send", R"( semantics { @@ -48,29 +49,73 @@ auto simple_loader = network::SimpleURLLoader::Create( std::move(resource_request), traffic_annotation); auto* const simple_loader_ptr = simple_loader.get(); + + ImageFetchId id = id_generator_.GenerateNextId(); + bool inserted = + pending_requests_ + .try_emplace(id, std::move(simple_loader), std::move(callback)) + .second; + DCHECK(inserted); + simple_loader_ptr->DownloadToString( url_loader_factory_.get(), base::BindOnce(&ImageFetcher::OnFetchComplete, weak_factory_.GetWeakPtr(), - std::move(simple_loader), std::move(callback)), + id), network::SimpleURLLoader::kMaxBoundedStringDownloadSize); + return id; } -void ImageFetcher::OnFetchComplete( - std::unique_ptr<network::SimpleURLLoader> simple_loader, - ImageCallback callback, - std::unique_ptr<std::string> response_data) { - MetricsReporter::OnImageFetched( - response_data ? simple_loader->ResponseInfo()->headers->response_code() - : simple_loader->NetError()); - NetworkResponse response{std::string(), simple_loader->NetError()}; - if (simple_loader->ResponseInfo() && simple_loader->ResponseInfo()->headers) { +void ImageFetcher::OnFetchComplete(ImageFetchId id, + std::unique_ptr<std::string> response_data) { + base::Optional<PendingRequest> request = RemovePending(id); + if (!request) + return; + + NetworkResponse response; + if (request->loader->ResponseInfo() && + request->loader->ResponseInfo()->headers) { response.status_code = - simple_loader->ResponseInfo()->headers->response_code(); + request->loader->ResponseInfo()->headers->response_code(); + } else { + response.status_code = request->loader->NetError(); } + MetricsReporter::OnImageFetched(response.status_code); if (response_data) response.response_bytes = std::move(*response_data); - std::move(callback).Run(std::move(response)); + std::move(request->callback).Run(std::move(response)); } +void ImageFetcher::Cancel(ImageFetchId id) { + base::Optional<PendingRequest> request = RemovePending(id); + if (!request) + return; + + // Cancel the fetch before running the callback. + request->loader.reset(); + std::move(request->callback) + .Run({/*response_bytes=*/std::string(), net::Error::ERR_ABORTED}); +} + +base::Optional<ImageFetcher::PendingRequest> ImageFetcher::RemovePending( + ImageFetchId id) { + auto iterator = pending_requests_.find(id); + if (iterator == pending_requests_.end()) + return base::nullopt; + + auto request = base::make_optional(std::move(iterator->second)); + pending_requests_.erase(iterator); + return request; +} + +ImageFetcher::PendingRequest::PendingRequest( + std::unique_ptr<network::SimpleURLLoader> loader, + ImageCallback callback) + : loader(std::move(loader)), callback(std::move(callback)) {} +ImageFetcher::PendingRequest::PendingRequest( + ImageFetcher::PendingRequest&& other) = default; +ImageFetcher::PendingRequest& ImageFetcher::PendingRequest::operator=( + ImageFetcher::PendingRequest&& other) = default; +ImageFetcher::PendingRequest::~PendingRequest() = default; + } // namespace feed
diff --git a/components/feed/core/v2/image_fetcher.h b/components/feed/core/v2/image_fetcher.h index e1fa77a..0d333321 100644 --- a/components/feed/core/v2/image_fetcher.h +++ b/components/feed/core/v2/image_fetcher.h
@@ -6,8 +6,11 @@ #define COMPONENTS_FEED_CORE_V2_IMAGE_FETCHER_H_ #include "base/callback.h" +#include "base/containers/flat_map.h" #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" +#include "base/optional.h" +#include "components/feed/core/v2/public/types.h" #include "url/gurl.h" namespace network { @@ -29,14 +32,29 @@ ImageFetcher(const ImageFetcher&) = delete; ImageFetcher& operator=(const ImageFetcher&) = delete; - virtual void Fetch(const GURL& url, ImageCallback callback); + virtual ImageFetchId Fetch(const GURL& url, ImageCallback callback); + virtual void Cancel(ImageFetchId id); private: + struct PendingRequest { + PendingRequest(std::unique_ptr<network::SimpleURLLoader> loader, + ImageCallback callback); + PendingRequest(PendingRequest&& other); + PendingRequest& operator=(PendingRequest&& other); + ~PendingRequest(); + + std::unique_ptr<network::SimpleURLLoader> loader; + ImageCallback callback; + }; + // Called when fetch request completes. - void OnFetchComplete(std::unique_ptr<network::SimpleURLLoader> simple_loader, - ImageCallback callback, + void OnFetchComplete(ImageFetchId id, std::unique_ptr<std::string> response_data); + base::Optional<PendingRequest> RemovePending(ImageFetchId id); + + ImageFetchId::Generator id_generator_; + base::flat_map<ImageFetchId, PendingRequest> pending_requests_; const scoped_refptr<::network::SharedURLLoaderFactory> url_loader_factory_; base::WeakPtrFactory<ImageFetcher> weak_factory_{this}; };
diff --git a/components/feed/core/v2/image_fetcher_unittest.cc b/components/feed/core/v2/image_fetcher_unittest.cc index 22be032..ba2dbe4 100644 --- a/components/feed/core/v2/image_fetcher_unittest.cc +++ b/components/feed/core/v2/image_fetcher_unittest.cc
@@ -151,5 +151,39 @@ HasSubstr("example2_response")); } +TEST_F(ImageFetcherTest, CancelRunsCallback) { + CallbackReceiver<NetworkResponse> receiver; + ImageFetchId id = + image_fetcher()->Fetch(GURL("https://example.com"), receiver.Bind()); + + image_fetcher()->Cancel(id); + ASSERT_TRUE(receiver.GetResult()); + EXPECT_EQ(std::string(), receiver.GetResult()->response_bytes); + EXPECT_EQ(net::Error::ERR_ABORTED, receiver.GetResult()->status_code); +} + +TEST_F(ImageFetcherTest, CancelThenRespond) { + CallbackReceiver<NetworkResponse> receiver; + ImageFetchId id = + image_fetcher()->Fetch(GURL("https://example.com"), receiver.Bind()); + + image_fetcher()->Cancel(id); + Respond("example1_response", net::HTTP_OK); + ASSERT_TRUE(receiver.GetResult()); + EXPECT_EQ(std::string(), receiver.GetResult()->response_bytes); + EXPECT_EQ(net::Error::ERR_ABORTED, receiver.GetResult()->status_code); +} + +TEST_F(ImageFetcherTest, CallbackCallsCancel) { + // Ensure nothing terrible happens if cancel is called from the callback. + ImageFetchId id; + id = image_fetcher()->Fetch( + GURL("https://example.com"), + base::BindLambdaForTesting( + [&](NetworkResponse response) { image_fetcher()->Cancel(id); })); + + image_fetcher()->Cancel(id); +} + } // namespace } // namespace feed
diff --git a/components/feed/core/v2/public/feed_stream_api.h b/components/feed/core/v2/public/feed_stream_api.h index d2adbda..d3bfabc3 100644 --- a/components/feed/core/v2/public/feed_stream_api.h +++ b/components/feed/core/v2/public/feed_stream_api.h
@@ -78,10 +78,15 @@ base::OnceCallback<void(bool)> callback) = 0; // Request to fetch and image for use in the feed. Calls |callback| - // with the network response when complete. - virtual void FetchImage( + // with the network response when complete. The returned ImageFetchId can be + // passed to CancelImageFetch() to cancel the request. + virtual ImageFetchId FetchImage( const GURL& url, base::OnceCallback<void(NetworkResponse)> callback) = 0; + // If |id| matches an active fetch, cancels the fetch and runs the callback + // with an empty response body and status_code=net::Error::ERR_ABORTED. If + // |id| doesn't match an active fetch, nothing happens. + virtual void CancelImageFetch(ImageFetchId id) = 0; // Apply |operations| to the stream model. Does nothing if the model is not // yet loaded.
diff --git a/components/feed/core/v2/public/types.h b/components/feed/core/v2/public/types.h index 64fa531..7680ef7 100644 --- a/components/feed/core/v2/public/types.h +++ b/components/feed/core/v2/public/types.h
@@ -32,6 +32,7 @@ // A unique ID for an ephemeral change. using EphemeralChangeId = util::IdTypeU32<class EphemeralChangeIdClass>; using SurfaceId = util::IdTypeU32<class SurfaceIdClass>; +using ImageFetchId = util::IdTypeU32<class ImageFetchIdClass>; struct NetworkResponseInfo { NetworkResponseInfo(); @@ -55,6 +56,7 @@ // HTTP status code if available, or net::Error otherwise. int status_code; + NetworkResponse() = default; NetworkResponse(NetworkResponse&& other) = default; NetworkResponse& operator=(NetworkResponse&& other) = default; };
diff --git a/components/history/core/browser/history_backend_unittest.cc b/components/history/core/browser/history_backend_unittest.cc index d613929..dcdedf72 100644 --- a/components/history/core/browser/history_backend_unittest.cc +++ b/components/history/core/browser/history_backend_unittest.cc
@@ -127,6 +127,9 @@ public: explicit HistoryBackendTestDelegate(HistoryBackendTestBase* test) : test_(test) {} + HistoryBackendTestDelegate(const HistoryBackendTestDelegate&) = delete; + HistoryBackendTestDelegate& operator=(const HistoryBackendTestDelegate&) = + delete; void NotifyProfileError(sql::InitStatus init_status, const std::string& diagnostics) override {} @@ -149,8 +152,6 @@ private: // Not owned by us. HistoryBackendTestBase* test_; - - DISALLOW_COPY_AND_ASSIGN(HistoryBackendTestDelegate); }; class HistoryBackendTestBase : public testing::Test { @@ -159,10 +160,10 @@ typedef std::vector<URLRows> URLsModifiedList; typedef std::vector<std::pair<bool, bool>> URLsDeletedList; - HistoryBackendTestBase() - : loaded_(false) {} - - ~HistoryBackendTestBase() override {} + HistoryBackendTestBase() = default; + HistoryBackendTestBase(const HistoryBackendTestBase&) = delete; + HistoryBackendTestBase& operator=(const HistoryBackendTestBase&) = delete; + ~HistoryBackendTestBase() override = default; protected: std::vector<GURL> favicon_changed_notifications_page_urls() const { @@ -247,7 +248,7 @@ history::HistoryClientFakeBookmarks history_client_; scoped_refptr<HistoryBackend> backend_; // Will be NULL on init failure. std::unique_ptr<InMemoryHistoryBackend> mem_backend_; - bool loaded_; + bool loaded_ = false; private: friend class HistoryBackendTestDelegate; @@ -286,8 +287,6 @@ URLsDeletedList urls_deleted_notifications_; base::FilePath test_dir_; - - DISALLOW_COPY_AND_ASSIGN(HistoryBackendTestBase); }; void HistoryBackendTestDelegate::SetInMemoryBackend( @@ -334,8 +333,10 @@ class HistoryBackendTest : public HistoryBackendTestBase { public: - HistoryBackendTest() {} - ~HistoryBackendTest() override {} + HistoryBackendTest() = default; + HistoryBackendTest(const HistoryBackendTest&) = delete; + HistoryBackendTest& operator=(const HistoryBackendTest&) = delete; + ~HistoryBackendTest() override = default; protected: favicon::FaviconDatabase* favicon_db() { @@ -469,15 +470,15 @@ bitmap_data->size() == 1u && *bitmap_data->front() == expected_data; } - - private: - DISALLOW_COPY_AND_ASSIGN(HistoryBackendTest); }; class InMemoryHistoryBackendTest : public HistoryBackendTestBase { public: - InMemoryHistoryBackendTest() {} - ~InMemoryHistoryBackendTest() override {} + InMemoryHistoryBackendTest() = default; + InMemoryHistoryBackendTest(const InMemoryHistoryBackendTest&) = delete; + InMemoryHistoryBackendTest& operator=(const InMemoryHistoryBackendTest&) = + delete; + ~InMemoryHistoryBackendTest() override = default; protected: void SimulateNotificationURLsDeleted(const URLRow* row1, @@ -539,9 +540,6 @@ static const KeywordID kTestKeywordId; static const char kTestSearchTerm1[]; static const char kTestSearchTerm2[]; - - private: - DISALLOW_COPY_AND_ASSIGN(InMemoryHistoryBackendTest); }; const KeywordID InMemoryHistoryBackendTest::kTestKeywordId = 42;
diff --git a/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc b/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc index 1281360..c0bd6c4 100644 --- a/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc +++ b/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc
@@ -15,7 +15,6 @@ #include "base/command_line.h" #include "base/i18n/rtl.h" #include "base/json/json_reader.h" -#include "base/macros.h" #include "base/run_loop.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" @@ -266,6 +265,10 @@ RequestThrottler::RegisterProfilePrefs(utils_.pref_service()->registry()); } + RemoteSuggestionsProviderImplTest(const RemoteSuggestionsProviderImplTest&) = + delete; + RemoteSuggestionsProviderImplTest& operator=( + const RemoteSuggestionsProviderImplTest&) = delete; ~RemoteSuggestionsProviderImplTest() override { provider_.reset(); observer_.reset(); @@ -609,8 +612,6 @@ FakeDB<SnippetImageProto>* image_db_; scoped_refptr<TestMockTimeTaskRunner> timer_mock_task_runner_; - - DISALLOW_COPY_AND_ASSIGN(RemoteSuggestionsProviderImplTest); }; TEST_F(RemoteSuggestionsProviderImplTest, Full) {
diff --git a/components/omnibox/browser/autocomplete_result.cc b/components/omnibox/browser/autocomplete_result.cc index 2a5e338..6967a42 100644 --- a/components/omnibox/browser/autocomplete_result.cc +++ b/components/omnibox/browser/autocomplete_result.cc
@@ -222,7 +222,7 @@ DeduplicateMatches(&matches_); - // Sort the matches. + // Sort the matches by relevance and demotions. std::sort(matches_.begin(), matches_.end(), comparing_object); // Find the best match and rotate it to the front to become the default match. @@ -270,6 +270,7 @@ CalculateNumMatches(is_zero_suggest, matches_, comparing_object); matches_.resize(num_matches); + // Group search suggestions above URL suggestions. #if defined(OS_ANDROID) if (matches_.size() > 2 && !base::FeatureList::IsEnabled(omnibox::kAdaptiveSuggestionsCount)) { @@ -282,11 +283,13 @@ matches_.front().type)) { while (next != matches_.end() && (AutocompleteMatch::ShouldBeSkippedForGroupBySearchVsUrl( - matches_.front().type))) { + next->type))) { next = std::next(next); } } - GroupSuggestionsBySearchVsURL(next, matches_.end()); + auto begin_url = GroupSuggestionsBySearchVsURL(next, matches_.end()); + if (base::FeatureList::IsEnabled(omnibox::kBubbleUrlSuggestions)) + BubbleURLSuggestions(next, begin_url, matches_); } // If we have a default match, run some sanity checks. Skip these checks if @@ -1012,9 +1015,60 @@ } // static -void AutocompleteResult::GroupSuggestionsBySearchVsURL(iterator begin, - iterator end) { - std::stable_partition(begin, end, [](const AutocompleteMatch& match) { - return match.IsSearchType(match.type); +AutocompleteResult::iterator AutocompleteResult::GroupSuggestionsBySearchVsURL( + iterator begin, + iterator end) { + return std::stable_partition(begin, end, [](const AutocompleteMatch& match) { + return AutocompleteMatch::IsSearchType(match.type); }); } + +// static +void AutocompleteResult::BubbleURLSuggestions(iterator begin_search, + iterator begin_url, + ACMatches& matches) { + auto absolute_gap = base::GetFieldTrialParamByFeatureAsInt( + omnibox::kBubbleUrlSuggestions, + OmniboxFieldTrial::kBubbleUrlSuggestionsAbsoluteGapParam, 200); + auto relative_gap = base::GetFieldTrialParamByFeatureAsDouble( + omnibox::kBubbleUrlSuggestions, + OmniboxFieldTrial::kBubbleUrlSuggestionsRelativeGapParam, 1); + auto absolute_buffer = base::GetFieldTrialParamByFeatureAsInt( + omnibox::kBubbleUrlSuggestions, + OmniboxFieldTrial::kBubbleUrlSuggestionsAbsoluteBufferParam, 100); + auto relative_buffer = base::GetFieldTrialParamByFeatureAsDouble( + omnibox::kBubbleUrlSuggestions, + OmniboxFieldTrial::kBubbleUrlSuggestionsRelativeBufferParam, 1); + + // |next_url| tracks the first (i.e. highest scoring) yet unbubbled URL + // suggestion. + auto next_url = begin_url; + + for (auto next_search = begin_search; + next_search != next_url && next_url != matches.end(); + next_search = std::next(next_search)) { + // Only bubble if there's a sufficient score gap between adjacent searches. + if (next_search != begin_search && + std::prev(next_search)->relevance < + std::max(next_search->relevance + absolute_gap * 1., + next_search->relevance * relative_gap)) + continue; + // Only bubble if there's a sufficient buffer between the URL and search. + if (next_url->relevance < + std::max(next_search->relevance + absolute_buffer * 1., + next_search->relevance * relative_buffer)) + continue; + + // Find the series of URLs to bubble: [next_url, last_bubble_url). + // Although |next_url| must score higher than the |next_search| by at least + // the buffer amount, the remaining URls in the series need to score only + // as high as |next_search|. + auto last_bubble_url = std::find_if( + std::next(next_url), matches.end(), + [&](auto& match) { return match.relevance < next_search->relevance; }); + + // Bubble [next_url, last_bubble_url) above |next_search|. + next_search = std::rotate(next_search, next_url, last_bubble_url); + next_url = last_bubble_url; + } +}
diff --git a/components/omnibox/browser/autocomplete_result.h b/components/omnibox/browser/autocomplete_result.h index b23112b..6f24875 100644 --- a/components/omnibox/browser/autocomplete_result.h +++ b/components/omnibox/browser/autocomplete_result.h
@@ -217,6 +217,7 @@ TestGroupSuggestionsBySearchVsURL); FRIEND_TEST_ALL_PREFIXES(AutocompleteResultTest, DemoteOnDeviceSearchSuggestions); + FRIEND_TEST_ALL_PREFIXES(AutocompleteResultTest, BubbleURLSuggestions); friend class HistoryURLProviderTest; typedef std::map<AutocompleteProvider*, ACMatches> ProviderToMatches; @@ -277,7 +278,17 @@ // search types, and their submatches regardless of type, are shifted // earlier in the range, while non-search types and their submatches // are shifted later. - static void GroupSuggestionsBySearchVsURL(iterator begin, iterator end); + static iterator GroupSuggestionsBySearchVsURL(iterator begin, iterator end); + + // Bubbles groups of high scoring URLs into gaps between searches. |matches| + // should already be grouped (see |GroupSuggestionsBySearchVsURL()|) such that + // search suggestions are ordered before URL suggestions. |begin_search| + // refers to the first search suggestion to be considered (e.g. excluding the + // default or clipboard suggestions). |begin_url| refers to the first URL + // suggestion. + static void BubbleURLSuggestions(iterator begin_search, + iterator begin_url, + ACMatches& matches); // If we have SearchProvider search suggestions, demote OnDeviceProvider // search suggestions, since, which in general have lower quality than
diff --git a/components/omnibox/browser/autocomplete_result_unittest.cc b/components/omnibox/browser/autocomplete_result_unittest.cc index 2ab93268..a41d8ff 100644 --- a/components/omnibox/browser/autocomplete_result_unittest.cc +++ b/components/omnibox/browser/autocomplete_result_unittest.cc
@@ -56,10 +56,12 @@ }; // Adds |count| AutocompleteMatches to |matches|. -void PopulateAutocompleteMatchesFromTestData( - const AutocompleteMatchTestData* data, - size_t count, - ACMatches* matches) { +template <typename T> +void PopulateAutocompleteMatchesFromTestData(const T* data, + size_t count, + ACMatches* matches) { + static_assert(std::is_base_of<AutocompleteMatchTestData, T>::value, + "T must derive from AutocompleteMatchTestData"); ASSERT_TRUE(matches != nullptr); for (size_t i = 0; i < count; ++i) { AutocompleteMatch match; @@ -145,6 +147,10 @@ const TestData* expected, size_t expected_count); + void AssertMatch(AutocompleteMatch match, + TestData expected_match_data, + int i); + // Creates an AutocompleteResult from |last| and |current|. The two are // merged by |TransferOldMatches| and compared by |AssertResultMatches|. void RunTransferOldMatchesTest(const TestData* last, @@ -205,17 +211,22 @@ const TestData* expected, size_t expected_count) { ASSERT_EQ(expected_count, result.size()); - for (size_t i = 0; i < expected_count; ++i) { - AutocompleteMatch expected_match; - PopulateAutocompleteMatch(expected[i], &expected_match); - const AutocompleteMatch& match = *(result.begin() + i); - EXPECT_EQ(expected_match.provider, match.provider) << i; - EXPECT_EQ(expected_match.relevance, match.relevance) << i; - EXPECT_EQ(expected_match.allowed_to_be_default_match, - match.allowed_to_be_default_match) << i; - EXPECT_EQ(expected_match.destination_url.spec(), - match.destination_url.spec()) << i; - } + for (size_t i = 0; i < expected_count; ++i) + AssertMatch(*(result.begin() + i), expected[i], i); +} + +void AutocompleteResultTest::AssertMatch(AutocompleteMatch match, + TestData expected_match_data, + int i) { + AutocompleteMatch expected_match; + PopulateAutocompleteMatch(expected_match_data, &expected_match); + EXPECT_EQ(expected_match.provider, match.provider) << i; + EXPECT_EQ(expected_match.relevance, match.relevance) << i; + EXPECT_EQ(expected_match.allowed_to_be_default_match, + match.allowed_to_be_default_match) + << i; + EXPECT_EQ(expected_match.destination_url.spec(), match.destination_url.spec()) + << i; } void AutocompleteResultTest::RunTransferOldMatchesTest(const TestData* last, @@ -1694,6 +1705,69 @@ EXPECT_FALSE(result.match_at(2)->has_tab_match); } +TEST_F(AutocompleteResultTest, AttachesPedals) { + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeatures( + {omnibox::kOmniboxPedalSuggestions, omnibox::kOmniboxSuggestionButtonRow}, + {}); + EXPECT_TRUE(OmniboxFieldTrial::IsPedalSuggestionsEnabled()); + FakeAutocompleteProviderClient client; + EXPECT_NE(nullptr, client.GetPedalProvider()); + + AutocompleteResult result; + + // Populate result with test matches. + { + ACMatches matches; + struct TestData : AutocompleteMatchTestData { + std::string contents; + TestData(std::string url, + AutocompleteMatch::Type type, + std::string contents) + : AutocompleteMatchTestData{url, type}, contents(contents) {} + }; + const TestData data[] = { + {"http://search-what-you-typed/", + AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, "search what you typed"}, + {"http://search-history/", AutocompleteMatchType::SEARCH_HISTORY, + "search history"}, + {"http://history-url/", AutocompleteMatchType::HISTORY_URL, + "history url"}, + {"http://history-title/", AutocompleteMatchType::HISTORY_TITLE, + "history title"}, + {"http://url-what-you-typed/", + AutocompleteMatchType::URL_WHAT_YOU_TYPED, "url what you typed"}, + {"http://clipboard-url/", AutocompleteMatchType::CLIPBOARD_URL, + "clipboard url"}, + {"http://bookmark-title/", AutocompleteMatchType::BOOKMARK_TITLE, + "bookmark title"}, + {"http://entity-clear-history/", + AutocompleteMatchType::SEARCH_SUGGEST_ENTITY, "clear history"}, + {"http://clear-history/", AutocompleteMatchType::SEARCH_SUGGEST, + "clear history"}, + }; + PopulateAutocompleteMatchesFromTestData(data, base::size(data), &matches); + for (size_t i = 0; i < base::size(data); i++) { + matches[i].contents = base::UTF8ToUTF16(data[i].contents); + } + + AutocompleteInput input(base::ASCIIToUTF16("a"), + metrics::OmniboxEventProto::OTHER, + TestSchemeClassifier()); + result.AppendMatches(input, matches); + } + + // Attach |pedal| to result matches where appropriate. + result.ConvertInSuggestionPedalMatches(&client); + + // Ensure the entity suggestion doesn't get a pedal even though its contents + // form a concept match. + EXPECT_EQ(nullptr, std::prev(std::prev(result.end()))->pedal); + + // The same concept-matching contents on a non-entity suggestion gets a pedal. + EXPECT_NE(nullptr, std::prev(result.end())->pedal); +} + TEST_F(AutocompleteResultTest, DocumentSuggestionsCanMergeButNotToDefault) { // Types are populated below to avoid introducing a new test data creation // process. @@ -1839,3 +1913,75 @@ EXPECT_EQ(result.match_at(0)->relevance, 1500); EXPECT_EQ(AutocompleteMatchType::CLIPBOARD_URL, result.match_at(0)->type); } + +TEST_F(AutocompleteResultTest, BubbleURLSuggestions) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(omnibox::kBubbleUrlSuggestions); + + auto test = [&](const std::vector<int>& scores, size_t begin_search, + size_t begin_url, const std::vector<size_t>& expected_order, + const std::string& trace_string) { + SCOPED_TRACE(trace_string); + std::vector<TestData> data; + for (size_t i = 0; i < scores.size(); ++i) + data.push_back(TestData{i, 0, scores[i]}); + ACMatches matches; + PopulateAutocompleteMatches(data.data(), scores.size(), &matches); + AutocompleteResult::BubbleURLSuggestions( + matches.begin() + begin_search, matches.begin() + begin_url, matches); + ASSERT_EQ(matches.size(), scores.size()); + for (size_t i = 0; i < matches.size(); ++i) + AssertMatch(matches[i], data[expected_order[i]], i); + }; + + // Regardless of scores, in the trivial cases with only either searches or + // URLs, the matches should not be reordered. + test({500, 1100, 1000, 1300, 1200}, 0, 5, {0, 1, 2, 3, 4}, "Only searches"); + test({500, 1100, 1000, 1300, 1200}, 0, 0, {0, 1, 2, 3, 4}, "Only URLs"); + test({500, 1100, 1000, 1300, 1200}, 3, 5, {0, 1, 2, 3, 4}, + "Only skipped suggestions & searches"); + test({500, 1100, 1000, 1300, 1200}, 3, 3, {0, 1, 2, 3, 4}, + "Only skipped suggestions & URLs"); + + // URLs are bubbled above a search suggestion if 2 conditions are met: + // 1) There must be a sufficient score gap between the adjacent searches. E.g. + // for (S1, U1, S2), the difference in scores of S1 and S2 must be larger than + // some threshold. + // 2) There must be a sufficient buffer between the URL and search scores. + // This only applies to the first URL suggestion in a group. E.g. for + // (S1, U1, U2, S2, U3, S3), U1 & U3 must score higher than S2 + threshold & + // S3 + threshold respectively, but U2 need only score higher than S2. + test({600, 400, /*URL*/ 500}, 0, 2, {0, 2, 1}, "Bubble 1 URL"); + test({599, 400, /*URL*/ 500}, 0, 2, {0, 1, 2}, "Insufficient gap"); + test({600, 400, /*URL*/ 499}, 0, 2, {0, 1, 2}, "Insufficient buffer"); + + // No buffer is necessary for subsequent URLs in a group, but is necessary + // for the 1st URL of each group. + test({600, 400, 200, /*URL group 1*/ 500, 450, /*URL group 2*/ 300, 250}, 0, + 3, {0, 3, 4, 1, 5, 6, 2}, "Bubble 2 URL groups"); + test({600, 400, 200, /*URL group 1*/ 500, 450, /*URL group 2*/ 299, 250}, 0, + 3, {0, 3, 4, 1, 2, 5, 6}, + "Bubble 1st of 2 URL groups; insufficient buffer for 2nd group"); + test({600, 399, 200, /*URL group 1*/ 500, 450, /*URL group 2*/ 300, 250}, 0, + 3, {0, 3, 4, 1, 2, 5, 6}, + "Bubble 1st of 2 URL groups; insufficient gap for 2nd group"); + test({600, 400, 200, /*URL group 1*/ 499, 450, /*URL group 2*/ 300, 250}, 0, + 3, {0, 1, 3, 4, 5, 6, 2}, + "Bubble 2nd of 2 URL groups; insufficient buffer for 1st group"); + test({599, 400, 200, /*URL group 1*/ 500, 450, /*URL group 2*/ 300, 250}, 0, + 3, {0, 1, 3, 4, 5, 6, 2}, + "Bubble 2nd of 2 URL groups; insufficient gap for 1st group"); + + // No gap is necessary when bubbling into the top position. + test({600, /*URLs*/ 700, 650}, 0, 1, {1, 2, 0}, + "Bubble 1 URL group into top position"); + test({600, /*URL*/ 650}, 0, 1, {0, 1}, + "Insufficient buffer for top position"); + + // Skipped suggestions (e.g. default or clipboard suggestions) should not + // affect ordering. + test({/*skipped*/ 900, /*search*/ 600, /*URL*/ 700}, 1, 2, {0, 2, 1}, + "Skipped suggestion"); + test({/*skipped*/ 600, /*search*/ 600, /*URL*/ 700}, 1, 2, {0, 2, 1}, + "Skipped suggestion should not affect gap"); +}
diff --git a/components/omnibox/browser/omnibox_field_trial.cc b/components/omnibox/browser/omnibox_field_trial.cc index ad102fe..0874807a 100644 --- a/components/omnibox/browser/omnibox_field_trial.cc +++ b/components/omnibox/browser/omnibox_field_trial.cc
@@ -947,6 +947,15 @@ const char OmniboxFieldTrial::kDynamicMaxAutocompleteIncreasedLimitParam[] = "OmniboxDynamicMaxAutocompleteIncreasedLimit"; +const char OmniboxFieldTrial::kBubbleUrlSuggestionsAbsoluteGapParam[] = + "OmniboxBubbleUrlSuggestionsAbsoluteGap"; +const char OmniboxFieldTrial::kBubbleUrlSuggestionsRelativeGapParam[] = + "OmniboxBubbleUrlSuggestionsRelativeGap"; +const char OmniboxFieldTrial::kBubbleUrlSuggestionsAbsoluteBufferParam[] = + "OmniboxBubbleUrlSuggestionsAbsoluteBuffer"; +const char OmniboxFieldTrial::kBubbleUrlSuggestionsRelativeBufferParam[] = + "OmniboxBubbleUrlSuggestionsRelativeBuffer"; + const char OmniboxFieldTrial::kOnDeviceHeadModelLocaleConstraint[] = "ForceModelLocaleConstraint"; const char OmniboxFieldTrial::kOnDeviceHeadSuggestMaxScoreForNonUrlInput[] =
diff --git a/components/omnibox/browser/omnibox_field_trial.h b/components/omnibox/browser/omnibox_field_trial.h index e93b2f3..8252ed3 100644 --- a/components/omnibox/browser/omnibox_field_trial.h +++ b/components/omnibox/browser/omnibox_field_trial.h
@@ -522,6 +522,12 @@ extern const char kDynamicMaxAutocompleteUrlCutoffParam[]; extern const char kDynamicMaxAutocompleteIncreasedLimitParam[]; +// Parameters used for ranking. +extern const char kBubbleUrlSuggestionsAbsoluteGapParam[]; +extern const char kBubbleUrlSuggestionsRelativeGapParam[]; +extern const char kBubbleUrlSuggestionsAbsoluteBufferParam[]; +extern const char kBubbleUrlSuggestionsRelativeBufferParam[]; + // Parameter names used by on device head provider. // These four parameters are shared by both non-incognito and incognito. extern const char kOnDeviceHeadModelLocaleConstraint[];
diff --git a/components/omnibox/common/omnibox_features.cc b/components/omnibox/common/omnibox_features.cc index 68e1a00..39787dba 100644 --- a/components/omnibox/common/omnibox_features.cc +++ b/components/omnibox/common/omnibox_features.cc
@@ -203,6 +203,13 @@ const base::Feature kDynamicMaxAutocomplete{"OmniboxDynamicMaxAutocomplete", base::FEATURE_DISABLED_BY_DEFAULT}; +// Feature used to enable bubbling URL suggestions above search suggestions +// after grouping if 2 conditions are met: +// 1) There must be a sufficient score gap between the adjacent searches. +// 2) There must be a sufficient buffer between the URL and search scores. +const base::Feature kBubbleUrlSuggestions{"OmniboxBubbleUrlSuggestions", + base::FEATURE_DISABLED_BY_DEFAULT}; + // If enabled, when the user clears the whole omnibox text (i.e. via Backspace), // Chrome will request remote ZeroSuggest suggestions for the OTHER page // classification (contextual web).
diff --git a/components/omnibox/common/omnibox_features.h b/components/omnibox/common/omnibox_features.h index 20a0d26..d47a5d19 100644 --- a/components/omnibox/common/omnibox_features.h +++ b/components/omnibox/common/omnibox_features.h
@@ -46,7 +46,7 @@ // Num suggestions - these affect how many suggestions are shown based on e.g. // focus, page context, provider, or URL v non-URL. -// Note that all of these are overriden and default values used instead if +// Note that all of these are overridden and default values used instead if // kNewSearchFeatures is disabled. extern const base::Feature kMaxZeroSuggestMatches; extern const base::Feature kUIExperimentMaxAutocompleteMatches; @@ -56,6 +56,9 @@ extern const base::Feature kOmniboxMaxURLMatches; extern const base::Feature kDynamicMaxAutocomplete; +// Ranking +extern const base::Feature kBubbleUrlSuggestions; + // On-Focus Suggestions a.k.a. ZeroSuggest. extern const base::Feature kClobberTriggersContextualWebZeroSuggest; extern const base::Feature kOmniboxLocalZeroSuggestAgeThreshold;
diff --git a/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc b/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc index b066dd9..1a317fa7 100644 --- a/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc +++ b/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc
@@ -12,7 +12,7 @@ // (or highly likely be) rare, e.g. <1% of page views as measured by UMA. // // UKM-based UseCounter should be used to cover the case when UMA UseCounter -// data shows a behaviour that is rare but too common to bindly change. +// data shows a behaviour that is rare but too common to blindly change. // UKM-based UseCounter would allow use to find specific pages to reason about // either a breaking change is acceptable or not. @@ -179,6 +179,7 @@ WebFeature::kSchemelesslySameSitePostMessage, WebFeature::kSchemelesslySameSitePostMessageSecureToInsecure, WebFeature::kSchemelesslySameSitePostMessageInsecureToSecure, + WebFeature::kElementAttachInternalsBeforeConstructor, })); return *opt_in_features; } \ No newline at end of file
diff --git a/components/password_manager/core/browser/login_database_unittest.cc b/components/password_manager/core/browser/login_database_unittest.cc index 41e54fb..3fa26a7 100644 --- a/components/password_manager/core/browser/login_database_unittest.cc +++ b/components/password_manager/core/browser/login_database_unittest.cc
@@ -2318,6 +2318,13 @@ protected: LoginDatabaseUndecryptableLoginsTest() = default; + public: + LoginDatabaseUndecryptableLoginsTest( + const LoginDatabaseUndecryptableLoginsTest&) = delete; + LoginDatabaseUndecryptableLoginsTest& operator=( + const LoginDatabaseUndecryptableLoginsTest&) = delete; + + protected: void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); database_path_ = temp_dir_.GetPath().AppendASCII("test.db"); @@ -2346,8 +2353,6 @@ base::ScopedTempDir temp_dir_; base::test::TaskEnvironment task_environment_; TestingPrefServiceSimple testing_local_state_; - - DISALLOW_COPY_AND_ASSIGN(LoginDatabaseUndecryptableLoginsTest); }; PasswordForm LoginDatabaseUndecryptableLoginsTest::AddDummyLogin(
diff --git a/components/password_manager/core/browser/password_form_manager_unittest.cc b/components/password_manager/core/browser/password_form_manager_unittest.cc index 7293d5c..b19766a 100644 --- a/components/password_manager/core/browser/password_form_manager_unittest.cc +++ b/components/password_manager/core/browser/password_form_manager_unittest.cc
@@ -121,6 +121,9 @@ public: MockAutofillDownloadManager() : AutofillDownloadManager(nullptr, &fake_observer) {} + MockAutofillDownloadManager(const MockAutofillDownloadManager&) = delete; + MockAutofillDownloadManager& operator=(const MockAutofillDownloadManager&) = + delete; MOCK_METHOD6(StartUploadRequest, bool(const FormStructure&, @@ -138,7 +141,6 @@ }; StubObserver fake_observer; - DISALLOW_COPY_AND_ASSIGN(MockAutofillDownloadManager); }; class MockPasswordManagerClient : public StubPasswordManagerClient { @@ -241,7 +243,8 @@ class MockFormSaver : public StubFormSaver { public: MockFormSaver() = default; - + MockFormSaver(const MockFormSaver&) = delete; + MockFormSaver& operator=(const MockFormSaver&) = delete; ~MockFormSaver() override = default; // FormSaver: @@ -269,9 +272,6 @@ static MockFormSaver& Get(PasswordFormManager* form_manager) { return *static_cast<MockFormSaver*>(form_manager->form_saver()); } - - private: - DISALLOW_COPY_AND_ASSIGN(MockFormSaver); }; class MockFieldInfoManager : public FieldInfoManager { @@ -2369,6 +2369,8 @@ class MockPasswordSaveManager : public PasswordSaveManager { public: MockPasswordSaveManager() = default; + MockPasswordSaveManager(const MockPasswordSaveManager&) = delete; + MockPasswordSaveManager& operator=(const MockPasswordSaveManager&) = delete; ~MockPasswordSaveManager() override = default; MOCK_METHOD4(Init, void(PasswordManagerClient*, @@ -2407,14 +2409,15 @@ MOCK_METHOD1(MoveCredentialsToAccountStore, void(metrics_util::MoveToAccountStoreTrigger)); MOCK_METHOD1(BlockMovingToAccountStoreFor, void(const autofill::GaiaIdHash&)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockPasswordSaveManager); }; class PasswordFormManagerTestWithMockedSaver : public PasswordFormManagerTest { public: PasswordFormManagerTestWithMockedSaver() = default; + PasswordFormManagerTestWithMockedSaver( + const PasswordFormManagerTestWithMockedSaver&) = delete; + PasswordFormManagerTestWithMockedSaver& operator=( + const PasswordFormManagerTestWithMockedSaver&) = delete; MockPasswordSaveManager* mock_password_save_manager() { return mock_password_save_manager_; @@ -2449,7 +2452,6 @@ private: NiceMock<MockPasswordSaveManager>* mock_password_save_manager_; - DISALLOW_COPY_AND_ASSIGN(PasswordFormManagerTestWithMockedSaver); }; TEST_F( @@ -2648,8 +2650,7 @@ TEST_F(PasswordFormManagerTestWithMockedSaver, PresaveGeneratedPassword) { fetcher_->NotifyFetchCompleted(); EXPECT_FALSE(form_manager_->HasGeneratedPassword()); - form_manager_->SetGenerationPopupWasShown(false /* is_manual_generation - */); + form_manager_->SetGenerationPopupWasShown(/*is_manual_generation=*/false); PasswordForm form_with_generated_password = parsed_submitted_form_; FormData& form_data = form_with_generated_password.form_data; // Check that the generated password is forwarded to the save manager.
diff --git a/components/plugins/renderer/webview_plugin.cc b/components/plugins/renderer/webview_plugin.cc index f4a3b27..55833cea4 100644 --- a/components/plugins/renderer/webview_plugin.cc +++ b/components/plugins/renderer/webview_plugin.cc
@@ -278,11 +278,8 @@ blink::mojom::FrameWidgetHostInterfaceBase>(), blink::CrossVariantMojoAssociatedReceiver< blink::mojom::FrameWidgetInterfaceBase>(), - // TODO(dtapuska): https://crbug.com/1085031. Have the suffix ForTesting - // removed. - blink_widget_host_receiver_ - .BindNewEndpointAndPassDedicatedRemoteForTesting(), - blink_widget_.BindNewEndpointAndPassDedicatedReceiverForTesting()); + blink_widget_host_receiver_.BindNewEndpointAndPassDedicatedRemote(), + blink_widget_.BindNewEndpointAndPassDedicatedReceiver()); // The WebFrame created here was already attached to the Page as its main // frame, and the WebFrameWidget has been initialized, so we can call
diff --git a/components/policy/android/BUILD.gn b/components/policy/android/BUILD.gn index 111aabe..5c7251c 100644 --- a/components/policy/android/BUILD.gn +++ b/components/policy/android/BUILD.gn
@@ -5,9 +5,9 @@ import("//build/config/android/rules.gni") _jni_sources = [ - "java/src/org/chromium/policy/CombinedPolicyProvider.java", - "java/src/org/chromium/policy/PolicyConverter.java", - "java/src/org/chromium/policy/PolicyService.java", + "java/src/org/chromium/components/policy/CombinedPolicyProvider.java", + "java/src/org/chromium/components/policy/PolicyConverter.java", + "java/src/org/chromium/components/policy/PolicyService.java", ] java_cpp_strings("java_switches_srcjar") { @@ -26,12 +26,14 @@ srcjar_deps = [ ":java_switches_srcjar" ] annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ] - sources = - _jni_sources + [ - "java/src/org/chromium/policy/AbstractAppRestrictionsProvider.java", - "java/src/org/chromium/policy/AppRestrictionsProvider.java", - "java/src/org/chromium/policy/PolicyProvider.java", - ] + sources = _jni_sources + [ + "java/src/org/chromium/policy/AppRestrictionsProvider.java", + "java/src/org/chromium/policy/CombinedPolicyProvider.java", + "java/src/org/chromium/policy/PolicyProvider.java", + "java/src/org/chromium/components/policy/AbstractAppRestrictionsProvider.java", + "java/src/org/chromium/components/policy/AppRestrictionsProvider.java", + "java/src/org/chromium/components/policy/PolicyProvider.java", + ] } android_library("policy_java_test_support") { @@ -44,8 +46,8 @@ "//third_party/junit", ] sources = [ - "javatests/src/org/chromium/policy/test/PolicyData.java", - "javatests/src/org/chromium/policy/test/annotations/Policies.java", + "javatests/src/org/chromium/components/policy/test/PolicyData.java", + "javatests/src/org/chromium/components/policy/test/annotations/Policies.java", ] } @@ -59,10 +61,10 @@ bypass_platform_checks = true testonly = true sources = [ - "junit/src/org/chromium/policy/AbstractAppRestrictionsProviderTest.java", - "junit/src/org/chromium/policy/CombinedPolicyProviderTest.java", - "junit/src/org/chromium/policy/PolicyConverterTest.java", - "junit/src/org/chromium/policy/test/annotations/PoliciesTest.java", + "junit/src/org/chromium/components/policy/AbstractAppRestrictionsProviderTest.java", + "junit/src/org/chromium/components/policy/CombinedPolicyProviderTest.java", + "junit/src/org/chromium/components/policy/PolicyConverterTest.java", + "junit/src/org/chromium/components/policy/test/annotations/PoliciesTest.java", ] deps = [ ":policy_java", @@ -77,8 +79,7 @@ ] } -_test_jni_sources = - [ "javatests/src/org/chromium/policy/test/PolicyServiceTestSupporter.java" ] +_test_jni_sources = [ "javatests/src/org/chromium/components/policy/test/PolicyServiceTestSupporter.java" ] android_library("native_test_support_java") { testonly = true
diff --git a/components/policy/android/java/src/org/chromium/policy/AbstractAppRestrictionsProvider.java b/components/policy/android/java/src/org/chromium/components/policy/AbstractAppRestrictionsProvider.java similarity index 98% rename from components/policy/android/java/src/org/chromium/policy/AbstractAppRestrictionsProvider.java rename to components/policy/android/java/src/org/chromium/components/policy/AbstractAppRestrictionsProvider.java index f076c81..ce6bbb20 100644 --- a/components/policy/android/java/src/org/chromium/policy/AbstractAppRestrictionsProvider.java +++ b/components/policy/android/java/src/org/chromium/components/policy/AbstractAppRestrictionsProvider.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.policy; +package org.chromium.components.policy; import android.content.BroadcastReceiver; import android.content.Context;
diff --git a/components/policy/android/java/src/org/chromium/components/policy/AppRestrictionsProvider.java b/components/policy/android/java/src/org/chromium/components/policy/AppRestrictionsProvider.java new file mode 100644 index 0000000..103d37d --- /dev/null +++ b/components/policy/android/java/src/org/chromium/components/policy/AppRestrictionsProvider.java
@@ -0,0 +1,67 @@ +// 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. + +package org.chromium.components.policy; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.os.SystemClock; +import android.os.UserManager; + +import org.chromium.base.metrics.RecordHistogram; + +/** + * Concrete app restriction provider, that uses the default android mechanism to retrieve the + * restrictions. + */ +public class AppRestrictionsProvider extends AbstractAppRestrictionsProvider { + /** + * Get the app restriction information from provided user manager, and record some timing + * metrics on its runtime. + * @param userManager UserManager service from Android System service + * @param packageName package name for target application. + * @return The restrictions for the provided package name, an empty bundle if they are not + * available. + */ + public static Bundle getApplicationRestrictionsFromUserManager( + UserManager userManager, String packageName) { + try { + return userManager.getApplicationRestrictions(packageName); + } catch (SecurityException e) { + // Android bug may throw SecurityException. See crbug.com/886814. + return new Bundle(); + } + } + + private final UserManager mUserManager; + + public AppRestrictionsProvider(Context context) { + super(context); + + mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); + } + + @Override + protected Bundle getApplicationRestrictions(String packageName) { + long startTime = SystemClock.elapsedRealtime(); + Bundle bundle = getApplicationRestrictionsFromUserManager(mUserManager, packageName); + long endTime = SystemClock.elapsedRealtime(); + long duration = endTime - startTime; + RecordHistogram.recordTimesHistogram("Enterprise.AppRestrictionLoadTime2", duration); + if (bundle.isEmpty()) { + RecordHistogram.recordTimesHistogram( + "Enterprise.AppRestrictionLoadTime2.EmptyBundle", duration); + } else { + RecordHistogram.recordTimesHistogram( + "Enterprise.AppRestrictionLoadTime2.NonEmptyBundle", duration); + } + return bundle; + } + + @Override + protected String getRestrictionChangeIntentAction() { + return Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED; + } +}
diff --git a/components/policy/android/java/src/org/chromium/components/policy/CombinedPolicyProvider.java b/components/policy/android/java/src/org/chromium/components/policy/CombinedPolicyProvider.java new file mode 100644 index 0000000..e66463f --- /dev/null +++ b/components/policy/android/java/src/org/chromium/components/policy/CombinedPolicyProvider.java
@@ -0,0 +1,145 @@ +// 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. + +package org.chromium.components.policy; + +import android.os.Bundle; + +import androidx.annotation.VisibleForTesting; + +import org.chromium.base.ThreadUtils; +import org.chromium.base.annotations.CalledByNative; +import org.chromium.base.annotations.JNINamespace; +import org.chromium.base.annotations.NativeMethods; + +import java.util.ArrayList; +import java.util.List; + +/** + * Reads enterprise policies from one or more policy providers and plumbs them through to the policy + * subsystem. + */ +@JNINamespace("policy::android") +public class CombinedPolicyProvider { + private static CombinedPolicyProvider sInstance; + + private long mNativeCombinedPolicyProvider; + + private PolicyConverter mPolicyConverter; + private final List<PolicyProvider> mPolicyProviders = new ArrayList<>(); + private final List<Bundle> mCachedPolicies = new ArrayList<>(); + private final List<PolicyChangeListener> mPolicyChangeListeners = new ArrayList<>(); + + public static CombinedPolicyProvider get() { + if (sInstance == null) { + sInstance = new CombinedPolicyProvider(); + } + return sInstance; + } + + private void linkNativeInternal( + long nativeCombinedPolicyProvider, PolicyConverter policyConverter) { + mNativeCombinedPolicyProvider = nativeCombinedPolicyProvider; + mPolicyConverter = policyConverter; + if (nativeCombinedPolicyProvider != 0) { + for (PolicyProvider provider : mPolicyProviders) { + provider.refresh(); + } + } + } + + @CalledByNative + public static CombinedPolicyProvider linkNative( + long nativeCombinedPolicyProvider, PolicyConverter policyConverter) { + ThreadUtils.assertOnUiThread(); + get().linkNativeInternal(nativeCombinedPolicyProvider, policyConverter); + return get(); + } + + /** + * PolicyProviders are assigned a unique precedence based on their order of registration. Later + * Registration -> Higher Precedence. This precedence is also used as a 'source' tag for + * disambiguating updates. + */ + public void registerProvider(PolicyProvider provider) { + mPolicyProviders.add(provider); + mCachedPolicies.add(null); + provider.setManagerAndSource(this, mPolicyProviders.size() - 1); + if (mNativeCombinedPolicyProvider != 0) provider.refresh(); + } + + public void destroy() { + // All the activities registered should have been destroyed by then. + assert mPolicyChangeListeners.isEmpty(); + + for (PolicyProvider provider : mPolicyProviders) { + provider.destroy(); + } + mPolicyProviders.clear(); + mPolicyConverter = null; + } + + void onSettingsAvailable(int source, Bundle newSettings) { + mCachedPolicies.set(source, newSettings); + // Check if we have policies from all the providers before applying them. + for (Bundle settings : mCachedPolicies) { + if (settings == null) return; + } + + if (mNativeCombinedPolicyProvider == 0) return; + + for (Bundle settings : mCachedPolicies) { + for (String key : settings.keySet()) { + mPolicyConverter.setPolicy(key, settings.get(key)); + } + } + CombinedPolicyProviderJni.get().flushPolicies(mNativeCombinedPolicyProvider, get()); + } + + void terminateIncognitoSession() { + for (PolicyChangeListener listener : mPolicyChangeListeners) { + listener.terminateIncognitoSession(); + } + } + + public void addPolicyChangeListener(PolicyChangeListener listener) { + mPolicyChangeListeners.add(listener); + } + + public void removePolicyChangeListener(PolicyChangeListener listener) { + assert mPolicyChangeListeners.contains(listener); + mPolicyChangeListeners.remove(listener); + } + + @VisibleForTesting + @CalledByNative + void refreshPolicies() { + assert mPolicyProviders.size() == mCachedPolicies.size(); + for (int i = 0; i < mCachedPolicies.size(); ++i) { + mCachedPolicies.set(i, null); + } + for (PolicyProvider provider : mPolicyProviders) { + provider.refresh(); + } + } + + /** + * Interface to handle actions related with policy changes. + */ + public interface PolicyChangeListener { + /** + * Call to notify the listener that incognito browsing is unavailable due to policy. + */ + void terminateIncognitoSession(); + } + + static void setForTesting(CombinedPolicyProvider p) { + sInstance = p; + } + + @NativeMethods + interface Natives { + void flushPolicies(long nativeAndroidCombinedPolicyProvider, CombinedPolicyProvider caller); + } +}
diff --git a/components/policy/android/java/src/org/chromium/policy/PolicyConverter.java b/components/policy/android/java/src/org/chromium/components/policy/PolicyConverter.java similarity index 99% rename from components/policy/android/java/src/org/chromium/policy/PolicyConverter.java rename to components/policy/android/java/src/org/chromium/components/policy/PolicyConverter.java index 957b709f..032a5f8 100644 --- a/components/policy/android/java/src/org/chromium/policy/PolicyConverter.java +++ b/components/policy/android/java/src/org/chromium/components/policy/PolicyConverter.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.policy; +package org.chromium.components.policy; import android.os.Bundle;
diff --git a/components/policy/android/java/src/org/chromium/components/policy/PolicyProvider.java b/components/policy/android/java/src/org/chromium/components/policy/PolicyProvider.java new file mode 100644 index 0000000..bdbbf8f --- /dev/null +++ b/components/policy/android/java/src/org/chromium/components/policy/PolicyProvider.java
@@ -0,0 +1,58 @@ +// 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. + +package org.chromium.components.policy; + +import android.os.Bundle; + +import org.chromium.base.ThreadUtils; + +/** + * Base class for Policy providers. + */ +public abstract class PolicyProvider { + private CombinedPolicyProvider mCombinedPolicyProvider; + private int mSource = -1; + + protected PolicyProvider() {} + + public void notifySettingsAvailable(Bundle settings) { + ThreadUtils.assertOnUiThread(); + mCombinedPolicyProvider.onSettingsAvailable(mSource, settings); + } + + protected void terminateIncognitoSession() { + mCombinedPolicyProvider.terminateIncognitoSession(); + } + + /** + * Called to request a refreshed set of policies. This method must handle notifying the + * CombinedPolicyProvider whenever applicable. + */ + public abstract void refresh(); + + /** + * Register the PolicyProvider for receiving policy changes. + */ + protected void startListeningForPolicyChanges() {} + + /** + * Called by the {@link CombinedPolicyProvider} to correctly hook it with the Policy system. + * + * @param combinedPolicyProvider reference to the CombinedPolicyProvider to be used like a + * delegate. + * @param source tags the PolicyProvider with a source. + */ + final void setManagerAndSource(CombinedPolicyProvider combinedPolicyProvider, int source) { + assert mSource < 0; + assert source >= 0; + mSource = source; + assert mCombinedPolicyProvider == null; + mCombinedPolicyProvider = combinedPolicyProvider; + startListeningForPolicyChanges(); + } + + /** Called when the provider is unregistered */ + public void destroy() {} +}
diff --git a/components/policy/android/java/src/org/chromium/policy/PolicyService.java b/components/policy/android/java/src/org/chromium/components/policy/PolicyService.java similarity index 98% rename from components/policy/android/java/src/org/chromium/policy/PolicyService.java rename to components/policy/android/java/src/org/chromium/components/policy/PolicyService.java index 64d099bf..71390cf 100644 --- a/components/policy/android/java/src/org/chromium/policy/PolicyService.java +++ b/components/policy/android/java/src/org/chromium/components/policy/PolicyService.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.policy; +package org.chromium.components.policy; import org.chromium.base.CollectionUtil; import org.chromium.base.annotations.CalledByNative;
diff --git a/components/policy/android/java/src/org/chromium/policy/AppRestrictionsProvider.java b/components/policy/android/java/src/org/chromium/policy/AppRestrictionsProvider.java index 70ff4f5..ab14e31 100644 --- a/components/policy/android/java/src/org/chromium/policy/AppRestrictionsProvider.java +++ b/components/policy/android/java/src/org/chromium/policy/AppRestrictionsProvider.java
@@ -5,63 +5,15 @@ package org.chromium.policy; import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.os.SystemClock; -import android.os.UserManager; - -import org.chromium.base.metrics.RecordHistogram; /** * Concrete app restriction provider, that uses the default android mechanism to retrieve the * restrictions. + * TODO(zmin): Delete once the internal code is migrated. */ -public class AppRestrictionsProvider extends AbstractAppRestrictionsProvider { - /** - * Get the app restriction information from provided user manager, and record some timing - * metrics on its runtime. - * @param userManager UserManager service from Android System service - * @param packageName package name for target application. - * @return The restrictions for the provided package name, an empty bundle if they are not - * available. - */ - public static Bundle getApplicationRestrictionsFromUserManager( - UserManager userManager, String packageName) { - try { - return userManager.getApplicationRestrictions(packageName); - } catch (SecurityException e) { - // Android bug may throw SecurityException. See crbug.com/886814. - return new Bundle(); - } - } - - private final UserManager mUserManager; - +public class AppRestrictionsProvider + extends org.chromium.components.policy.AppRestrictionsProvider { public AppRestrictionsProvider(Context context) { super(context); - - mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); - } - - @Override - protected Bundle getApplicationRestrictions(String packageName) { - long startTime = SystemClock.elapsedRealtime(); - Bundle bundle = getApplicationRestrictionsFromUserManager(mUserManager, packageName); - long endTime = SystemClock.elapsedRealtime(); - long duration = endTime - startTime; - RecordHistogram.recordTimesHistogram("Enterprise.AppRestrictionLoadTime2", duration); - if (bundle.isEmpty()) { - RecordHistogram.recordTimesHistogram( - "Enterprise.AppRestrictionLoadTime2.EmptyBundle", duration); - } else { - RecordHistogram.recordTimesHistogram( - "Enterprise.AppRestrictionLoadTime2.NonEmptyBundle", duration); - } - return bundle; - } - - @Override - protected String getRestrictionChangeIntentAction() { - return Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED; } }
diff --git a/components/policy/android/java/src/org/chromium/policy/CombinedPolicyProvider.java b/components/policy/android/java/src/org/chromium/policy/CombinedPolicyProvider.java index 9ffb5706..7294fc8 100644 --- a/components/policy/android/java/src/org/chromium/policy/CombinedPolicyProvider.java +++ b/components/policy/android/java/src/org/chromium/policy/CombinedPolicyProvider.java
@@ -4,142 +4,10 @@ package org.chromium.policy; -import android.os.Bundle; - -import androidx.annotation.VisibleForTesting; - -import org.chromium.base.ThreadUtils; -import org.chromium.base.annotations.CalledByNative; -import org.chromium.base.annotations.JNINamespace; -import org.chromium.base.annotations.NativeMethods; - -import java.util.ArrayList; -import java.util.List; - /** * Reads enterprise policies from one or more policy providers and plumbs them through to the policy * subsystem. + * + * TODO(zmin): Delete once the internal code is migrated. */ -@JNINamespace("policy::android") -public class CombinedPolicyProvider { - private static CombinedPolicyProvider sInstance; - - private long mNativeCombinedPolicyProvider; - - private PolicyConverter mPolicyConverter; - private final List<PolicyProvider> mPolicyProviders = new ArrayList<>(); - private final List<Bundle> mCachedPolicies = new ArrayList<>(); - private final List<PolicyChangeListener> mPolicyChangeListeners = new ArrayList<>(); - - public static CombinedPolicyProvider get() { - if (sInstance == null) { - sInstance = new CombinedPolicyProvider(); - } - return sInstance; - } - - private void linkNativeInternal( - long nativeCombinedPolicyProvider, PolicyConverter policyConverter) { - mNativeCombinedPolicyProvider = nativeCombinedPolicyProvider; - mPolicyConverter = policyConverter; - if (nativeCombinedPolicyProvider != 0) { - for (PolicyProvider provider : mPolicyProviders) { - provider.refresh(); - } - } - } - - @CalledByNative - public static CombinedPolicyProvider linkNative( - long nativeCombinedPolicyProvider, PolicyConverter policyConverter) { - ThreadUtils.assertOnUiThread(); - get().linkNativeInternal(nativeCombinedPolicyProvider, policyConverter); - return get(); - } - - /** - * PolicyProviders are assigned a unique precedence based on their order of registration. Later - * Registration -> Higher Precedence. This precedence is also used as a 'source' tag for - * disambiguating updates. - */ - public void registerProvider(PolicyProvider provider) { - mPolicyProviders.add(provider); - mCachedPolicies.add(null); - provider.setManagerAndSource(this, mPolicyProviders.size() - 1); - if (mNativeCombinedPolicyProvider != 0) provider.refresh(); - } - - public void destroy() { - // All the activities registered should have been destroyed by then. - assert mPolicyChangeListeners.isEmpty(); - - for (PolicyProvider provider : mPolicyProviders) { - provider.destroy(); - } - mPolicyProviders.clear(); - mPolicyConverter = null; - } - - void onSettingsAvailable(int source, Bundle newSettings) { - mCachedPolicies.set(source, newSettings); - // Check if we have policies from all the providers before applying them. - for (Bundle settings : mCachedPolicies) { - if (settings == null) return; - } - - if (mNativeCombinedPolicyProvider == 0) return; - - for (Bundle settings : mCachedPolicies) { - for (String key : settings.keySet()) { - mPolicyConverter.setPolicy(key, settings.get(key)); - } - } - CombinedPolicyProviderJni.get().flushPolicies(mNativeCombinedPolicyProvider, get()); - } - - void terminateIncognitoSession() { - for (PolicyChangeListener listener : mPolicyChangeListeners) { - listener.terminateIncognitoSession(); - } - } - - public void addPolicyChangeListener(PolicyChangeListener listener) { - mPolicyChangeListeners.add(listener); - } - - public void removePolicyChangeListener(PolicyChangeListener listener) { - assert mPolicyChangeListeners.contains(listener); - mPolicyChangeListeners.remove(listener); - } - - @VisibleForTesting - @CalledByNative - void refreshPolicies() { - assert mPolicyProviders.size() == mCachedPolicies.size(); - for (int i = 0; i < mCachedPolicies.size(); ++i) { - mCachedPolicies.set(i, null); - } - for (PolicyProvider provider : mPolicyProviders) { - provider.refresh(); - } - } - - /** - * Interface to handle actions related with policy changes. - */ - public interface PolicyChangeListener { - /** - * Call to notify the listener that incognito browsing is unavailable due to policy. - */ - void terminateIncognitoSession(); - } - - static void setForTesting(CombinedPolicyProvider p) { - sInstance = p; - } - - @NativeMethods - interface Natives { - void flushPolicies(long nativeAndroidCombinedPolicyProvider, CombinedPolicyProvider caller); - } -} +public class CombinedPolicyProvider extends org.chromium.components.policy.CombinedPolicyProvider {}
diff --git a/components/policy/android/java/src/org/chromium/policy/PolicyProvider.java b/components/policy/android/java/src/org/chromium/policy/PolicyProvider.java index a626dd7..1df6db7 100644 --- a/components/policy/android/java/src/org/chromium/policy/PolicyProvider.java +++ b/components/policy/android/java/src/org/chromium/policy/PolicyProvider.java
@@ -4,55 +4,8 @@ package org.chromium.policy; -import android.os.Bundle; - -import org.chromium.base.ThreadUtils; - /** * Base class for Policy providers. + * TODO(zmin): Delete once the internal code is migrated. */ -public abstract class PolicyProvider { - private CombinedPolicyProvider mCombinedPolicyProvider; - private int mSource = -1; - - protected PolicyProvider() {} - - public void notifySettingsAvailable(Bundle settings) { - ThreadUtils.assertOnUiThread(); - mCombinedPolicyProvider.onSettingsAvailable(mSource, settings); - } - - protected void terminateIncognitoSession() { - mCombinedPolicyProvider.terminateIncognitoSession(); - } - - /** - * Called to request a refreshed set of policies. This method must handle notifying the - * CombinedPolicyProvider whenever applicable. - */ - public abstract void refresh(); - - /** - * Register the PolicyProvider for receiving policy changes. - */ - protected void startListeningForPolicyChanges() {} - - /** - * Called by the {@link CombinedPolicyProvider} to correctly hook it with the Policy system. - * - * @param combinedPolicyProvider reference to the CombinedPolicyProvider to be used like a - * delegate. - * @param source tags the PolicyProvider with a source. - */ - final void setManagerAndSource(CombinedPolicyProvider combinedPolicyProvider, int source) { - assert mSource < 0; - assert source >= 0; - mSource = source; - assert mCombinedPolicyProvider == null; - mCombinedPolicyProvider = combinedPolicyProvider; - startListeningForPolicyChanges(); - } - - /** Called when the provider is unregistered */ - public void destroy() {} -} +public abstract class PolicyProvider extends org.chromium.components.policy.PolicyProvider {}
diff --git a/components/policy/android/java_templates/PolicySwitches.java.tmpl b/components/policy/android/java_templates/PolicySwitches.java.tmpl index 0c49a772..621e6f6 100644 --- a/components/policy/android/java_templates/PolicySwitches.java.tmpl +++ b/components/policy/android/java_templates/PolicySwitches.java.tmpl
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.policy; +package org.chromium.components.policy; /** * Contains command line switches that are specific to the policy component.
diff --git a/components/policy/android/javatests/src/org/chromium/policy/test/PolicyData.java b/components/policy/android/javatests/src/org/chromium/components/policy/test/PolicyData.java similarity index 98% rename from components/policy/android/javatests/src/org/chromium/policy/test/PolicyData.java rename to components/policy/android/javatests/src/org/chromium/components/policy/test/PolicyData.java index 5a1fa70..57a6e9e 100644 --- a/components/policy/android/javatests/src/org/chromium/policy/test/PolicyData.java +++ b/components/policy/android/javatests/src/org/chromium/components/policy/test/PolicyData.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.policy.test; +package org.chromium.components.policy.test; import android.os.Bundle;
diff --git a/components/policy/android/javatests/src/org/chromium/policy/test/PolicyServiceTestSupporter.java b/components/policy/android/javatests/src/org/chromium/components/policy/test/PolicyServiceTestSupporter.java similarity index 94% rename from components/policy/android/javatests/src/org/chromium/policy/test/PolicyServiceTestSupporter.java rename to components/policy/android/javatests/src/org/chromium/components/policy/test/PolicyServiceTestSupporter.java index 0da9713..4f9021fed 100644 --- a/components/policy/android/javatests/src/org/chromium/policy/test/PolicyServiceTestSupporter.java +++ b/components/policy/android/javatests/src/org/chromium/components/policy/test/PolicyServiceTestSupporter.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.policy.test; +package org.chromium.components.policy.test; import static org.mockito.Mockito.times; @@ -11,7 +11,7 @@ import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; -import org.chromium.policy.PolicyService; +import org.chromium.components.policy.PolicyService; import java.util.ArrayList; import java.util.List;
diff --git a/components/policy/android/javatests/src/org/chromium/policy/test/annotations/Policies.java b/components/policy/android/javatests/src/org/chromium/components/policy/test/annotations/Policies.java similarity index 93% rename from components/policy/android/javatests/src/org/chromium/policy/test/annotations/Policies.java rename to components/policy/android/javatests/src/org/chromium/components/policy/test/annotations/Policies.java index cc08192..bfe25cb9 100644 --- a/components/policy/android/javatests/src/org/chromium/policy/test/annotations/Policies.java +++ b/components/policy/android/javatests/src/org/chromium/components/policy/test/annotations/Policies.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.policy.test.annotations; +package org.chromium.components.policy.test.annotations; import android.content.Context; import android.os.Bundle; @@ -13,8 +13,8 @@ import org.junit.runners.model.FrameworkMethod; import org.chromium.base.test.BaseJUnit4ClassRunner.TestHook; -import org.chromium.policy.AbstractAppRestrictionsProvider; -import org.chromium.policy.test.PolicyData; +import org.chromium.components.policy.AbstractAppRestrictionsProvider; +import org.chromium.components.policy.test.PolicyData; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; @@ -117,9 +117,8 @@ AnnotatedElement parent = (element instanceof Method) ? ((Method) element).getDeclaringClass() : ((Class<?>) element).getSuperclass(); - Map<String, PolicyData> flags = (parent == null) - ? new HashMap<String, PolicyData>() - : getPolicies(parent); + Map<String, PolicyData> flags = + (parent == null) ? new HashMap<String, PolicyData>() : getPolicies(parent); if (element.isAnnotationPresent(Policies.Add.class)) { flags.putAll(fromItems(element.getAnnotation(Policies.Add.class).value()));
diff --git a/components/policy/android/junit/src/org/chromium/policy/AbstractAppRestrictionsProviderTest.java b/components/policy/android/junit/src/org/chromium/components/policy/AbstractAppRestrictionsProviderTest.java similarity index 98% rename from components/policy/android/junit/src/org/chromium/policy/AbstractAppRestrictionsProviderTest.java rename to components/policy/android/junit/src/org/chromium/components/policy/AbstractAppRestrictionsProviderTest.java index 90ccb81..bd2dfe8 100644 --- a/components/policy/android/junit/src/org/chromium/policy/AbstractAppRestrictionsProviderTest.java +++ b/components/policy/android/junit/src/org/chromium/components/policy/AbstractAppRestrictionsProviderTest.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.policy; +package org.chromium.components.policy; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; @@ -37,7 +37,6 @@ * Minimal concrete class implementing AbstractAppRestrictionsProvider. */ private class DummyAppRestrictionsProvider extends AbstractAppRestrictionsProvider { - public DummyAppRestrictionsProvider(Context context) { super(context); } @@ -51,7 +50,6 @@ protected String getRestrictionChangeIntentAction() { return null; } - } /** @@ -132,5 +130,4 @@ provider.stopListening(); Assert.assertFalse(shadowApplication.hasReceiverForIntent(intent)); } - }
diff --git a/components/policy/android/junit/src/org/chromium/policy/CombinedPolicyProviderTest.java b/components/policy/android/junit/src/org/chromium/components/policy/CombinedPolicyProviderTest.java similarity index 99% rename from components/policy/android/junit/src/org/chromium/policy/CombinedPolicyProviderTest.java rename to components/policy/android/junit/src/org/chromium/components/policy/CombinedPolicyProviderTest.java index e19bfd9..cbf86182 100644 --- a/components/policy/android/junit/src/org/chromium/policy/CombinedPolicyProviderTest.java +++ b/components/policy/android/junit/src/org/chromium/components/policy/CombinedPolicyProviderTest.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.policy; +package org.chromium.components.policy; import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any;
diff --git a/components/policy/android/junit/src/org/chromium/policy/PolicyConverterTest.java b/components/policy/android/junit/src/org/chromium/components/policy/PolicyConverterTest.java similarity index 94% rename from components/policy/android/junit/src/org/chromium/policy/PolicyConverterTest.java rename to components/policy/android/junit/src/org/chromium/components/policy/PolicyConverterTest.java index 5fddb6f..a76e27f4 100644 --- a/components/policy/android/junit/src/org/chromium/policy/PolicyConverterTest.java +++ b/components/policy/android/junit/src/org/chromium/components/policy/PolicyConverterTest.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.policy; +package org.chromium.components.policy; import static org.mockito.Mockito.verify; @@ -40,7 +40,8 @@ /** * Test method for - * {@link org.chromium.policy.PolicyConverter#setPolicy(java.lang.String, java.lang.Object)}. + * {@link org.chromium.components.policy.PolicyConverter#setPolicy(java.lang.String, + * java.lang.Object)}. */ @Test public void testSetPolicy() {
diff --git a/components/policy/android/junit/src/org/chromium/policy/test/annotations/PoliciesTest.java b/components/policy/android/junit/src/org/chromium/components/policy/test/annotations/PoliciesTest.java similarity index 96% rename from components/policy/android/junit/src/org/chromium/policy/test/annotations/PoliciesTest.java rename to components/policy/android/junit/src/org/chromium/components/policy/test/annotations/PoliciesTest.java index 9cc56fe..879e0a0 100644 --- a/components/policy/android/junit/src/org/chromium/policy/test/annotations/PoliciesTest.java +++ b/components/policy/android/junit/src/org/chromium/components/policy/test/annotations/PoliciesTest.java
@@ -2,17 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.policy.test.annotations; +package org.chromium.components.policy.test.annotations; import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; -import org.chromium.policy.test.PolicyData; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.BlockJUnit4ClassRunner; +import org.chromium.components.policy.test.PolicyData; + import java.lang.reflect.Method; import java.util.Arrays; import java.util.HashSet;
diff --git a/components/policy/core/browser/BUILD.gn b/components/policy/core/browser/BUILD.gn index 70051a1..d56d4eb3 100644 --- a/components/policy/core/browser/BUILD.gn +++ b/components/policy/core/browser/BUILD.gn
@@ -64,16 +64,6 @@ "//url", ] - if (is_android) { - sources += [ - "android/android_combined_policy_provider.cc", - "android/android_combined_policy_provider.h", - "android/policy_converter.cc", - "android/policy_converter.h", - ] - deps += [ "//components/policy/android:jni_headers" ] - } - public_deps += [ "//components/policy/core/common:internal" ] deps += [ "//components/proxy_config", @@ -118,8 +108,6 @@ source_set("unit_tests") { testonly = true sources = [ - "android/android_combined_policy_provider_unittest.cc", - "android/policy_converter_unittest.cc", "browser_policy_connector_unittest.cc", "configuration_policy_handler_list_unittest.cc", "configuration_policy_handler_unittest.cc",
diff --git a/components/policy/core/browser/android/DEPS b/components/policy/core/browser/android/DEPS deleted file mode 100644 index 8e5f7d57..0000000 --- a/components/policy/core/browser/android/DEPS +++ /dev/null
@@ -1,3 +0,0 @@ -include_rules = [ - "+components/policy/android/jni_headers", -]
diff --git a/components/policy/core/common/BUILD.gn b/components/policy/core/common/BUILD.gn index e9fa1c0..b7c6b274 100644 --- a/components/policy/core/common/BUILD.gn +++ b/components/policy/core/common/BUILD.gn
@@ -240,6 +240,10 @@ } if (is_android) { sources += [ + "android/android_combined_policy_provider.cc", + "android/android_combined_policy_provider.h", + "android/policy_converter.cc", + "android/policy_converter.h", "android/policy_service_android.cc", "android/policy_service_android.h", ] @@ -449,7 +453,11 @@ } if (is_android) { - sources += [ "android/policy_service_android_unittest.cc" ] + sources += [ + "android/android_combined_policy_provider_unittest.cc", + "android/policy_converter_unittest.cc", + "android/policy_service_android_unittest.cc", + ] } else { sources += [ "async_policy_provider_unittest.cc" ] }
diff --git a/components/policy/core/browser/android/android_combined_policy_provider.cc b/components/policy/core/common/android/android_combined_policy_provider.cc similarity index 92% rename from components/policy/core/browser/android/android_combined_policy_provider.cc rename to components/policy/core/common/android/android_combined_policy_provider.cc index 316a8ef5..ddfcd4ee 100644 --- a/components/policy/core/browser/android/android_combined_policy_provider.cc +++ b/components/policy/core/common/android/android_combined_policy_provider.cc
@@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/policy/core/browser/android/android_combined_policy_provider.h" +#include "components/policy/core/common/android/android_combined_policy_provider.h" #include "base/android/jni_android.h" #include "base/android/jni_string.h" #include "components/policy/android/jni_headers/CombinedPolicyProvider_jni.h" -#include "components/policy/core/browser/android/policy_converter.h" +#include "components/policy/core/common/android/policy_converter.h" using base::android::AttachCurrentThread; using base::android::JavaParamRef;
diff --git a/components/policy/core/browser/android/android_combined_policy_provider.h b/components/policy/core/common/android/android_combined_policy_provider.h similarity index 87% rename from components/policy/core/browser/android/android_combined_policy_provider.h rename to components/policy/core/common/android/android_combined_policy_provider.h index 8bbdfc1..bafa14a 100644 --- a/components/policy/core/browser/android/android_combined_policy_provider.h +++ b/components/policy/core/common/android/android_combined_policy_provider.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_POLICY_CORE_BROWSER_ANDROID_ANDROID_COMBINED_POLICY_PROVIDER_H_ -#define COMPONENTS_POLICY_CORE_BROWSER_ANDROID_ANDROID_COMBINED_POLICY_PROVIDER_H_ +#ifndef COMPONENTS_POLICY_CORE_COMMON_ANDROID_ANDROID_COMBINED_POLICY_PROVIDER_H_ +#define COMPONENTS_POLICY_CORE_COMMON_ANDROID_ANDROID_COMBINED_POLICY_PROVIDER_H_ #include <jni.h> @@ -55,7 +55,6 @@ std::unique_ptr<policy::android::PolicyConverter> policy_converter_; base::android::ScopedJavaGlobalRef<jobject> java_combined_policy_provider_; - DISALLOW_COPY_AND_ASSIGN(AndroidCombinedPolicyProvider); }; @@ -63,4 +62,4 @@ } // namespace policy -#endif // COMPONENTS_POLICY_CORE_BROWSER_ANDROID_ANDROID_COMBINED_POLICY_PROVIDER_H_ +#endif // COMPONENTS_POLICY_CORE_COMMON_ANDROID_ANDROID_COMBINED_POLICY_PROVIDER_H_
diff --git a/components/policy/core/browser/android/android_combined_policy_provider_unittest.cc b/components/policy/core/common/android/android_combined_policy_provider_unittest.cc similarity index 95% rename from components/policy/core/browser/android/android_combined_policy_provider_unittest.cc rename to components/policy/core/common/android/android_combined_policy_provider_unittest.cc index 87d45e9..1cee5bc 100644 --- a/components/policy/core/browser/android/android_combined_policy_provider_unittest.cc +++ b/components/policy/core/common/android/android_combined_policy_provider_unittest.cc
@@ -8,15 +8,15 @@ #include "base/android/jni_string.h" #include "base/android/scoped_java_ref.h" #include "base/values.h" -#include "components/policy/core/browser/android/android_combined_policy_provider.h" -#include "components/policy/core/browser/android/policy_converter.h" +#include "components/policy/core/common/android/android_combined_policy_provider.h" +#include "components/policy/core/common/android/policy_converter.h" #include "components/policy/core/common/policy_bundle.h" #include "components/policy/core/common/schema.h" #include "components/policy/core/common/schema_registry.h" #include "testing/gtest/include/gtest/gtest.h" -using base::android::ConvertUTF8ToJavaString; using base::android::AttachCurrentThread; +using base::android::ConvertUTF8ToJavaString; using base::android::ScopedJavaLocalRef; namespace policy {
diff --git a/components/policy/core/browser/android/policy_converter.cc b/components/policy/core/common/android/policy_converter.cc similarity index 98% rename from components/policy/core/browser/android/policy_converter.cc rename to components/policy/core/common/android/policy_converter.cc index 18dd904..566eb42f 100644 --- a/components/policy/core/browser/android/policy_converter.cc +++ b/components/policy/core/common/android/policy_converter.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/policy/core/browser/android/policy_converter.h" +#include "components/policy/core/common/android/policy_converter.h" #include <utility> #include <vector>
diff --git a/components/policy/core/browser/android/policy_converter.h b/components/policy/core/common/android/policy_converter.h similarity index 93% rename from components/policy/core/browser/android/policy_converter.h rename to components/policy/core/common/android/policy_converter.h index 3d6bebe..e4473a8c 100644 --- a/components/policy/core/browser/android/policy_converter.h +++ b/components/policy/core/common/android/policy_converter.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_POLICY_CORE_BROWSER_ANDROID_POLICY_CONVERTER_H -#define COMPONENTS_POLICY_CORE_BROWSER_ANDROID_POLICY_CONVERTER_H +#ifndef COMPONENTS_POLICY_CORE_COMMON_ANDROID_POLICY_CONVERTER_H_ +#define COMPONENTS_POLICY_CORE_COMMON_ANDROID_POLICY_CONVERTER_H_ #include <jni.h> @@ -89,4 +89,4 @@ } // namespace android } // namespace policy -#endif // COMPONENTS_POLICY_CORE_BROWSER_ANDROID_POLICY_CONVERTER_H +#endif // COMPONENTS_POLICY_CORE_COMMON_ANDROID_POLICY_CONVERTER_H_
diff --git a/components/policy/core/browser/android/policy_converter_unittest.cc b/components/policy/core/common/android/policy_converter_unittest.cc similarity index 98% rename from components/policy/core/browser/android/policy_converter_unittest.cc rename to components/policy/core/common/android/policy_converter_unittest.cc index 4c0487ff..6d76986 100644 --- a/components/policy/core/browser/android/policy_converter_unittest.cc +++ b/components/policy/core/common/android/policy_converter_unittest.cc
@@ -9,7 +9,7 @@ #include "base/android/jni_string.h" #include "base/json/json_writer.h" #include "base/values.h" -#include "components/policy/core/browser/android/policy_converter.h" +#include "components/policy/core/common/android/policy_converter.h" #include "components/policy/core/common/schema.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/components/printing/test/print_render_frame_helper_browsertest.cc b/components/printing/test/print_render_frame_helper_browsertest.cc index ed14aaf..3aa5aa8 100644 --- a/components/printing/test/print_render_frame_helper_browsertest.cc +++ b/components/printing/test/print_render_frame_helper_browsertest.cc
@@ -167,7 +167,7 @@ ~FakePrintPreviewUI() override = default; mojo::PendingAssociatedRemote<mojom::PrintPreviewUI> BindReceiver() { - return receiver_.BindNewEndpointAndPassDedicatedRemoteForTesting(); + return receiver_.BindNewEndpointAndPassDedicatedRemote(); } void SetQuitClosure(base::OnceClosure quit_closure) { quit_closure_ = std::move(quit_closure);
diff --git a/components/security_state/core/features.cc b/components/security_state/core/features.cc index 9711685..9dcd8b9 100644 --- a/components/security_state/core/features.cc +++ b/components/security_state/core/features.cc
@@ -21,8 +21,5 @@ const base::Feature kSafetyTipUI{"SafetyTip", base::FEATURE_DISABLED_BY_DEFAULT}; -const base::Feature kPassiveMixedContentWarning{ - "PassiveMixedContentWarning", base::FEATURE_ENABLED_BY_DEFAULT}; - } // namespace features } // namespace security_state
diff --git a/components/security_state/core/features.h b/components/security_state/core/features.h index 263a2ac..59be999 100644 --- a/components/security_state/core/features.h +++ b/components/security_state/core/features.h
@@ -44,11 +44,6 @@ COMPONENT_EXPORT(SECURITY_STATE_FEATURES) extern const base::Feature kSafetyTipUI; -// This feature causes passive mixed content to show the not secure warning -// chip. Does not affect mixed forms. -COMPONENT_EXPORT(SECURITY_STATE_FEATURES) -extern const base::Feature kPassiveMixedContentWarning; - } // namespace features } // namespace security_state
diff --git a/components/security_state/core/security_state.cc b/components/security_state/core/security_state.cc index 03699da3..af0b7c5 100644 --- a/components/security_state/core/security_state.cc +++ b/components/security_state/core/security_state.cc
@@ -210,10 +210,7 @@ DCHECK(!visible_security_state.ran_content_with_cert_errors); if (visible_security_state.displayed_mixed_content) { - if (base::FeatureList::IsEnabled(features::kPassiveMixedContentWarning)) { - return kDisplayedInsecureContentWarningLevel; - } - return kDisplayedInsecureContentLevel; + return kDisplayedInsecureContentWarningLevel; } if ((visible_security_state.contained_mixed_form &&
diff --git a/components/security_state/core/security_state_unittest.cc b/components/security_state/core/security_state_unittest.cc index bc631f2..33132a55 100644 --- a/components/security_state/core/security_state_unittest.cc +++ b/components/security_state/core/security_state_unittest.cc
@@ -302,10 +302,7 @@ // Verify that passive mixed content downgrades the security level. helper.set_contained_mixed_form(false); helper.set_displayed_mixed_content(true); - SecurityLevel expected_passive_level = - base::FeatureList::IsEnabled(features::kPassiveMixedContentWarning) - ? WARNING - : NONE; + SecurityLevel expected_passive_level = WARNING; EXPECT_EQ(expected_passive_level, helper.GetSecurityLevel()); // Ensure that active mixed content downgrades the security level.
diff --git a/components/services/app_service/public/cpp/intent_util.cc b/components/services/app_service/public/cpp/intent_util.cc index 2be1e951..c815d89 100644 --- a/components/services/app_service/public/cpp/intent_util.cc +++ b/components/services/app_service/public/cpp/intent_util.cc
@@ -167,6 +167,15 @@ return intent; } +apps::mojom::IntentPtr CreateShareIntentFromText( + const std::string& share_text) { + auto intent = apps::mojom::Intent::New(); + intent->action = kIntentActionSend; + intent->mime_type = "text/plain"; + intent->share_text = share_text; + return intent; +} + bool ConditionValueMatches( const std::string& value, const apps::mojom::ConditionValuePtr& condition_value) {
diff --git a/components/services/app_service/public/cpp/intent_util.h b/components/services/app_service/public/cpp/intent_util.h index 753ba06..fbb97bb 100644 --- a/components/services/app_service/public/cpp/intent_util.h +++ b/components/services/app_service/public/cpp/intent_util.h
@@ -35,6 +35,9 @@ const std::string& mime_type, const GURL& drive_share_url); +// Create an intent struct from URL. +apps::mojom::IntentPtr CreateShareIntentFromText(const std::string& share_text); + // Return true if |value| matches with the |condition_value|, based on the // pattern match type in the |condition_value|. bool ConditionValueMatches(
diff --git a/components/services/app_service/public/mojom/types.mojom b/components/services/app_service/public/mojom/types.mojom index d8381d0..f327cf9 100644 --- a/components/services/app_service/public/mojom/types.mojom +++ b/components/services/app_service/public/mojom/types.mojom
@@ -329,6 +329,7 @@ // The Drive share URL, this is only filled if the intent contains a file // from Google Drive. url.mojom.Url? drive_share_url; + string? share_text; // Text to share. e.g. Share link to other app. }; // Represents a group of |app_ids| that is no longer preferred app of their
diff --git a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc index bbee181..65ae5b3 100644 --- a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc +++ b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc
@@ -309,6 +309,9 @@ ActivationDecision* decision) override { return effective_activation_level; } + void OnAdsViolationTriggered( + content::RenderFrameHost* rfh, + mojom::AdsViolation triggered_violation) override {} ContentSubresourceFilterThrottleManager* throttle_manager() { return throttle_manager_.get();
diff --git a/components/subresource_filter/content/browser/subresource_filter_client.h b/components/subresource_filter/content/browser/subresource_filter_client.h index ce82afe..4567548 100644 --- a/components/subresource_filter/content/browser/subresource_filter_client.h +++ b/components/subresource_filter/content/browser/subresource_filter_client.h
@@ -8,6 +8,7 @@ #include "components/subresource_filter/content/browser/verified_ruleset_dealer.h" #include "components/subresource_filter/core/common/activation_decision.h" #include "components/subresource_filter/core/mojom/subresource_filter.mojom.h" +#include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" namespace content { @@ -37,6 +38,11 @@ content::NavigationHandle* navigation_handle, mojom::ActivationLevel initial_activation_level, subresource_filter::ActivationDecision* decision) = 0; + + // Called on the subresource filter client when an ads violation is detected. + virtual void OnAdsViolationTriggered( + content::RenderFrameHost* rfh, + mojom::AdsViolation triggered_violation) = 0; }; } // namespace subresource_filter
diff --git a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc index b1b0d48..4435878e 100644 --- a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc +++ b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc
@@ -87,6 +87,9 @@ MOCK_METHOD0(ShowNotification, void()); MOCK_METHOD0(ForceActivationInCurrentWebContents, bool()); + MOCK_METHOD2(OnAdsViolationTriggered, + void(content::RenderFrameHost*, + subresource_filter::mojom::AdsViolation)); void AllowlistInCurrentWebContents(const GURL& url) { ASSERT_TRUE(url.SchemeIsHTTPOrHTTPS());
diff --git a/components/subresource_filter/core/browser/subresource_filter_features.cc b/components/subresource_filter/core/browser/subresource_filter_features.cc index f465de7..60f1eaf 100644 --- a/components/subresource_filter/core/browser/subresource_filter_features.cc +++ b/components/subresource_filter/core/browser/subresource_filter_features.cc
@@ -236,6 +236,13 @@ const base::Feature kFilterAdsOnAbusiveSites{"FilterAdsOnAbusiveSites", base::FEATURE_ENABLED_BY_DEFAULT}; +const base::Feature kAdsInterventionsEnforced{ + "AdsInterventionsEnforced", base::FEATURE_DISABLED_BY_DEFAULT}; + +const base::FeatureParam<base::TimeDelta> kAdsInterventionDuration = { + &kAdsInterventionsEnforced, "kAdsInterventionDuration", + base::TimeDelta::FromDays(3)}; + // Legacy name `activation_state` is used in variation parameters. const char kActivationLevelParameterName[] = "activation_state"; const char kActivationLevelDryRun[] = "dryrun";
diff --git a/components/subresource_filter/core/browser/subresource_filter_features.h b/components/subresource_filter/core/browser/subresource_filter_features.h index 0bcc52b4..cc73b58 100644 --- a/components/subresource_filter/core/browser/subresource_filter_features.h +++ b/components/subresource_filter/core/browser/subresource_filter_features.h
@@ -186,6 +186,12 @@ // Enables the blocking of ads on sites that are abusive. extern const base::Feature kFilterAdsOnAbusiveSites; +// Enables the blocking of ads on sites that have ads violations. +extern const base::Feature kAdsInterventionsEnforced; + +// The duration that an ads intervention is active for. +extern const base::FeatureParam<base::TimeDelta> kAdsInterventionDuration; + // Name/values of the variation parameter controlling maximum activation level. extern const char kActivationLevelParameterName[]; extern const char kActivationLevelDryRun[];
diff --git a/components/subresource_filter/core/mojom/subresource_filter.mojom b/components/subresource_filter/core/mojom/subresource_filter.mojom index 187170fb..7231e4a0 100644 --- a/components/subresource_filter/core/mojom/subresource_filter.mojom +++ b/components/subresource_filter/core/mojom/subresource_filter.mojom
@@ -12,6 +12,11 @@ kEnabled }; +// Enumerates which ads violations are recorded for a page. +enum AdsViolation { + kMobileAdDensityByHeightAbove30, +}; + struct ActivationState { // The degree to which subresource filtering is activated for the page load. ActivationLevel activation_level = kDisabled;
diff --git a/components/sync/engine/engine_components_factory_impl.cc b/components/sync/engine/engine_components_factory_impl.cc index 98be1f5..c035cf5 100644 --- a/components/sync/engine/engine_components_factory_impl.cc +++ b/components/sync/engine/engine_components_factory_impl.cc
@@ -18,8 +18,6 @@ const Switches& switches) : switches_(switches) {} -EngineComponentsFactoryImpl::~EngineComponentsFactoryImpl() {} - std::unique_ptr<SyncScheduler> EngineComponentsFactoryImpl::BuildScheduler( const std::string& name, SyncCycleContext* context,
diff --git a/components/sync/engine/engine_components_factory_impl.h b/components/sync/engine/engine_components_factory_impl.h index 74e3b737..b02d23e 100644 --- a/components/sync/engine/engine_components_factory_impl.h +++ b/components/sync/engine/engine_components_factory_impl.h
@@ -9,7 +9,6 @@ #include <string> #include <vector> -#include "base/macros.h" #include "components/sync/engine/engine_components_factory.h" namespace syncer { @@ -19,7 +18,10 @@ class EngineComponentsFactoryImpl : public EngineComponentsFactory { public: explicit EngineComponentsFactoryImpl(const Switches& switches); - ~EngineComponentsFactoryImpl() override; + EngineComponentsFactoryImpl(const EngineComponentsFactoryImpl&) = delete; + EngineComponentsFactoryImpl& operator=(const EngineComponentsFactoryImpl&) = + delete; + ~EngineComponentsFactoryImpl() override = default; std::unique_ptr<SyncScheduler> BuildScheduler( const std::string& name, @@ -41,7 +43,6 @@ private: const Switches switches_; - DISALLOW_COPY_AND_ASSIGN(EngineComponentsFactoryImpl); }; } // namespace syncer
diff --git a/components/sync/engine/test_engine_components_factory.cc b/components/sync/engine/test_engine_components_factory.cc index 00fec435..2532a44d 100644 --- a/components/sync/engine/test_engine_components_factory.cc +++ b/components/sync/engine/test_engine_components_factory.cc
@@ -9,10 +9,6 @@ namespace syncer { -TestEngineComponentsFactory::TestEngineComponentsFactory() {} - -TestEngineComponentsFactory::~TestEngineComponentsFactory() {} - std::unique_ptr<SyncScheduler> TestEngineComponentsFactory::BuildScheduler( const std::string& name, SyncCycleContext* context,
diff --git a/components/sync/engine/test_engine_components_factory.h b/components/sync/engine/test_engine_components_factory.h index 982ec7a..1bd24e0 100644 --- a/components/sync/engine/test_engine_components_factory.h +++ b/components/sync/engine/test_engine_components_factory.h
@@ -9,15 +9,17 @@ #include <string> #include <vector> -#include "base/macros.h" #include "components/sync/engine/engine_components_factory.h" namespace syncer { class TestEngineComponentsFactory : public EngineComponentsFactory { public: - TestEngineComponentsFactory(); - ~TestEngineComponentsFactory() override; + TestEngineComponentsFactory() = default; + TestEngineComponentsFactory(const TestEngineComponentsFactory&) = delete; + TestEngineComponentsFactory& operator=(const TestEngineComponentsFactory&) = + delete; + ~TestEngineComponentsFactory() override = default; std::unique_ptr<SyncScheduler> BuildScheduler( const std::string& name, @@ -36,9 +38,6 @@ const std::string& store_birthday, const std::string& bag_of_chips, base::TimeDelta poll_interval) override; - - private: - DISALLOW_COPY_AND_ASSIGN(TestEngineComponentsFactory); }; } // namespace syncer
diff --git a/components/test/components_test_suite.cc b/components/test/components_test_suite.cc index 0a1776f..b07c5c6 100644 --- a/components/test/components_test_suite.cc +++ b/components/test/components_test_suite.cc
@@ -5,6 +5,7 @@ #include "components/test/components_test_suite.h" #include <memory> +#include <utility> #include "base/bind.h" #include "base/command_line.h" @@ -49,6 +50,8 @@ class ComponentsTestSuite : public base::TestSuite { public: ComponentsTestSuite(int argc, char** argv) : base::TestSuite(argc, argv) {} + ComponentsTestSuite(const ComponentsTestSuite&) = delete; + ComponentsTestSuite& operator=(const ComponentsTestSuite&) = delete; private: void Initialize() override { @@ -111,14 +114,16 @@ #if defined(OS_WIN) base::win::ScopedCOMInitializer com_initializer_; #endif - - DISALLOW_COPY_AND_ASSIGN(ComponentsTestSuite); }; class ComponentsUnitTestEventListener : public testing::EmptyTestEventListener { public: - ComponentsUnitTestEventListener() {} - ~ComponentsUnitTestEventListener() override {} + ComponentsUnitTestEventListener() = default; + ComponentsUnitTestEventListener(const ComponentsUnitTestEventListener&) = + delete; + ComponentsUnitTestEventListener& operator=( + const ComponentsUnitTestEventListener&) = delete; + ~ComponentsUnitTestEventListener() override = default; void OnTestStart(const testing::TestInfo& test_info) override { #if defined(OS_IOS) @@ -142,8 +147,6 @@ #else std::unique_ptr<content::TestContentClientInitializer> content_initializer_; #endif - - DISALLOW_COPY_AND_ASSIGN(ComponentsUnitTestEventListener); }; } // namespace
diff --git a/components/test/ios_components_test_initializer.h b/components/test/ios_components_test_initializer.h index 59bcc0038..3e49463 100644 --- a/components/test/ios_components_test_initializer.h +++ b/components/test/ios_components_test_initializer.h
@@ -7,8 +7,6 @@ #include <memory> -#include "base/macros.h" - namespace network { class TestNetworkConnectionTracker; } @@ -17,13 +15,14 @@ class IosComponentsTestInitializer { public: IosComponentsTestInitializer(); + IosComponentsTestInitializer(const IosComponentsTestInitializer&) = delete; + IosComponentsTestInitializer& operator=(const IosComponentsTestInitializer&) = + delete; virtual ~IosComponentsTestInitializer(); private: std::unique_ptr<network::TestNetworkConnectionTracker> network_connection_tracker_; - - DISALLOW_COPY_AND_ASSIGN(IosComponentsTestInitializer); }; #endif // COMPONENTS_TEST_IOS_COMPONENTS_TEST_INITIALIZER_H_
diff --git a/components/variations/android/BUILD.gn b/components/variations/android/BUILD.gn index b913ba68..0897cd1 100644 --- a/components/variations/android/BUILD.gn +++ b/components/variations/android/BUILD.gn
@@ -9,7 +9,6 @@ "//base:base_java", "//base:jni_java", "//third_party/android_deps:androidx_annotation_annotation_java", - "//third_party/android_deps:androidx_legacy_legacy_support_core_utils_java", ] annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ] sources = [
diff --git a/components/variations/variations_associated_data.h b/components/variations/variations_associated_data.h index 33e1ccc..a34aeb1 100644 --- a/components/variations/variations_associated_data.h +++ b/components/variations/variations_associated_data.h
@@ -64,9 +64,10 @@ // transmitted via the X-Client-Data header. These IDs are transmitted in // first- and third-party contexts. GOOGLE_WEB_PROPERTIES_ANY_CONTEXT, - // Used when kRestrictGoogleWebVisibility is enabled. The IDs in this - // collection are used by Google web properties and are transmitted via the - // X-Client-Data header. These IDs are transmitted in first-party contexts. + // The IDs in this collection are used by Google web properties and are + // transmitted via the X-Client-Data header. When kRestrictGoogleWebVisibility + // is enabled, these IDs are transmitted in only first-party contexts; + // otherwise, these IDs are transmitted in first- and third-party contexts. GOOGLE_WEB_PROPERTIES_FIRST_PARTY, // This collection is used by Google web properties for signed in users only, // transmitted through the X-Client-Data header. @@ -75,10 +76,11 @@ // server-side experimental behavior and are transmitted via the X-Client-Data // header. These IDs are transmitted in first- and third-party contexts. GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT, - // Used when kRestrictGoogleWebVisibility is enabled. The IDs in this - // collection are used by Google web properties to trigger server-side - // experimental behavior and are transmitted via the X-Client-Data header. - // These IDs are transmitted in first-party contexts. + // The IDs in this collection are used by Google web properties to trigger + // server-side experimental behavior and are transmitted via the X-Client-Data + // header. When kRestrictGoogleWebVisibility is enabled, these IDs are + // transmitted in only first-party contexts; otherwise, these IDs are + // transmitted in first- and third-party contexts. GOOGLE_WEB_PROPERTIES_TRIGGER_FIRST_PARTY, // This collection is used by the Google App and is passed at the time // the cross-app communication is triggered.
diff --git a/components/variations/variations_ids_provider.cc b/components/variations/variations_ids_provider.cc index 5f1a1d3..eff15a8 100644 --- a/components/variations/variations_ids_provider.cc +++ b/components/variations/variations_ids_provider.cc
@@ -7,9 +7,6 @@ #include <stddef.h> #include <algorithm> -#include <set> -#include <string> -#include <vector> #include "base/base64.h" #include "base/memory/singleton.h" @@ -55,44 +52,44 @@ return variation_ids_header_copy; } -std::string VariationsIdsProvider::GetVariationsString(IDCollectionKey key) { - InitVariationIDsCacheIfNeeded(); - +std::string VariationsIdsProvider::GetVariationsString( + const std::set<IDCollectionKey>& keys) { // Construct a space-separated string with leading and trailing spaces from - // the variations set. Note: The ids in it will be in sorted order per the + // the VariationIDs set. The IDs in the string are in sorted order as per the // std::set contract. std::string ids_string = " "; - { - base::AutoLock scoped_lock(lock_); - for (const VariationIDEntry& entry : GetAllVariationIds()) { - if (entry.second == key) { - ids_string.append(base::NumberToString(entry.first)); - ids_string.push_back(' '); - } - } + + for (const VariationID& id : GetVariationsVector(keys)) { + ids_string.append(base::NumberToString(id)); + ids_string.push_back(' '); } + return ids_string; } std::string VariationsIdsProvider::GetGoogleAppVariationsString() { - return GetVariationsString(GOOGLE_APP); + return GetVariationsString({GOOGLE_APP}); } std::string VariationsIdsProvider::GetVariationsString() { - return GetVariationsString(GOOGLE_WEB_PROPERTIES_ANY_CONTEXT); + return GetVariationsString( + {GOOGLE_WEB_PROPERTIES_ANY_CONTEXT, GOOGLE_WEB_PROPERTIES_FIRST_PARTY}); } std::vector<VariationID> VariationsIdsProvider::GetVariationsVector( - IDCollectionKey key) { - return GetVariationsVectorImpl(std::set<IDCollectionKey>{key}); + const std::set<IDCollectionKey>& keys) { + return GetVariationsVectorImpl(keys); } std::vector<VariationID> VariationsIdsProvider::GetVariationsVectorForWebPropertiesKeys() { const std::set<IDCollectionKey> web_properties_keys{ - variations::GOOGLE_WEB_PROPERTIES_ANY_CONTEXT, - variations::GOOGLE_WEB_PROPERTIES_SIGNED_IN, - variations::GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT}; + GOOGLE_WEB_PROPERTIES_ANY_CONTEXT, + GOOGLE_WEB_PROPERTIES_FIRST_PARTY, + GOOGLE_WEB_PROPERTIES_SIGNED_IN, + GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT, + GOOGLE_WEB_PROPERTIES_TRIGGER_FIRST_PARTY, + }; return GetVariationsVectorImpl(web_properties_keys); } @@ -168,11 +165,7 @@ const std::string& group_name) { base::AutoLock scoped_lock(lock_); const size_t old_size = variation_ids_set_.size(); - CacheVariationsId(trial_name, group_name, GOOGLE_WEB_PROPERTIES_ANY_CONTEXT); - CacheVariationsId(trial_name, group_name, GOOGLE_WEB_PROPERTIES_SIGNED_IN); - CacheVariationsId(trial_name, group_name, - GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT); - CacheVariationsId(trial_name, group_name, GOOGLE_APP); + CacheVariationsId(trial_name, group_name); if (variation_ids_set_.size() != old_size) UpdateVariationIDsHeaderValue(); } @@ -215,13 +208,7 @@ base::FieldTrialList::GetActiveFieldTrialGroups(&initial_groups); for (const auto& entry : initial_groups) { - CacheVariationsId(entry.trial_name, entry.group_name, - GOOGLE_WEB_PROPERTIES_ANY_CONTEXT); - CacheVariationsId(entry.trial_name, entry.group_name, - GOOGLE_WEB_PROPERTIES_SIGNED_IN); - CacheVariationsId(entry.trial_name, entry.group_name, - GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT); - CacheVariationsId(entry.trial_name, entry.group_name, GOOGLE_APP); + CacheVariationsId(entry.trial_name, entry.group_name); } UpdateVariationIDsHeaderValue(); @@ -229,11 +216,13 @@ } void VariationsIdsProvider::CacheVariationsId(const std::string& trial_name, - const std::string& group_name, - IDCollectionKey key) { - const VariationID id = GetGoogleVariationID(key, trial_name, group_name); - if (id != EMPTY_ID) - variation_ids_set_.insert(VariationIDEntry(id, key)); + const std::string& group_name) { + for (int i = 0; i < ID_COLLECTION_COUNT; ++i) { + IDCollectionKey key = static_cast<IDCollectionKey>(i); + const VariationID id = GetGoogleVariationID(key, trial_name, group_name); + if (id != EMPTY_ID) + variation_ids_set_.insert(VariationIDEntry(id, key)); + } } void VariationsIdsProvider::UpdateVariationIDsHeaderValue() { @@ -270,16 +259,38 @@ case GOOGLE_WEB_PROPERTIES_ANY_CONTEXT: proto.add_variation_id(entry.first); break; + case GOOGLE_WEB_PROPERTIES_FIRST_PARTY: + if (base::FeatureList::IsEnabled( + internal::kRestrictGoogleWebVisibility)) { + // TODO(crbug/1094303): Send fewer VariationIDs in third-party + // contexts by excluding IDs associated with + // GOOGLE_WEB_PROPERTIES_FIRST_PARTY. + break; + } + // When the feature is not enabled, treat VariationIDs associated with + // GOOGLE_WEB_PROPERTIES_FIRST_PARTY in the same way as those + // associated with GOOGLE_WEB_PROPERTIES_ANY_CONTEXT. + proto.add_variation_id(entry.first); + break; case GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT: proto.add_trigger_variation_id(entry.first); break; + case GOOGLE_WEB_PROPERTIES_TRIGGER_FIRST_PARTY: + if (base::FeatureList::IsEnabled( + internal::kRestrictGoogleWebVisibility)) { + // TODO(crbug/1094303): Send fewer VariationIDs in third-party + // contexts by excluding IDs associated with + // GOOGLE_WEB_PROPERTIES_FIRST_PARTY. + break; + } + // When the feature is not enabled, treat VariationIDs associated with + // GOOGLE_WEB_PROPERTIES_TRIGGER_FIRST_PARTY in the same way as those + // associated with GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT. + proto.add_trigger_variation_id(entry.first); + break; case GOOGLE_APP: // These IDs should not be added into Google Web headers. break; - case GOOGLE_WEB_PROPERTIES_FIRST_PARTY: - case GOOGLE_WEB_PROPERTIES_TRIGGER_FIRST_PARTY: - // TODO(crbug/1094303): Add support for the above IDCollectionKeys. - break; case ID_COLLECTION_COUNT: // This case included to get full enum coverage for switch, so that // new enums introduce compiler warnings. Nothing to do for this. @@ -385,7 +396,7 @@ result.push_back(entry.first); } - // Make sure each enry is unique. As a side-effect, the output will be sorted. + // Make sure each entry is unique. As a side effect, the output is sorted. std::sort(result.begin(), result.end()); result.erase(std::unique(result.begin(), result.end()), result.end()); return result;
diff --git a/components/variations/variations_ids_provider.h b/components/variations/variations_ids_provider.h index 1743c9a..7be7567 100644 --- a/components/variations/variations_ids_provider.h +++ b/components/variations/variations_ids_provider.h
@@ -64,9 +64,10 @@ // apps. std::string GetGoogleAppVariationsString(); - // Returns the collection of variation ids matching the given |key|. Each - // entry in the returned vector will be unique. - std::vector<VariationID> GetVariationsVector(IDCollectionKey key); + // Returns the collection of VariationIDs associated with |keys|. Each entry + // in the returned vector is unique. + std::vector<VariationID> GetVariationsVector( + const std::set<IDCollectionKey>& keys); // Returns the collection of variations ids for all Google Web Properties // related keys. @@ -132,7 +133,7 @@ // Returns a space-separated string containing the list of current active // variations (as would be reported in the |variation_id| repeated field of // the ClientVariations proto) for a given ID collection. - std::string GetVariationsString(IDCollectionKey key); + std::string GetVariationsString(const std::set<IDCollectionKey>& keys); // base::FieldTrialList::Observer: // This will add the variation ID associated with |trial_name| and @@ -149,11 +150,10 @@ // new variation IDs. void InitVariationIDsCacheIfNeeded(); - // Looks up the associated id for the given trial/group and adds an entry for - // it to |variation_ids_set_| if found. + // Looks up the VariationID associated with |trial_name| and |group_name|, and + // if found, adds an entry for it to |variation_ids_set_|. void CacheVariationsId(const std::string& trial_name, - const std::string& group_name, - IDCollectionKey key); + const std::string& group_name); // Takes whatever is currently in |variation_ids_set_| and recreates // |variation_ids_header_| with it. Assumes the the |lock_| is currently
diff --git a/components/variations/variations_ids_provider_unittest.cc b/components/variations/variations_ids_provider_unittest.cc index 9be52dc5..cabc214 100644 --- a/components/variations/variations_ids_provider_unittest.cc +++ b/components/variations/variations_ids_provider_unittest.cc
@@ -165,17 +165,25 @@ const std::string default_name = "default"; scoped_refptr<base::FieldTrial> trial_1(CreateTrialAndAssociateId( - "t1", default_name, GOOGLE_WEB_PROPERTIES_ANY_CONTEXT, 123)); + "t1", default_name, GOOGLE_WEB_PROPERTIES_ANY_CONTEXT, 11)); ASSERT_EQ(default_name, trial_1->group_name()); scoped_refptr<base::FieldTrial> trial_2(CreateTrialAndAssociateId( - "t2", default_name, GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT, 456)); + "t2", default_name, GOOGLE_WEB_PROPERTIES_FIRST_PARTY, 22)); ASSERT_EQ(default_name, trial_2->group_name()); scoped_refptr<base::FieldTrial> trial_3(CreateTrialAndAssociateId( - "t3", default_name, GOOGLE_WEB_PROPERTIES_SIGNED_IN, 789)); + "t3", default_name, GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT, 33)); ASSERT_EQ(default_name, trial_3->group_name()); + scoped_refptr<base::FieldTrial> trial_4(CreateTrialAndAssociateId( + "t4", default_name, GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT, 44)); + ASSERT_EQ(default_name, trial_4->group_name()); + + scoped_refptr<base::FieldTrial> trial_5(CreateTrialAndAssociateId( + "t5", default_name, GOOGLE_WEB_PROPERTIES_SIGNED_IN, 55)); + ASSERT_EQ(default_name, trial_5->group_name()); + // Run the message loop to make sure OnFieldTrialGroupFinalized is called for // the two field trials. base::RunLoop().RunUntilIdle(); @@ -186,10 +194,12 @@ std::set<VariationID> variation_ids; std::set<VariationID> trigger_ids; ASSERT_TRUE(ExtractVariationIds(variations, &variation_ids, &trigger_ids)); - EXPECT_EQ(1U, variation_ids.size()); - EXPECT_TRUE(variation_ids.find(123) != variation_ids.end()); - EXPECT_EQ(1U, trigger_ids.size()); - EXPECT_TRUE(trigger_ids.find(456) != trigger_ids.end()); + EXPECT_EQ(2U, variation_ids.size()); + EXPECT_TRUE(variation_ids.find(11) != variation_ids.end()); + EXPECT_TRUE(variation_ids.find(22) != variation_ids.end()); + EXPECT_EQ(2U, trigger_ids.size()); + EXPECT_TRUE(trigger_ids.find(33) != trigger_ids.end()); + EXPECT_TRUE(trigger_ids.find(44) != trigger_ids.end()); } // Now, get signed-in ids. @@ -198,22 +208,28 @@ std::set<VariationID> variation_ids; std::set<VariationID> trigger_ids; ASSERT_TRUE(ExtractVariationIds(variations, &variation_ids, &trigger_ids)); - EXPECT_EQ(2U, variation_ids.size()); - EXPECT_TRUE(variation_ids.find(123) != variation_ids.end()); - EXPECT_TRUE(variation_ids.find(789) != variation_ids.end()); - EXPECT_EQ(1U, trigger_ids.size()); - EXPECT_TRUE(trigger_ids.find(456) != trigger_ids.end()); + EXPECT_EQ(3U, variation_ids.size()); + EXPECT_TRUE(variation_ids.find(11) != variation_ids.end()); + EXPECT_TRUE(variation_ids.find(22) != variation_ids.end()); + EXPECT_TRUE(variation_ids.find(55) != variation_ids.end()); + EXPECT_EQ(2U, trigger_ids.size()); + EXPECT_TRUE(trigger_ids.find(33) != trigger_ids.end()); + EXPECT_TRUE(trigger_ids.find(44) != trigger_ids.end()); } } TEST_F(VariationsIdsProviderTest, GetGoogleAppVariationsString) { - // All GOOGLE_WEB_PROPERTIES(_X) ids shouldn't be included. - CreateTrialAndAssociateId("t1", "g1", GOOGLE_WEB_PROPERTIES_ANY_CONTEXT, 123); - CreateTrialAndAssociateId("t2", "g2", GOOGLE_WEB_PROPERTIES_ANY_CONTEXT, 124); - CreateTrialAndAssociateId("t3", "g3", GOOGLE_WEB_PROPERTIES_SIGNED_IN, 125); + // No GOOGLE_WEB_PROPERTIES(_X) ids should be included. + CreateTrialAndAssociateId("t1", "g1", + GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT, 121); + CreateTrialAndAssociateId("t2", "g2", + GOOGLE_WEB_PROPERTIES_TRIGGER_FIRST_PARTY, 122); + CreateTrialAndAssociateId("t3", "g3", GOOGLE_WEB_PROPERTIES_ANY_CONTEXT, 123); + CreateTrialAndAssociateId("t4", "g4", GOOGLE_WEB_PROPERTIES_FIRST_PARTY, 124); + CreateTrialAndAssociateId("t5", "g5", GOOGLE_WEB_PROPERTIES_SIGNED_IN, 125); // GOOGLE_APP ids should be included. - CreateTrialAndAssociateId("t4", "g4", GOOGLE_APP, 126); + CreateTrialAndAssociateId("t6", "g6", GOOGLE_APP, 126); VariationsIdsProvider provider; provider.ForceVariationIds({"100", "200"}, ""); @@ -221,12 +237,21 @@ } TEST_F(VariationsIdsProviderTest, GetVariationsString) { - CreateTrialAndAssociateId("t1", "g1", GOOGLE_WEB_PROPERTIES_ANY_CONTEXT, 123); - CreateTrialAndAssociateId("t2", "g2", GOOGLE_WEB_PROPERTIES_ANY_CONTEXT, 124); - // SIGNED_IN ids shouldn't be included. - CreateTrialAndAssociateId("t3", "g3", GOOGLE_WEB_PROPERTIES_SIGNED_IN, 125); + // Trigger ids shouldn't be included. + CreateTrialAndAssociateId("t1", "g1", + GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT, 121); + CreateTrialAndAssociateId("t2", "g2", + GOOGLE_WEB_PROPERTIES_TRIGGER_FIRST_PARTY, 122); + + // These ids should be included. + CreateTrialAndAssociateId("t3", "g3", GOOGLE_WEB_PROPERTIES_ANY_CONTEXT, 123); + CreateTrialAndAssociateId("t4", "g4", GOOGLE_WEB_PROPERTIES_FIRST_PARTY, 124); + + // Signed-in ids shouldn't be included. + CreateTrialAndAssociateId("t5", "g5", GOOGLE_WEB_PROPERTIES_SIGNED_IN, 125); + // GOOGLE_APP ids shouldn't be included. - CreateTrialAndAssociateId("t4", "g4", GOOGLE_APP, 126); + CreateTrialAndAssociateId("t6", "g6", GOOGLE_APP, 126); VariationsIdsProvider provider; provider.ForceVariationIds({"100", "200"}, ""); @@ -235,66 +260,82 @@ TEST_F(VariationsIdsProviderTest, GetVariationsVector) { CreateTrialAndAssociateId("t1", "g1", GOOGLE_WEB_PROPERTIES_ANY_CONTEXT, 121); - CreateTrialAndAssociateId("t2", "g2", GOOGLE_WEB_PROPERTIES_ANY_CONTEXT, 122); - CreateTrialAndAssociateId("t3", "g3", - GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT, 123); + CreateTrialAndAssociateId("t3", "g3", GOOGLE_WEB_PROPERTIES_FIRST_PARTY, 122); CreateTrialAndAssociateId("t4", "g4", - GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT, 124); - CreateTrialAndAssociateId("t5", "g5", GOOGLE_WEB_PROPERTIES_SIGNED_IN, 125); - CreateTrialAndAssociateId("t6", "g6", GOOGLE_APP, 126); - - VariationsIdsProvider provider; - provider.ForceVariationIds({"100", "200", "t101"}, ""); - - EXPECT_EQ((std::vector<VariationID>{100, 121, 122, 200}), - provider.GetVariationsVector(GOOGLE_WEB_PROPERTIES_ANY_CONTEXT)); - EXPECT_EQ( - (std::vector<VariationID>{101, 123, 124}), - provider.GetVariationsVector(GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT)); - EXPECT_EQ((std::vector<VariationID>{125}), - provider.GetVariationsVector(GOOGLE_WEB_PROPERTIES_SIGNED_IN)); - EXPECT_EQ((std::vector<VariationID>{126}), - provider.GetVariationsVector(GOOGLE_APP)); -} - -TEST_F(VariationsIdsProviderTest, GetVariationsVectorForWebPropertiesKeys) { - CreateTrialAndAssociateId("t1", "g1", GOOGLE_WEB_PROPERTIES_ANY_CONTEXT, 121); - CreateTrialAndAssociateId("t2", "g2", - GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT, 122); - CreateTrialAndAssociateId("t3", "g3", GOOGLE_WEB_PROPERTIES_SIGNED_IN, 123); - CreateTrialAndAssociateId("t4", "g4", GOOGLE_APP, 124); // Will be excluded. - VariationsIdsProvider provider; - provider.ForceVariationIds({"100", "t101"}, ""); - EXPECT_EQ((std::vector<VariationID>{100, 101, 121, 122, 123}), - provider.GetVariationsVectorForWebPropertiesKeys()); -} - -TEST_F(VariationsIdsProviderTest, GetVariationsVectorImpl) { - CreateTrialAndAssociateId("t1", "g1", GOOGLE_WEB_PROPERTIES_ANY_CONTEXT, 121); - CreateTrialAndAssociateId("t2", "g2", GOOGLE_WEB_PROPERTIES_ANY_CONTEXT, 122); - CreateTrialAndAssociateId("t3", "g3", GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT, 123); - CreateTrialAndAssociateId("t4", "g4", - GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT, 124); - CreateTrialAndAssociateId("t5", "g5", GOOGLE_WEB_PROPERTIES_SIGNED_IN, 125); - CreateTrialAndAssociateId("t6", "g6", GOOGLE_WEB_PROPERTIES_SIGNED_IN, - 124); // Note: Duplicate. + CreateTrialAndAssociateId("t5", "g5", + GOOGLE_WEB_PROPERTIES_TRIGGER_FIRST_PARTY, 124); + CreateTrialAndAssociateId("t6", "g6", GOOGLE_WEB_PROPERTIES_SIGNED_IN, 125); CreateTrialAndAssociateId("t7", "g7", GOOGLE_APP, 126); VariationsIdsProvider provider; provider.ForceVariationIds({"100", "200", "t101"}, ""); - EXPECT_EQ((std::vector<VariationID>{100, 101, 121, 122, 123, 124, 200}), + EXPECT_EQ((std::vector<VariationID>{100, 121, 200}), + provider.GetVariationsVector({GOOGLE_WEB_PROPERTIES_ANY_CONTEXT})); + EXPECT_EQ((std::vector<VariationID>{122}), + provider.GetVariationsVector({GOOGLE_WEB_PROPERTIES_FIRST_PARTY})); + EXPECT_EQ((std::vector<VariationID>{101, 123}), + provider.GetVariationsVector( + {GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT})); + EXPECT_EQ((std::vector<VariationID>{124}), + provider.GetVariationsVector( + {GOOGLE_WEB_PROPERTIES_TRIGGER_FIRST_PARTY})); + EXPECT_EQ((std::vector<VariationID>{125}), + provider.GetVariationsVector({GOOGLE_WEB_PROPERTIES_SIGNED_IN})); + EXPECT_EQ((std::vector<VariationID>{126}), + provider.GetVariationsVector({GOOGLE_APP})); + EXPECT_EQ( + (std::vector<VariationID>{100, 101, 121, 122, 123, 124, 125, 126, 200}), + provider.GetVariationsVector( + {GOOGLE_WEB_PROPERTIES_ANY_CONTEXT, GOOGLE_WEB_PROPERTIES_FIRST_PARTY, + GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT, + GOOGLE_WEB_PROPERTIES_TRIGGER_FIRST_PARTY, + GOOGLE_WEB_PROPERTIES_SIGNED_IN, GOOGLE_APP})); +} + +TEST_F(VariationsIdsProviderTest, GetVariationsVectorForWebPropertiesKeys) { + CreateTrialAndAssociateId("t1", "g1", GOOGLE_WEB_PROPERTIES_ANY_CONTEXT, 121); + CreateTrialAndAssociateId("t2", "g2", GOOGLE_WEB_PROPERTIES_FIRST_PARTY, 122); + CreateTrialAndAssociateId("t3", "g3", + GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT, 123); + CreateTrialAndAssociateId("t4", "g4", + GOOGLE_WEB_PROPERTIES_TRIGGER_FIRST_PARTY, 124); + CreateTrialAndAssociateId("t5", "g5", GOOGLE_WEB_PROPERTIES_SIGNED_IN, 125); + + // GOOGLE_APP ids shouldn't be included. + CreateTrialAndAssociateId("t6", "g6", GOOGLE_APP, 126); + + VariationsIdsProvider provider; + provider.ForceVariationIds({"100", "t101"}, ""); + EXPECT_EQ((std::vector<VariationID>{100, 101, 121, 122, 123, 124, 125}), + provider.GetVariationsVectorForWebPropertiesKeys()); +} + +TEST_F(VariationsIdsProviderTest, GetVariationsVectorImpl) { + CreateTrialAndAssociateId("t1", "g1", GOOGLE_WEB_PROPERTIES_ANY_CONTEXT, 121); + CreateTrialAndAssociateId("t2", "g2", GOOGLE_WEB_PROPERTIES_FIRST_PARTY, 122); + CreateTrialAndAssociateId("t3", "g3", + GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT, 123); + CreateTrialAndAssociateId("t4", "g4", + GOOGLE_WEB_PROPERTIES_TRIGGER_FIRST_PARTY, 124); + CreateTrialAndAssociateId("t5", "g5", GOOGLE_WEB_PROPERTIES_SIGNED_IN, 125); + CreateTrialAndAssociateId("t6", "g6", GOOGLE_APP, 125); // Duplicate. + + VariationsIdsProvider provider; + provider.ForceVariationIds({"100", "200", "t101"}, ""); + + EXPECT_EQ( + (std::vector<VariationID>{100, 121, 122, 200}), + provider.GetVariationsVectorImpl({GOOGLE_WEB_PROPERTIES_ANY_CONTEXT, + GOOGLE_WEB_PROPERTIES_FIRST_PARTY})); + EXPECT_EQ((std::vector<VariationID>{101, 123, 124}), provider.GetVariationsVectorImpl( - {GOOGLE_WEB_PROPERTIES_ANY_CONTEXT, - GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT})); - EXPECT_EQ((std::vector<VariationID>{101, 123, 124, 125}), + {GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT, + GOOGLE_WEB_PROPERTIES_TRIGGER_FIRST_PARTY})); + EXPECT_EQ((std::vector<VariationID>{125}), provider.GetVariationsVectorImpl( - {GOOGLE_WEB_PROPERTIES_SIGNED_IN, - GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT})); - EXPECT_EQ((std::vector<VariationID>{124, 125, 126}), - provider.GetVariationsVectorImpl( - {GOOGLE_APP, GOOGLE_WEB_PROPERTIES_SIGNED_IN})); + {GOOGLE_WEB_PROPERTIES_SIGNED_IN, GOOGLE_APP})); } } // namespace variations
diff --git a/components/variations/variations_seed_processor.cc b/components/variations/variations_seed_processor.cc index a0dc36d..140104c 100644 --- a/components/variations/variations_seed_processor.cc +++ b/components/variations/variations_seed_processor.cc
@@ -13,6 +13,7 @@ #include "base/feature_list.h" #include "base/metrics/field_trial.h" #include "base/metrics/histogram_macros.h" +#include "base/optional.h" #include "base/strings/utf_string_conversions.h" #include "components/variations/client_filterable_state.h" #include "components/variations/processed_study.h" @@ -35,31 +36,60 @@ AssociateVariationParams(study.name(), experiment.name(), params); } -// If there are variation ids associated with |experiment|, register the -// variation ids. +// Returns the IDCollectionKey with which |experiment| should be associated. +// Returns nullopt when |experiment| doesn't have a Google web or Google web +// trigger experiment ID. +base::Optional<IDCollectionKey> GetKeyForWebExperiment( + const Study_Experiment& experiment) { + bool has_web_experiment_id = experiment.has_google_web_experiment_id(); + bool has_web_trigger_experiment_id = + experiment.has_google_web_trigger_experiment_id(); + + if (!has_web_experiment_id && !has_web_trigger_experiment_id) + return base::nullopt; + + // An experiment cannot have both |google_web_experiment_id| and + // |google_trigger_web_experiment_id|. This is enforced by the variations + // server before generating a variations seed. + DCHECK(!(has_web_experiment_id && has_web_trigger_experiment_id)); + + Study_GoogleWebVisibility visibility = experiment.google_web_visibility(); + if (visibility == Study_GoogleWebVisibility_FIRST_PARTY) { + return has_web_trigger_experiment_id + ? GOOGLE_WEB_PROPERTIES_TRIGGER_FIRST_PARTY + : GOOGLE_WEB_PROPERTIES_FIRST_PARTY; + } + return has_web_trigger_experiment_id + ? GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT + : GOOGLE_WEB_PROPERTIES_ANY_CONTEXT; +} + +// If there are VariationIDs associated with |experiment|, register the +// VariationIDs. void RegisterVariationIds(const Study_Experiment& experiment, const std::string& trial_name) { - if (experiment.has_google_web_experiment_id()) { - const VariationID variation_id = - static_cast<VariationID>(experiment.google_web_experiment_id()); - AssociateGoogleVariationIDForce(GOOGLE_WEB_PROPERTIES_ANY_CONTEXT, - trial_name, experiment.name(), - variation_id); - } - if (experiment.has_google_web_trigger_experiment_id()) { - const VariationID variation_id = - static_cast<VariationID>(experiment.google_web_trigger_experiment_id()); - AssociateGoogleVariationIDForce(GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT, - trial_name, experiment.name(), - variation_id); - } - if (experiment.has_google_app_experiment_id()) { const VariationID variation_id = static_cast<VariationID>(experiment.google_app_experiment_id()); AssociateGoogleVariationIDForce(GOOGLE_APP, trial_name, experiment.name(), variation_id); } + + base::Optional<IDCollectionKey> key = GetKeyForWebExperiment(experiment); + if (!key.has_value()) + return; + + // An experiment cannot have both |google_web_experiment_id| and + // |google_trigger_web_experiment_id|. See GetKeyForWebExperiment() for more + // details. + const VariationID variation_id = + experiment.has_google_web_trigger_experiment_id() + ? static_cast<VariationID>( + experiment.google_web_trigger_experiment_id()) + : static_cast<VariationID>(experiment.google_web_experiment_id()); + + AssociateGoogleVariationIDForce(key.value(), trial_name, experiment.name(), + variation_id); } // Executes |callback| on every override defined by |experiment|.
diff --git a/components/variations/variations_seed_processor_unittest.cc b/components/variations/variations_seed_processor_unittest.cc index 60a58dd..f6f268e5 100644 --- a/components/variations/variations_seed_processor_unittest.cc +++ b/components/variations/variations_seed_processor_unittest.cc
@@ -27,6 +27,7 @@ #include "base/test/scoped_field_trial_list_resetter.h" #include "components/variations/client_filterable_state.h" #include "components/variations/processed_study.h" +#include "components/variations/proto/study.pb.h" #include "components/variations/study_filtering.h" #include "components/variations/variations_associated_data.h" #include "testing/gmock/include/gmock/gmock.h" @@ -182,6 +183,23 @@ EXPECT_EQ(kExperimentId, id); } +TEST_F(VariationsSeedProcessorTest, AllowForceGroupAndVariationId_FirstParty) { + base::CommandLine::ForCurrentProcess()->AppendSwitch(kForcingFlag1); + + Study study = CreateStudyWithFlagGroups(100, 0, 0); + Study_Experiment* experiment1 = study.mutable_experiment(1); + experiment1->set_google_web_experiment_id(kExperimentId); + experiment1->set_google_web_visibility(Study_GoogleWebVisibility_FIRST_PARTY); + + EXPECT_TRUE(CreateTrialFromStudy(study)); + EXPECT_EQ(kFlagGroup1Name, + base::FieldTrialList::FindFullName(kFlagStudyName)); + + VariationID id = GetGoogleVariationID(GOOGLE_WEB_PROPERTIES_FIRST_PARTY, + kFlagStudyName, kFlagGroup1Name); + EXPECT_EQ(kExperimentId, id); +} + // Test that the group for kForcingFlag1 is forced. TEST_F(VariationsSeedProcessorTest, ForceGroupWithFlag1) { base::CommandLine::ForCurrentProcess()->AppendSwitch(kForcingFlag1);
diff --git a/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.cc b/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.cc index 253542db..6136180 100644 --- a/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.cc +++ b/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.cc
@@ -100,15 +100,15 @@ params->gpu_compositing = false; params->compositor_frame_sink = root_compositor_frame_sink_remote_ - .BindNewEndpointAndPassDedicatedReceiverForTesting(); + .BindNewEndpointAndPassDedicatedReceiver(); params->compositor_frame_sink_client = root_compositor_frame_sink_client_.BindInterfaceRemote(); params->display_private = - display_private_.BindNewEndpointAndPassDedicatedReceiverForTesting(); + display_private_.BindNewEndpointAndPassDedicatedReceiver(); params->display_client = display_client_.BindRemote(); params->external_begin_frame_controller = external_begin_frame_controller_remote_ - .BindNewEndpointAndPassDedicatedReceiverForTesting(); + .BindNewEndpointAndPassDedicatedReceiver(); return params; }
diff --git a/components/viz/service/main/viz_main_impl.cc b/components/viz/service/main/viz_main_impl.cc index 5203eca..9db285f4 100644 --- a/components/viz/service/main/viz_main_impl.cc +++ b/components/viz/service/main/viz_main_impl.cc
@@ -10,13 +10,9 @@ #include "base/bind.h" #include "base/feature_list.h" #include "base/message_loop/message_pump_type.h" -#include "base/no_destructor.h" #include "base/power_monitor/power_monitor.h" #include "base/power_monitor/power_monitor_source.h" #include "base/single_thread_task_runner.h" -#include "base/synchronization/lock.h" -#include "base/task/thread_pool.h" -#include "base/time/time.h" #include "base/trace_event/memory_dump_manager.h" #include "build/build_config.h" #include "components/ui_devtools/buildflags.h" @@ -25,81 +21,12 @@ #include "gpu/ipc/service/gpu_init.h" #include "gpu/ipc/service/gpu_watchdog_thread.h" #include "media/gpu/buildflags.h" -#include "mojo/public/cpp/bindings/scoped_message_error_crash_key.h" -#include "mojo/public/cpp/system/functions.h" #include "services/metrics/public/cpp/delegating_ukm_recorder.h" #include "services/metrics/public/cpp/mojo_ukm_recorder.h" #include "third_party/skia/include/core/SkFontLCDConfig.h" namespace { -// Singleton class to store error strings from global mojo error handler. It -// will store error strings for kTimeout seconds and can be used to set a crash -// key if the GPU process is going to crash due to a deserialization error. -// TODO(kylechar): This can be removed after tracking down all outstanding -// deserialization errors in messages sent from the browser to GPU on the viz -// message pipe. -class MojoErrorTracker { - public: - static constexpr base::TimeDelta kTimeout = base::TimeDelta::FromSeconds(5); - - static MojoErrorTracker& Get() { - static base::NoDestructor<MojoErrorTracker> tracker; - return *tracker; - } - - void OnError(const std::string& error) { - { - base::AutoLock locked(lock_); - error_ = error; - error_time_ = base::TimeTicks::Now(); - } - - // Once the error is old enough we will no longer use it in a crash key we - // can reset the string storage. - base::ThreadPool::PostDelayedTask( - FROM_HERE, - base::BindOnce(&MojoErrorTracker::Reset, base::Unretained(this)), - kTimeout); - } - - // This will initialize the scoped crash key in |key| with the last mojo - // error message if the last mojo error happened within kTimeout seconds. - void MaybeSetCrashKeyWithRecentError( - base::Optional<mojo::debug::ScopedMessageErrorCrashKey>& key) { - base::AutoLock locked(lock_); - if (!HasErrorTimedOut()) - key.emplace(error_); - } - - private: - friend class base::NoDestructor<MojoErrorTracker>; - MojoErrorTracker() = default; - - bool HasErrorTimedOut() const EXCLUSIVE_LOCKS_REQUIRED(lock_) { - return base::TimeTicks::Now() - error_time_ > kTimeout; - } - - void Reset() { - base::AutoLock locked(lock_); - - // If another mojo error happened since this task was scheduled we shouldn't - // reset the error string yet. - if (!HasErrorTimedOut()) - return; - - error_.clear(); - error_.shrink_to_fit(); - } - - base::Lock lock_; - std::string error_ GUARDED_BY(lock_); - base::TimeTicks error_time_ GUARDED_BY(lock_); -}; - -// static -constexpr base::TimeDelta MojoErrorTracker::kTimeout; - std::unique_ptr<base::Thread> CreateAndStartIOThread() { // TODO(sad): We do not need the IO thread once gpu has a separate process. // It should be possible to use |main_task_runner_| for doing IO tasks. @@ -136,12 +63,6 @@ gpu_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()) { DCHECK(gpu_init_); - if (!gpu_init_->gpu_info().in_process_gpu) { - mojo::SetDefaultProcessErrorHandler( - base::BindRepeating(&MojoErrorTracker::OnError, - base::Unretained(&MojoErrorTracker::Get()))); - } - // TODO(crbug.com/609317): Remove this when Mus Window Server and GPU are // split into separate processes. Until then this is necessary to be able to // run Mushrome (chrome with mus) with Mus running in the browser process. @@ -317,16 +238,8 @@ // FrameSinkManagerImpl, so just do a hard CHECK rather than crashing down the // road so that all crash reports caused by this issue look the same and have // the same signature. https://crbug.com/928845 - if (task_executor_) { - // If the global mojo error handler callback ran recently, we've cached the - // error string and will initialize |crash_key| to contain it before - // intentionally crashing. The deserialization error that caused the mojo - // error handler to run was probably, but not 100% guaranteed, the error - // that caused the main viz browser-to-GPU message pipe close. - base::Optional<mojo::debug::ScopedMessageErrorCrashKey> crash_key; - MojoErrorTracker::Get().MaybeSetCrashKeyWithRecentError(crash_key); - CHECK(!task_executor_); - } + CHECK(!task_executor_); + task_executor_ = std::make_unique<gpu::GpuInProcessThreadService>( this, gpu_thread_task_runner_, gpu_service_->GetGpuScheduler(), gpu_service_->sync_point_manager(), gpu_service_->mailbox_manager(),
diff --git a/components/webdata/common/web_data_results.h b/components/webdata/common/web_data_results.h index db1e907..9d9a6188 100644 --- a/components/webdata/common/web_data_results.h +++ b/components/webdata/common/web_data_results.h
@@ -40,6 +40,8 @@ // std::unique_ptr<CreditCard>>> AUTOFILL_CUSTOMERDATA_RESULT, // WDResult<std::unique_ptr< // PaymentsCustomerData>> + AUTOFILL_OFFER_DATA, // WDResult<std::vector<std::unique_ptr< + // AutofillOfferData>>> AUTOFILL_UPI_RESULT, // WDResult<std::string> #if !defined(OS_IOS) // PAYMENT_WEB_APP_MANIFEST, // WDResult<std::vector<
diff --git a/content/app/content_service_manager_main_delegate.cc b/content/app/content_service_manager_main_delegate.cc index 1e6ad31..7cb0c25 100644 --- a/content/app/content_service_manager_main_delegate.cc +++ b/content/app/content_service_manager_main_delegate.cc
@@ -9,7 +9,6 @@ #include "content/common/mojo_core_library_support.h" #include "content/public/app/content_main_delegate.h" #include "content/public/common/content_switches.h" -#include "content/public/common/service_names.mojom.h" #include "mojo/core/embedder/embedder.h" #include "mojo/public/cpp/platform/platform_channel.h" #include "mojo/public/cpp/system/dynamic_library_support.h" @@ -66,11 +65,6 @@ #endif } -service_manager::ProcessType -ContentServiceManagerMainDelegate::OverrideProcessType() { - return content_main_params_.delegate->OverrideProcessType(); -} - void ContentServiceManagerMainDelegate::InitializeMojo( mojo::core::Configuration* config) { // If this is the browser process and there's no Mojo invitation pipe on the @@ -117,58 +111,6 @@ CHECK_EQ(MOJO_RESULT_OK, result); } -std::vector<service_manager::Manifest> -ContentServiceManagerMainDelegate::GetServiceManifests() { - return std::vector<service_manager::Manifest>(); -} - -bool ContentServiceManagerMainDelegate::ShouldLaunchAsServiceProcess( - const service_manager::Identity& identity) { - return identity.name() != mojom::kPackagedServicesServiceName; -} - -void ContentServiceManagerMainDelegate::AdjustServiceProcessCommandLine( - const service_manager::Identity& identity, - base::CommandLine* command_line) { - base::CommandLine::StringVector args_without_switches; - if (identity.name() == mojom::kPackagedServicesServiceName) { - // Ensure other arguments like URL are not lost. - args_without_switches = command_line->GetArgs(); - - // When launching the browser process, ensure that we don't inherit any - // process type flag. When content embeds Service Manager, a process with no - // type is launched as a browser process. - base::CommandLine::SwitchMap switches = command_line->GetSwitches(); - switches.erase(switches::kProcessType); - *command_line = base::CommandLine(command_line->GetProgram()); - for (const auto& sw : switches) - command_line->AppendSwitchNative(sw.first, sw.second); - } - - content_main_params_.delegate->AdjustServiceProcessCommandLine(identity, - command_line); - - // Append other arguments back to |command_line| after the second call to - // delegate as long as it can still remove all the arguments without switches. - for (const auto& arg : args_without_switches) - command_line->AppendArgNative(arg); -} - -void ContentServiceManagerMainDelegate::OnServiceManagerInitialized( - base::OnceClosure quit_closure, - service_manager::BackgroundServiceManager* service_manager) { - return content_main_params_.delegate->OnServiceManagerInitialized( - std::move(quit_closure), service_manager); -} - -std::unique_ptr<service_manager::Service> -ContentServiceManagerMainDelegate::CreateEmbeddedService( - const std::string& service_name) { - // TODO - - return nullptr; -} - void ContentServiceManagerMainDelegate::SetStartServiceManagerOnly( bool start_service_manager_only) { start_service_manager_only_ = start_service_manager_only;
diff --git a/content/app/content_service_manager_main_delegate.h b/content/app/content_service_manager_main_delegate.h index ae97969..eb7768b 100644 --- a/content/app/content_service_manager_main_delegate.h +++ b/content/app/content_service_manager_main_delegate.h
@@ -8,9 +8,6 @@ #include <memory> #include "base/macros.h" -#include "base/memory/scoped_refptr.h" -#include "base/single_thread_task_runner.h" -#include "build/build_config.h" #include "content/public/app/content_main.h" #include "services/service_manager/embedder/main_delegate.h" @@ -28,19 +25,7 @@ bool IsEmbedderSubprocess() override; int RunEmbedderProcess() override; void ShutDownEmbedderProcess() override; - service_manager::ProcessType OverrideProcessType() override; void InitializeMojo(mojo::core::Configuration* config) override; - std::vector<service_manager::Manifest> GetServiceManifests() override; - bool ShouldLaunchAsServiceProcess( - const service_manager::Identity& identity) override; - void AdjustServiceProcessCommandLine( - const service_manager::Identity& identity, - base::CommandLine* command_line) override; - void OnServiceManagerInitialized( - base::OnceClosure quit_closure, - service_manager::BackgroundServiceManager* service_manager) override; - std::unique_ptr<service_manager::Service> CreateEmbeddedService( - const std::string& service_name) override; // Sets the flag whether to start the Service Manager without starting the // full browser.
diff --git a/content/browser/background_sync/background_sync_manager.cc b/content/browser/background_sync/background_sync_manager.cc index 745affc..ca7aa3a 100644 --- a/content/browser/background_sync/background_sync_manager.cc +++ b/content/browser/background_sync/background_sync_manager.cc
@@ -309,6 +309,8 @@ return "succeeded"; case blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected: return "waitUntil rejected"; + case blink::ServiceWorkerStatusCode::kErrorFailed: + return "failed"; case blink::ServiceWorkerStatusCode::kErrorAbort: return "aborted"; case blink::ServiceWorkerStatusCode::kErrorTimeout:
diff --git a/content/browser/bluetooth/frame_connected_bluetooth_devices_unittest.cc b/content/browser/bluetooth/frame_connected_bluetooth_devices_unittest.cc index e24ed2b..018530f8 100644 --- a/content/browser/bluetooth/frame_connected_bluetooth_devices_unittest.cc +++ b/content/browser/bluetooth/frame_connected_bluetooth_devices_unittest.cc
@@ -43,7 +43,7 @@ mojo::AssociatedRemote<blink::mojom::WebBluetoothServerClient> CreateServerClient() { mojo::AssociatedRemote<blink::mojom::WebBluetoothServerClient> client; - ignore_result(client.BindNewEndpointAndPassDedicatedReceiverForTesting()); + ignore_result(client.BindNewEndpointAndPassDedicatedReceiver()); return client; }
diff --git a/content/browser/media/midi_host.cc b/content/browser/media/midi_host.cc index 60ff8b2..c6e0e155 100644 --- a/content/browser/media/midi_host.cc +++ b/content/browser/media/midi_host.cc
@@ -205,15 +205,13 @@ // Check |has_sys_ex_permission_| first to avoid searching kSysExByte in large // bulk data transfers for correct uses. if (!has_sys_ex_permission_ && base::Contains(data, kSysExByte)) { + has_sys_ex_permission_ = + ChildProcessSecurityPolicyImpl::GetInstance()->CanSendMidiSysExMessage( + renderer_process_id_); if (!has_sys_ex_permission_) { - has_sys_ex_permission_ = - ChildProcessSecurityPolicyImpl::GetInstance() - ->CanSendMidiSysExMessage(renderer_process_id_); - if (!has_sys_ex_permission_) { - bad_message::ReceivedBadMessage(renderer_process_id_, - bad_message::MH_SYS_EX_PERMISSION); - return; - } + bad_message::ReceivedBadMessage(renderer_process_id_, + bad_message::MH_SYS_EX_PERMISSION); + return; } }
diff --git a/content/browser/renderer_host/mock_render_widget_host.cc b/content/browser/renderer_host/mock_render_widget_host.cc index 0441b9c2..fa6d0ca 100644 --- a/content/browser/renderer_host/mock_render_widget_host.cc +++ b/content/browser/renderer_host/mock_render_widget_host.cc
@@ -44,7 +44,7 @@ int32_t routing_id) { mojo::AssociatedRemote<blink::mojom::Widget> blink_widget; auto blink_widget_receiver = - blink_widget.BindNewEndpointAndPassDedicatedReceiverForTesting(); + blink_widget.BindNewEndpointAndPassDedicatedReceiver(); return new MockRenderWidgetHost(delegate, agent_scheduling_group, routing_id, blink_widget.Unbind()); } @@ -83,7 +83,7 @@ acked_touch_event_type_ = blink::WebInputEvent::Type::kUndefined; mojo::AssociatedRemote<blink::mojom::WidgetHost> blink_widget_host; BindWidgetInterfaces( - blink_widget_host.BindNewEndpointAndPassDedicatedReceiverForTesting(), + blink_widget_host.BindNewEndpointAndPassDedicatedReceiver(), std::move(pending_blink_widget)); }
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc index 95637432d..245f0f8 100644 --- a/content/browser/renderer_host/render_frame_host_impl.cc +++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -1699,8 +1699,8 @@ } else { // The channel may not be initialized in some tests environments. In this // case we set up a dummy interface provider. - ignore_result(remote_interfaces - .BindNewEndpointAndPassDedicatedReceiverForTesting()); + ignore_result( + remote_interfaces.BindNewEndpointAndPassDedicatedReceiver()); } remote_associated_interfaces_ = std::make_unique<blink::AssociatedInterfaceProvider>(
diff --git a/content/browser/renderer_host/render_frame_proxy_host.cc b/content/browser/renderer_host/render_frame_proxy_host.cc index 64d4487..b73b351 100644 --- a/content/browser/renderer_host/render_frame_proxy_host.cc +++ b/content/browser/renderer_host/render_frame_proxy_host.cc
@@ -312,8 +312,8 @@ } else { // The channel may not be initialized in some tests environments. In this // case we set up a dummy interface provider. - ignore_result(remote_interfaces - .BindNewEndpointAndPassDedicatedReceiverForTesting()); + ignore_result( + remote_interfaces.BindNewEndpointAndPassDedicatedReceiver()); } remote_associated_interfaces_ = std::make_unique<blink::AssociatedInterfaceProvider>(
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc b/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc index 094d542..8e2552e 100644 --- a/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc
@@ -238,17 +238,17 @@ mojo::AssociatedRemote<blink::mojom::WidgetHost> blink_widget_host; mojo::AssociatedRemote<blink::mojom::Widget> blink_widget; auto blink_widget_receiver = - blink_widget.BindNewEndpointAndPassDedicatedReceiverForTesting(); + blink_widget.BindNewEndpointAndPassDedicatedReceiver(); widget_host_root_->BindWidgetInterfaces( - blink_widget_host.BindNewEndpointAndPassDedicatedReceiverForTesting(), + blink_widget_host.BindNewEndpointAndPassDedicatedReceiver(), blink_widget.Unbind()); mojo::AssociatedRemote<blink::mojom::FrameWidgetHost> frame_widget_host; mojo::AssociatedRemote<blink::mojom::FrameWidget> frame_widget; auto frame_widget_receiver = - frame_widget.BindNewEndpointAndPassDedicatedReceiverForTesting(); + frame_widget.BindNewEndpointAndPassDedicatedReceiver(); widget_host_root_->BindFrameWidgetInterfaces( - frame_widget_host.BindNewEndpointAndPassDedicatedReceiverForTesting(), + frame_widget_host.BindNewEndpointAndPassDedicatedReceiver(), frame_widget.Unbind()); view_root_ =
diff --git a/content/browser/renderer_host/render_widget_host_unittest.cc b/content/browser/renderer_host/render_widget_host_unittest.cc index 09dc83f0..fff56d3 100644 --- a/content/browser/renderer_host/render_widget_host_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -605,15 +605,15 @@ void ReinitalizeHost() { mojo::AssociatedRemote<blink::mojom::WidgetHost> widget_host; host_->BindWidgetInterfaces( - widget_host.BindNewEndpointAndPassDedicatedReceiverForTesting(), + widget_host.BindNewEndpointAndPassDedicatedReceiver(), widget_.GetNewRemote()); mojo::AssociatedRemote<blink::mojom::FrameWidgetHost> frame_widget_host; mojo::AssociatedRemote<blink::mojom::FrameWidget> frame_widget; auto frame_widget_receiver = - frame_widget.BindNewEndpointAndPassDedicatedReceiverForTesting(); + frame_widget.BindNewEndpointAndPassDedicatedReceiver(); host_->BindFrameWidgetInterfaces( - frame_widget_host.BindNewEndpointAndPassDedicatedReceiverForTesting(), + frame_widget_host.BindNewEndpointAndPassDedicatedReceiver(), frame_widget.Unbind()); host_->Init();
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc index c4ddc90..3b0bbf3a 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -432,7 +432,7 @@ lastWheelOrTouchEventLatencyInfo = ui::LatencyInfo(); mojo::AssociatedRemote<blink::mojom::WidgetHost> blink_widget_host; BindWidgetInterfaces( - blink_widget_host.BindNewEndpointAndPassDedicatedReceiverForTesting(), + blink_widget_host.BindNewEndpointAndPassDedicatedReceiver(), widget_.GetNewRemote()); } @@ -556,11 +556,10 @@ mojo::AssociatedRemote<blink::mojom::FrameWidgetHost> parent_frame_widget_host; auto parent_frame_widget_host_receiver = - parent_frame_widget_host - .BindNewEndpointAndPassDedicatedReceiverForTesting(); + parent_frame_widget_host.BindNewEndpointAndPassDedicatedReceiver(); mojo::AssociatedRemote<blink::mojom::FrameWidget> parent_frame_widget; auto parent_frame_widget_receiver = - parent_frame_widget.BindNewEndpointAndPassDedicatedReceiverForTesting(); + parent_frame_widget.BindNewEndpointAndPassDedicatedReceiver(); parent_host_->BindFrameWidgetInterfaces( std::move(parent_frame_widget_host_receiver), parent_frame_widget.Unbind()); @@ -575,10 +574,10 @@ widget_host_ = static_cast<MockRenderWidgetHostImpl*>(view_->host()); mojo::AssociatedRemote<blink::mojom::FrameWidgetHost> frame_widget_host; auto frame_widget_host_receiver = - frame_widget_host.BindNewEndpointAndPassDedicatedReceiverForTesting(); + frame_widget_host.BindNewEndpointAndPassDedicatedReceiver(); mojo::AssociatedRemote<blink::mojom::FrameWidget> frame_widget; auto frame_widget_receiver = - frame_widget.BindNewEndpointAndPassDedicatedReceiverForTesting(); + frame_widget.BindNewEndpointAndPassDedicatedReceiver(); widget_host_->BindFrameWidgetInterfaces( std::move(frame_widget_host_receiver), frame_widget.Unbind()); // Set the mouse_wheel_phase_handler_ timer timeout to 100ms. @@ -6132,11 +6131,10 @@ mojo::AssociatedRemote<blink::mojom::FrameWidgetHost> blink_frame_widget_host; auto blink_frame_widget_host_receiver = - blink_frame_widget_host - .BindNewEndpointAndPassDedicatedReceiverForTesting(); + blink_frame_widget_host.BindNewEndpointAndPassDedicatedReceiver(); mojo::AssociatedRemote<blink::mojom::FrameWidget> blink_frame_widget; auto blink_frame_widget_receiver = - blink_frame_widget.BindNewEndpointAndPassDedicatedReceiverForTesting(); + blink_frame_widget.BindNewEndpointAndPassDedicatedReceiver(); static_cast<RenderWidgetHostImpl*>(views_[index]->GetRenderWidgetHost()) ->BindFrameWidgetInterfaces(std::move(blink_frame_widget_host_receiver),
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc b/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc index 363f5e0..e51fa31 100644 --- a/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc
@@ -129,15 +129,15 @@ mojo::AssociatedRemote<blink::mojom::WidgetHost> blink_widget_host; widget_host_->BindWidgetInterfaces( - blink_widget_host.BindNewEndpointAndPassDedicatedReceiverForTesting(), + blink_widget_host.BindNewEndpointAndPassDedicatedReceiver(), widget_.GetNewRemote()); mojo::AssociatedRemote<blink::mojom::FrameWidgetHost> frame_widget_host; mojo::AssociatedRemote<blink::mojom::FrameWidget> frame_widget; auto frame_widget_receiver = - frame_widget.BindNewEndpointAndPassDedicatedReceiverForTesting(); + frame_widget.BindNewEndpointAndPassDedicatedReceiver(); widget_host_->BindFrameWidgetInterfaces( - frame_widget_host.BindNewEndpointAndPassDedicatedReceiverForTesting(), + frame_widget_host.BindNewEndpointAndPassDedicatedReceiver(), frame_widget.Unbind()); blink::ScreenInfo screen_info;
diff --git a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm index 5c4f7ee..9955638 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
@@ -366,10 +366,10 @@ std::make_unique<FrameTokenMessageQueue>()) { mojo::AssociatedRemote<blink::mojom::FrameWidgetHost> frame_widget_host; auto frame_widget_host_receiver = - frame_widget_host.BindNewEndpointAndPassDedicatedReceiverForTesting(); + frame_widget_host.BindNewEndpointAndPassDedicatedReceiver(); mojo::AssociatedRemote<blink::mojom::FrameWidget> frame_widget; auto frame_widget_receiver = - frame_widget.BindNewEndpointAndPassDedicatedReceiverForTesting(); + frame_widget.BindNewEndpointAndPassDedicatedReceiver(); BindFrameWidgetInterfaces(std::move(frame_widget_host_receiver), frame_widget.Unbind()); @@ -500,10 +500,10 @@ process_host_->GetNextRoutingID())); mojo::AssociatedRemote<blink::mojom::FrameWidgetHost> frame_widget_host; auto frame_widget_host_receiver = - frame_widget_host.BindNewEndpointAndPassDedicatedReceiverForTesting(); + frame_widget_host.BindNewEndpointAndPassDedicatedReceiver(); mojo::AssociatedRemote<blink::mojom::FrameWidget> frame_widget; auto frame_widget_receiver = - frame_widget.BindNewEndpointAndPassDedicatedReceiverForTesting(); + frame_widget.BindNewEndpointAndPassDedicatedReceiver(); host_->BindFrameWidgetInterfaces(std::move(frame_widget_host_receiver), frame_widget.Unbind()); host_->set_owner_delegate(&mock_owner_delegate_);
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index d76fe04..77d1cd5 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -4235,10 +4235,13 @@ return; waiting_for_response_ = false; - if (delegate_) - delegate_->LoadingStateChanged(this, is_load_to_different_document_); observers_.ForEachObserver( [&](WebContentsObserver* observer) { observer->DidReceiveResponse(); }); + + // LoadingStateChanged must be called last in case it triggers deletion of + // |this| due to recursive message pumps. + if (delegate_) + delegate_->LoadingStateChanged(this, is_load_to_different_document_); } void WebContentsImpl::SendScreenRects() { @@ -5309,6 +5312,8 @@ : false); } + // LoadingStateChanged must be called last in case it triggers deletion of + // |this| due to recursive message pumps. SetNotWaitingForResponse(); }
diff --git a/content/browser/web_contents_receiver_set_browsertest.cc b/content/browser/web_contents_receiver_set_browsertest.cc index c40eeaec..00a73421 100644 --- a/content/browser/web_contents_receiver_set_browsertest.cc +++ b/content/browser/web_contents_receiver_set_browsertest.cc
@@ -97,7 +97,7 @@ ->OnAssociatedInterfaceRequest( web_contents->GetMainFrame(), mojom::BrowserAssociatedInterfaceTestDriver::Name_, - override_client.BindNewEndpointAndPassDedicatedReceiverForTesting() + override_client.BindNewEndpointAndPassDedicatedReceiver() .PassHandle()); run_loop.Run(); @@ -119,7 +119,7 @@ ->OnAssociatedInterfaceRequest( web_contents->GetMainFrame(), mojom::WebContentsFrameReceiverSetTest::Name_, - override_client.BindNewEndpointAndPassDedicatedReceiverForTesting() + override_client.BindNewEndpointAndPassDedicatedReceiver() .PassHandle()); base::RunLoop run_loop;
diff --git a/content/gpu/gpu_child_thread.cc b/content/gpu/gpu_child_thread.cc index eb0485f..571b3b14 100644 --- a/content/gpu/gpu_child_thread.cc +++ b/content/gpu/gpu_child_thread.cc
@@ -12,6 +12,7 @@ #include "base/bind_helpers.h" #include "base/callback_helpers.h" #include "base/command_line.h" +#include "base/debug/dump_without_crashing.h" #include "base/memory/weak_ptr.h" #include "base/power_monitor/power_monitor.h" #include "base/power_monitor/power_monitor_device_source.h" @@ -35,6 +36,8 @@ #include "mojo/public/cpp/bindings/binder_map.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/cpp/bindings/scoped_message_error_crash_key.h" +#include "mojo/public/cpp/system/functions.h" #include "services/metrics/public/cpp/mojo_ukm_recorder.h" #include "services/metrics/public/mojom/ukm_interface.mojom.h" #include "services/service_manager/public/cpp/binder_registry.h" @@ -49,6 +52,13 @@ namespace content { namespace { +// Called when the GPU process receives a bad IPC message. +void HandleBadMessage(const std::string& error) { + LOG(ERROR) << "Mojo error in GPU process: " << error; + mojo::debug::ScopedMessageErrorCrashKey crash_key_value(error); + base::debug::DumpWithoutCrashing(); +} + ChildThreadImpl::Options GetOptions() { ChildThreadImpl::Options::Builder builder; @@ -118,6 +128,9 @@ GpuChildThread::~GpuChildThread() = default; void GpuChildThread::Init(const base::Time& process_start_time) { + if (!in_process_gpu()) + mojo::SetDefaultProcessErrorHandler(base::BindRepeating(&HandleBadMessage)); + viz_main_.gpu_service()->set_start_time(process_start_time); // When running in in-process mode, this has been set in the browser at
diff --git a/content/public/android/java/src/org/chromium/content/browser/font/AndroidFontLookupImpl.java b/content/public/android/java/src/org/chromium/content/browser/font/AndroidFontLookupImpl.java index 62ff4f75..b5618cf 100644 --- a/content/public/android/java/src/org/chromium/content/browser/font/AndroidFontLookupImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/font/AndroidFontLookupImpl.java
@@ -16,7 +16,6 @@ import androidx.core.provider.FontsContractCompat.FontFamilyResult; import androidx.core.provider.FontsContractCompat.FontInfo; -import org.chromium.base.Consumer; import org.chromium.base.ContextUtils; import org.chromium.base.Log; import org.chromium.base.task.PostTask; @@ -24,14 +23,18 @@ import org.chromium.blink.mojom.AndroidFontLookup; import org.chromium.content.R; import org.chromium.mojo.bindings.ExecutorFactory; +import org.chromium.mojo.system.Core; import org.chromium.mojo.system.MojoException; import org.chromium.mojo.system.impl.CoreImpl; import org.chromium.mojo_base.mojom.File; import org.chromium.services.service_manager.InterfaceFactory; import java.io.IOException; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.Executor; /** @@ -45,7 +48,10 @@ private final Context mAppContext; private FontsContractWrapper mFontsContract = new FontsContractWrapper(); /** - * Map from ICU case folded full font name to GMS Core font provider query format. + * Map from ICU case folded full font names to corresponding GMS Core font provider query. + * + * This collection of Android Downloadable fonts should match the fonts listed in + * preloaded_fonts.xml. */ private Map<String, String> mFullFontNameToQuery = createFullFontNameToQueryMap(); @@ -54,86 +60,109 @@ } /** - * Synchronously gets a list of unique font names that are available from GMS Core and can be - * fetched quickly. + * Verifies which fonts are available from GMS Core and can be fetched quickly, and + * asynchronously responds with that list. These fonts should have already been preloaded via + * the "preloaded_fonts" AndroidManifest directive. This second programmatic prefetch request is + * necessary to confirm whether those fonts were successfully downloaded and are now available. * - * @param callback The callback to be called with the list of font names. + * TODO(chouinard): Consider requiring the returned list to be sorted. + * + * @param callback The callback to be called with the list of available fonts. */ @Override public void getUniqueNameLookupTable(GetUniqueNameLookupTableResponse callback) { - // TODO(crbug.com/1111148): Verify which fonts were successfully preloaded and are available - // on-device to populate this list. - String[] results = new String[0]; - callback.call(results); + // Get executor associated with the current thread for running Mojo callback. + Executor executor = ExecutorFactory.getExecutorForCurrentThread(CoreImpl.getInstance()); + + PostTask.postTask(TaskTraits.BEST_EFFORT, () -> { + Set<String> expectedFonts = mFullFontNameToQuery.keySet(); + List<String> availableFonts = new ArrayList<>(); + + for (String fontName : expectedFonts) { + if (tryFetchFont(fontName) != null) { + availableFonts.add(fontName); + } + } + + String[] results = availableFonts.toArray(new String[availableFonts.size()]); + executor.execute(() -> callback.call(results)); + }); } /** * Fetches the requested font from GMS Core on a background thread. * * @param fontUniqueName The unique full font name requested. - * @param callback The callback to be called with the resulting font file handle, or null if the - * font file is not available. + * @param callback The callback to be called with the resulting opened font file handle, or null + * if the font file is not available. Caller is responsible for closing file when done. */ @Override public void matchLocalFontByUniqueName( String fontUniqueName, MatchLocalFontByUniqueNameResponse callback) { + // Get executor associated with the current thread for running Mojo callback. + Core core = CoreImpl.getInstance(); + Executor executor = ExecutorFactory.getExecutorForCurrentThread(core); + + // Post synchronous font request to background worker thread. + PostTask.postTask(TaskTraits.USER_BLOCKING, () -> { + ParcelFileDescriptor fileDescriptor = tryFetchFont(fontUniqueName); + if (fileDescriptor == null) { + executor.execute(() -> callback.call(null)); + return; + } + + // Wrap file descriptor as an opened Mojo file handle. + File file = new File(); + file.fd = core.wrapFileDescriptor(fileDescriptor); + file.async = false; + + executor.execute(() -> callback.call(file)); + }); + } + + private ParcelFileDescriptor tryFetchFont(String fontUniqueName) { String query = mFullFontNameToQuery.get(fontUniqueName); if (query == null) { - Log.d(TAG, "Query format not found for full font name: %s.", fontUniqueName); - callback.call(null); - return; + Log.d(TAG, "Query format not found for full font name: %s", fontUniqueName); + return null; } FontRequest request = new FontRequest("com.google.android.gms.fonts", "com.google.android.gms", query, R.array.com_google_android_gms_fonts_certs); - // Get executor associated with the current thread for running Mojo callback. - Executor executor = ExecutorFactory.getExecutorForCurrentThread(CoreImpl.getInstance()); - Consumer<File> consumer = (File file) -> { - executor.execute(() -> callback.call(file)); - }; - - // Execute synchronous font request on background worker thread. - PostTask.postTask(TaskTraits.USER_BLOCKING, () -> { tryFetchFont(request, consumer); }); - } - - private void tryFetchFont(FontRequest request, Consumer<File> consumer) { try { FontFamilyResult fontFamilyResult = mFontsContract.fetchFonts(mAppContext, null, request); if (fontFamilyResult.getStatusCode() != FontFamilyResult.STATUS_OK) { - Log.d(TAG, "Font fetch failed with status code %d.", + Log.d(TAG, "Font fetch failed with status code: %d", fontFamilyResult.getStatusCode()); - consumer.accept(null); - return; + return null; } FontInfo[] fontInfos = fontFamilyResult.getFonts(); if (fontInfos.length != 1) { Log.d(TAG, "Font fetch did not return a unique result: length = %d", fontInfos.length); - consumer.accept(null); - return; + return null; } FontInfo fontInfo = fontInfos[0]; if (fontInfo.getResultCode() != FontsContractCompat.Columns.RESULT_CODE_OK) { - Log.d(TAG, "Returned font has failed status code: %d.", fontInfo.getResultCode()); - consumer.accept(null); - return; + Log.d(TAG, "Returned font has failed status code: %d", fontInfo.getResultCode()); + return null; } ContentResolver contentResolver = mAppContext.getContentResolver(); ParcelFileDescriptor fileDescriptor = contentResolver.openFileDescriptor(fontInfo.getUri(), READ_ONLY_MODE); - File file = new File(); - file.fd = CoreImpl.getInstance().wrapFileDescriptor(fileDescriptor); - file.async = false; - consumer.accept(file); + if (fileDescriptor == null) { + Log.d(TAG, "Unable to open font file at: %s", fontInfo.getUri()); + } + return fileDescriptor; } catch (NameNotFoundException | IOException | OutOfMemoryError e) { Log.d(TAG, "Failed to get font with: %s", e.toString()); - consumer.accept(null); + return null; } }
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/font/AndroidFontLookupImplTest.java b/content/public/android/javatests/src/org/chromium/content/browser/font/AndroidFontLookupImplTest.java index 749ed5d1..55ff74c 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/font/AndroidFontLookupImplTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/font/AndroidFontLookupImplTest.java
@@ -4,8 +4,7 @@ package org.chromium.content.browser.font; -import static junit.framework.Assert.assertEquals; - +import static org.mockito.AdditionalMatchers.aryEq; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isNull; @@ -43,6 +42,7 @@ import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.blink.mojom.AndroidFontLookup; +import org.chromium.blink.mojom.AndroidFontLookup.GetUniqueNameLookupTableResponse; import org.chromium.blink.mojom.AndroidFontLookup.MatchLocalFontByUniqueNameResponse; import org.chromium.content_public.browser.test.NativeLibraryTestUtils; import org.chromium.content_public.browser.test.util.CriteriaHelper; @@ -57,7 +57,9 @@ private static final String FONT_QUERY = "name=Foo&weight=400"; private static final String AUTHORITY = "com.google.android.gms.fonts"; private static final Uri URI = Uri.parse("content://com.google.android.gms.fonts/123"); + private static final Uri URI2 = Uri.parse("content://com.google.android.gms.fonts/456"); private static final int FD = 42; + private static final int FD2 = 43; private static final long RUN_LOOP_TIMEOUT_MS = 50; @Rule @@ -67,9 +69,13 @@ private FontsContractWrapper mMockFontsContractWrapper; @Mock private ParcelFileDescriptor mMockFileDescriptor; + @Mock + private ParcelFileDescriptor mMockFileDescriptor2; private Context mMockContext; @Mock + private GetUniqueNameLookupTableResponse mGetUniqueNameLookupTableCallback; + @Mock private MatchLocalFontByUniqueNameResponse mMatchLocalFontByUniqueNameCallback; private AndroidFontLookupImpl mAndroidFontLookup; @@ -83,11 +89,17 @@ MockContentResolver resolver = new MockContentResolver(); MockContext mockContext = new MockContext(); when(mMockFileDescriptor.detachFd()).thenReturn(FD); + when(mMockFileDescriptor2.detachFd()).thenReturn(FD2); resolver.addProvider(AUTHORITY, new MockContentProvider(mockContext) { @Override public AssetFileDescriptor openTypedAssetFile(Uri url, String mimeType, Bundle opts) { - assertEquals(URI, url); - return new AssetFileDescriptor(mMockFileDescriptor, 0, -1); + if (url.equals(URI)) { + return new AssetFileDescriptor(mMockFileDescriptor, 0, -1); + } else if (url.equals(URI2)) { + return new AssetFileDescriptor(mMockFileDescriptor2, 0, -1); + } else { + return null; + } } }); mMockContext = new IsolatedContext(resolver, mockContext); @@ -100,8 +112,73 @@ @SmallTest @Test + public void testGetUniqueNameLookupTable_Empty() throws NameNotFoundException { + String[] expected = new String[0]; + FontFamilyResult result = new FontFamilyResult(FontFamilyResult.STATUS_OK, new FontInfo[0]); + whenFetchFontsWith(FONT_QUERY).thenReturn(result); + + mAndroidFontLookup.getUniqueNameLookupTable(mGetUniqueNameLookupTableCallback); + + mMojoTestRule.runLoop(RUN_LOOP_TIMEOUT_MS); + verify(mGetUniqueNameLookupTableCallback).call(aryEq(expected)); + } + + @SmallTest + @Test + public void testGetUniqueNameLookupTable_Available() throws NameNotFoundException { + String[] expected = new String[] {FULL_FONT_NAME}; + + FontInfo fontInfo = new FontInfo(URI, 0, 400, false, Columns.RESULT_CODE_OK); + FontFamilyResult result = + new FontFamilyResult(FontFamilyResult.STATUS_OK, new FontInfo[] {fontInfo}); + whenFetchFontsWith(FONT_QUERY).thenReturn(result); + + mAndroidFontLookup.getUniqueNameLookupTable(mGetUniqueNameLookupTableCallback); + + mMojoTestRule.runLoop(RUN_LOOP_TIMEOUT_MS); + verify(mGetUniqueNameLookupTableCallback).call(aryEq(expected)); + } + + @SmallTest + @Test + public void testGetUniqueNameLookupTable_MultipleFonts() throws NameNotFoundException { + String fullFontName2 = "bar"; + String fontQuery2 = "name=Bar&weight=400"; + String fullFontName3 = "bar bold"; + String fontQuery3 = "name=Bar&weight=700"; + + String[] expected = new String[] {FULL_FONT_NAME, fullFontName2}; + + mAndroidFontLookup.setFullFontNameToQueryMapForTest(ImmutableMap.of( + FULL_FONT_NAME, FONT_QUERY, fullFontName2, fontQuery2, fullFontName3, fontQuery3)); + + // Foo is available. + FontInfo fontInfo = new FontInfo(URI, 0, 400, false, Columns.RESULT_CODE_OK); + FontFamilyResult result = + new FontFamilyResult(FontFamilyResult.STATUS_OK, new FontInfo[] {fontInfo}); + whenFetchFontsWith(FONT_QUERY).thenReturn(result); + + // Bar is available. + FontInfo fontInfo2 = new FontInfo(URI2, 0, 400, false, Columns.RESULT_CODE_OK); + FontFamilyResult result2 = + new FontFamilyResult(FontFamilyResult.STATUS_OK, new FontInfo[] {fontInfo2}); + whenFetchFontsWith(fontQuery2).thenReturn(result2); + + // Bar Bold is not available. + FontFamilyResult result3 = + new FontFamilyResult(FontFamilyResult.STATUS_OK, new FontInfo[0]); + whenFetchFontsWith(fontQuery3).thenReturn(result3); + + mAndroidFontLookup.getUniqueNameLookupTable(mGetUniqueNameLookupTableCallback); + + mMojoTestRule.runLoop(RUN_LOOP_TIMEOUT_MS); + verify(mGetUniqueNameLookupTableCallback).call(aryEq(expected)); + } + + @SmallTest + @Test public void testMatchLocalFontByUniqueName_UnsupportedFontName() { - mAndroidFontLookup.matchLocalFontByUniqueName("Bar", mMatchLocalFontByUniqueNameCallback); + mAndroidFontLookup.matchLocalFontByUniqueName("bar", mMatchLocalFontByUniqueNameCallback); mMojoTestRule.runLoop(RUN_LOOP_TIMEOUT_MS); verify(mMatchLocalFontByUniqueNameCallback,
diff --git a/content/public/app/content_main_delegate.cc b/content/public/app/content_main_delegate.cc index 57f1dcf..e6379748 100644 --- a/content/public/app/content_main_delegate.cc +++ b/content/public/app/content_main_delegate.cc
@@ -36,18 +36,6 @@ return 0; } -service_manager::ProcessType ContentMainDelegate::OverrideProcessType() { - return service_manager::ProcessType::kDefault; -} - -void ContentMainDelegate::AdjustServiceProcessCommandLine( - const service_manager::Identity& identity, - base::CommandLine* command_line) {} - -void ContentMainDelegate::OnServiceManagerInitialized( - base::OnceClosure quit_closure, - service_manager::BackgroundServiceManager* service_manager) {} - bool ContentMainDelegate::ShouldCreateFeatureList() { return true; }
diff --git a/content/public/app/content_main_delegate.h b/content/public/app/content_main_delegate.h index a384cd8..abb46995 100644 --- a/content/public/app/content_main_delegate.h +++ b/content/public/app/content_main_delegate.h
@@ -9,19 +9,8 @@ #include <string> #include <vector> -#include "base/callback_forward.h" #include "build/build_config.h" #include "content/common/content_export.h" -#include "services/service_manager/embedder/process_type.h" - -namespace base { -class CommandLine; -} - -namespace service_manager { -class BackgroundServiceManager; -class Identity; -} // namespace service_manager namespace content { @@ -76,25 +65,6 @@ // returning initialization error code. Default behavior is CHECK(false). virtual int TerminateForFatalInitializationError(); - // Overrides the Service Manager process type to use for the currently running - // process. - virtual service_manager::ProcessType OverrideProcessType(); - - // Allows the content embedder to adjust arbitrary command line arguments for - // any service process started by the Service Manager. - virtual void AdjustServiceProcessCommandLine( - const service_manager::Identity& identity, - base::CommandLine* command_line); - - // Allows the embedder to perform arbitrary initialization within the Service - // Manager process immediately before the Service Manager runs its main loop. - // - // |quit_closure| is a callback the embedder may retain and invoke at any time - // to cleanly terminate Service Manager execution. - virtual void OnServiceManagerInitialized( - base::OnceClosure quit_closure, - service_manager::BackgroundServiceManager* service_manager); - // Allows the embedder to perform platform-specific initialization before // creating the main message loop. virtual void PreCreateMainMessageLoop() {}
diff --git a/content/public/browser/dedicated_worker_service.h b/content/public/browser/dedicated_worker_service.h index de8bec1..3f6cad0 100644 --- a/content/public/browser/dedicated_worker_service.h +++ b/content/public/browser/dedicated_worker_service.h
@@ -33,11 +33,9 @@ // Called when the final response URL (the URL after redirects) was // determined when fetching the worker's script. - // - // TODO(pmonette): Implement this in derived classes and make it pure. virtual void OnFinalResponseURLDetermined( const blink::DedicatedWorkerToken& worker_token, - const GURL& url) {} + const GURL& url) = 0; }; // Adds/removes an observer.
diff --git a/content/public/browser/desktop_media_id.cc b/content/public/browser/desktop_media_id.cc index c36a81c..31fb1bc 100644 --- a/content/public/browser/desktop_media_id.cc +++ b/content/public/browser/desktop_media_id.cc
@@ -22,11 +22,6 @@ const char kScreenPrefix[] = "screen"; const char kWindowPrefix[] = "window"; -// static -const DesktopMediaID::Id DesktopMediaID::kNullId = 0; -// static -const DesktopMediaID::Id DesktopMediaID::kFakeId = -3; - #if defined(USE_AURA) || defined(OS_MAC) // static DesktopMediaID DesktopMediaID::RegisterNativeWindow(DesktopMediaID::Type type, @@ -58,6 +53,10 @@ audio_share == other.audio_share; } +bool DesktopMediaID::operator!=(const DesktopMediaID& other) const { + return !(*this == other); +} + // static // Input string should in format: // for WebContents:
diff --git a/content/public/browser/desktop_media_id.h b/content/public/browser/desktop_media_id.h index 43c1fa44..c68f089 100644 --- a/content/public/browser/desktop_media_id.h +++ b/content/public/browser/desktop_media_id.h
@@ -24,9 +24,9 @@ typedef intptr_t Id; // Represents an "unset" value for either |id| or |window_id|. - static const Id kNullId; + static constexpr Id kNullId = 0; // Represents a fake id to create a dummy capturer for autotests. - static const Id kFakeId; + static constexpr Id kFakeId = -3; #if defined(USE_AURA) || defined(OS_MAC) // Assigns integer identifier to the |window| and returns its DesktopMediaID. @@ -53,6 +53,7 @@ // Operators so that DesktopMediaID can be used with STL containers. bool operator<(const DesktopMediaID& other) const; bool operator==(const DesktopMediaID& other) const; + bool operator!=(const DesktopMediaID& other) const; bool is_null() const { return type == TYPE_NONE; } std::string ToString() const;
diff --git a/content/public/test/browser_test_base.cc b/content/public/test/browser_test_base.cc index 15b5686..1638afd 100644 --- a/content/public/test/browser_test_base.cc +++ b/content/public/test/browser_test_base.cc
@@ -4,6 +4,7 @@ #include "content/public/test/browser_test_base.h" +#include <fcntl.h> #include <stddef.h> #include <iostream> @@ -16,6 +17,8 @@ #include "base/command_line.h" #include "base/debug/stack_trace.h" #include "base/feature_list.h" +#include "base/files/file_path.h" +#include "base/files/scoped_file.h" #include "base/i18n/icu_util.h" #include "base/location.h" #include "base/macros.h" @@ -33,6 +36,7 @@ #include "base/threading/thread_restrictions.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "content/browser/browser_main_loop.h" #include "content/browser/browser_thread_impl.h" #include "content/browser/network_service_instance_impl.h" @@ -62,6 +66,8 @@ #include "media/base/media_switches.h" #include "mojo/public/cpp/bindings/remote.h" #include "mojo/public/cpp/bindings/sync_call_restrictions.h" +#include "mojo/public/cpp/platform/named_platform_channel.h" +#include "mojo/public/cpp/platform/platform_channel.h" #include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "services/network/public/cpp/features.h" @@ -109,6 +115,14 @@ #include "ui/aura/test/event_generator_delegate_aura.h" // nogncheck #endif +#if BUILDFLAG(IS_LACROS) +#include "base/files/file_path.h" +#include "base/files/scoped_file.h" +#include "mojo/public/cpp/platform/named_platform_channel.h" +#include "mojo/public/cpp/platform/platform_channel.h" +#include "mojo/public/cpp/platform/socket_utils_posix.h" +#endif + namespace content { namespace { @@ -338,6 +352,45 @@ use_software_gl = false; #endif +#if BUILDFLAG(IS_LACROS) + // If the test is running on the lacros environment, a file descriptor needs + // to be obtained and used to launch lacros-chrome so that a mojo connection + // between lacros-chrome and ash-chrome can be established. + // For more details, please see: + // //chrome/browser/chromeos/crosapi/test_mojo_connection_manager.h. + { + // TODO(crbug.com/1127581): Switch to use |kLacrosMojoSocketForTesting| in + // //chromeos/constants/chromeos_switches.h. + // Please refer to the CL comments for why it can't be done now: + // http://crrev.com/c/2402580/2/content/public/test/browser_test_base.cc + std::string socket_path = + command_line->GetSwitchValueASCII("lacros-mojo-socket-for-testing"); + if (!socket_path.empty()) { + auto channel = mojo::NamedPlatformChannel::ConnectToServer(socket_path); + base::ScopedFD socket_fd = channel.TakePlatformHandle().TakeFD(); + + // Mark the channel as blocking. + int flags = fcntl(socket_fd.get(), F_GETFL); + PCHECK(flags != -1); + fcntl(socket_fd.get(), F_SETFL, flags & ~O_NONBLOCK); + + uint8_t buf[32]; + std::vector<base::ScopedFD> descriptors; + auto size = mojo::SocketRecvmsg(socket_fd.get(), buf, sizeof(buf), + &descriptors, true /*block*/); + if (size < 0) + PLOG(ERROR) << "Error receiving message from the socket"; + ASSERT_EQ(1, size); + EXPECT_EQ(0u, buf[0]); + ASSERT_EQ(1u, descriptors.size()); + // It's OK to release the FD because lacros-chrome's code will consume it. + command_line->AppendSwitchASCII( + mojo::PlatformChannel::kHandleSwitch, + base::NumberToString(descriptors[0].release())); + } + } +#endif + if (use_software_gl && !use_software_compositing_) command_line->AppendSwitch(switches::kOverrideUseSoftwareGLForTests);
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc index 0f770ba..539cefca 100644 --- a/content/public/test/browser_test_utils.cc +++ b/content/public/test/browser_test_utils.cc
@@ -688,12 +688,11 @@ mojo::AssociatedRemote<blink::mojom::FrameWidgetHost> blink_frame_widget_host; auto blink_frame_widget_host_receiver = - blink_frame_widget_host - .BindNewEndpointAndPassDedicatedReceiverForTesting(); + blink_frame_widget_host.BindNewEndpointAndPassDedicatedReceiver(); mojo::AssociatedRemote<blink::mojom::FrameWidget> blink_frame_widget; auto blink_frame_widget_receiver = - blink_frame_widget.BindNewEndpointAndPassDedicatedReceiverForTesting(); + blink_frame_widget.BindNewEndpointAndPassDedicatedReceiver(); render_widget_host_impl->BindFrameWidgetInterfaces( std::move(blink_frame_widget_host_receiver), blink_frame_widget.Unbind());
diff --git a/content/public/test/fake_render_widget_host.cc b/content/public/test/fake_render_widget_host.cc index b0dbf39..c9cd06e1 100644 --- a/content/public/test/fake_render_widget_host.cc +++ b/content/public/test/fake_render_widget_host.cc
@@ -18,9 +18,8 @@ frame_widget_host_receiver_.reset(); frame_widget_remote_.reset(); return std::make_pair( - frame_widget_host_receiver_ - .BindNewEndpointAndPassDedicatedRemoteForTesting(), - frame_widget_remote_.BindNewEndpointAndPassDedicatedReceiverForTesting()); + frame_widget_host_receiver_.BindNewEndpointAndPassDedicatedRemote(), + frame_widget_remote_.BindNewEndpointAndPassDedicatedReceiver()); } std::pair<mojo::PendingAssociatedRemote<blink::mojom::WidgetHost>, @@ -29,8 +28,8 @@ widget_host_receiver_.reset(); widget_remote_.reset(); return std::make_pair( - widget_host_receiver_.BindNewEndpointAndPassDedicatedRemoteForTesting(), - widget_remote_.BindNewEndpointAndPassDedicatedReceiverForTesting()); + widget_host_receiver_.BindNewEndpointAndPassDedicatedRemote(), + widget_remote_.BindNewEndpointAndPassDedicatedReceiver()); } void FakeRenderWidgetHost::AnimateDoubleTapZoomInMainFrame(
diff --git a/content/public/test/mock_render_process_host.cc b/content/public/test/mock_render_process_host.cc index 28f1fdc..e77f6c9 100644 --- a/content/public/test/mock_render_process_host.cc +++ b/content/public/test/mock_render_process_host.cc
@@ -412,8 +412,8 @@ if (!renderer_interface_) { renderer_interface_ = std::make_unique<mojo::AssociatedRemote<mojom::Renderer>>(); - ignore_result(renderer_interface_ - ->BindNewEndpointAndPassDedicatedReceiverForTesting()); + ignore_result( + renderer_interface_->BindNewEndpointAndPassDedicatedReceiver()); } return renderer_interface_->get(); }
diff --git a/content/public/test/mock_render_thread.cc b/content/public/test/mock_render_thread.cc index 2ed3635..a81284d3 100644 --- a/content/public/test/mock_render_thread.cc +++ b/content/public/test/mock_render_thread.cc
@@ -335,14 +335,12 @@ mojo::AssociatedRemote<blink::mojom::FrameWidget> blink_frame_widget; mojo::PendingAssociatedReceiver<blink::mojom::FrameWidget> blink_frame_widget_receiver = - blink_frame_widget - .BindNewEndpointAndPassDedicatedReceiverForTesting(); + blink_frame_widget.BindNewEndpointAndPassDedicatedReceiver(); mojo::AssociatedRemote<blink::mojom::FrameWidgetHost> blink_frame_widget_host; mojo::PendingAssociatedReceiver<blink::mojom::FrameWidgetHost> blink_frame_widget_host_receiver = - blink_frame_widget_host - .BindNewEndpointAndPassDedicatedReceiverForTesting(); + blink_frame_widget_host.BindNewEndpointAndPassDedicatedReceiver(); reply->frame_widget = std::move(blink_frame_widget_receiver); reply->frame_widget_host = blink_frame_widget_host.Unbind();
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc index e82a95a..e162bc5 100644 --- a/content/renderer/render_view_browsertest.cc +++ b/content/renderer/render_view_browsertest.cc
@@ -1262,14 +1262,12 @@ mojo::AssociatedRemote<blink::mojom::FrameWidget> blink_frame_widget; mojo::PendingAssociatedReceiver<blink::mojom::FrameWidget> blink_frame_widget_receiver = - blink_frame_widget - .BindNewEndpointAndPassDedicatedReceiverForTesting(); + blink_frame_widget.BindNewEndpointAndPassDedicatedReceiver(); mojo::AssociatedRemote<blink::mojom::FrameWidgetHost> blink_frame_widget_host; mojo::PendingAssociatedReceiver<blink::mojom::FrameWidgetHost> blink_frame_widget_host_receiver = - blink_frame_widget_host - .BindNewEndpointAndPassDedicatedReceiverForTesting(); + blink_frame_widget_host.BindNewEndpointAndPassDedicatedReceiver(); widget_params->frame_widget = std::move(blink_frame_widget_receiver); widget_params->frame_widget_host = blink_frame_widget_host.Unbind();
diff --git a/content/renderer/render_widget_unittest.cc b/content/renderer/render_widget_unittest.cc index 1f6665da..1a1860b 100644 --- a/content/renderer/render_widget_unittest.cc +++ b/content/renderer/render_widget_unittest.cc
@@ -210,23 +210,21 @@ mojo::AssociatedRemote<blink::mojom::FrameWidget> frame_widget_remote; mojo::PendingAssociatedReceiver<blink::mojom::FrameWidget> frame_widget_receiver = - frame_widget_remote - .BindNewEndpointAndPassDedicatedReceiverForTesting(); + frame_widget_remote.BindNewEndpointAndPassDedicatedReceiver(); mojo::AssociatedRemote<blink::mojom::FrameWidgetHost> frame_widget_host; mojo::PendingAssociatedReceiver<blink::mojom::FrameWidgetHost> frame_widget_host_receiver = - frame_widget_host - .BindNewEndpointAndPassDedicatedReceiverForTesting(); + frame_widget_host.BindNewEndpointAndPassDedicatedReceiver(); mojo::AssociatedRemote<blink::mojom::Widget> widget_remote; mojo::PendingAssociatedReceiver<blink::mojom::Widget> widget_receiver = - widget_remote.BindNewEndpointAndPassDedicatedReceiverForTesting(); + widget_remote.BindNewEndpointAndPassDedicatedReceiver(); mojo::AssociatedRemote<blink::mojom::WidgetHost> widget_host; mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost> widget_host_receiver = - widget_host.BindNewEndpointAndPassDedicatedReceiverForTesting(); + widget_host.BindNewEndpointAndPassDedicatedReceiver(); web_view_ = blink::WebView::Create(/*client=*/&web_view_client_, /*is_hidden=*/false,
diff --git a/content/renderer/service_worker/service_worker_provider_context_unittest.cc b/content/renderer/service_worker/service_worker_provider_context_unittest.cc index ebf0190..c26c0b5 100644 --- a/content/renderer/service_worker/service_worker_provider_context_unittest.cc +++ b/content/renderer/service_worker/service_worker_provider_context_unittest.cc
@@ -332,8 +332,7 @@ mojo::AssociatedRemote<blink::mojom::ServiceWorkerContainerHost> host_remote; mojo::PendingAssociatedReceiver<blink::mojom::ServiceWorkerContainerHost> - host_receiver = - host_remote.BindNewEndpointAndPassDedicatedReceiverForTesting(); + host_receiver = host_remote.BindNewEndpointAndPassDedicatedReceiver(); // (1) In the case there is no WebSWProviderClient but SWProviderContext for // the provider, the passed reference should be adopted and owned by the @@ -341,7 +340,7 @@ mojo::AssociatedRemote<blink::mojom::ServiceWorkerContainer> container_remote; auto container_receiver = - container_remote.BindNewEndpointAndPassDedicatedReceiverForTesting(); + container_remote.BindNewEndpointAndPassDedicatedReceiver(); auto provider_context = base::MakeRefCounted<ServiceWorkerProviderContext>( blink::mojom::ServiceWorkerContainerType::kForWindow, std::move(container_receiver), host_remote.Unbind(), @@ -377,13 +376,12 @@ mojo::AssociatedRemote<blink::mojom::ServiceWorkerContainerHost> host_remote; mojo::PendingAssociatedReceiver<blink::mojom::ServiceWorkerContainerHost> - host_receiver = - host_remote.BindNewEndpointAndPassDedicatedReceiverForTesting(); + host_receiver = host_remote.BindNewEndpointAndPassDedicatedReceiver(); mojo::AssociatedRemote<blink::mojom::ServiceWorkerContainer> container_remote; auto container_receiver = - container_remote.BindNewEndpointAndPassDedicatedReceiverForTesting(); + container_remote.BindNewEndpointAndPassDedicatedReceiver(); auto provider_context = base::MakeRefCounted<ServiceWorkerProviderContext>( blink::mojom::ServiceWorkerContainerType::kForWindow, std::move(container_receiver), host_remote.Unbind(), @@ -411,12 +409,11 @@ TEST_F(ServiceWorkerProviderContextTest, SetController_Null) { mojo::AssociatedRemote<blink::mojom::ServiceWorkerContainerHost> host_remote; mojo::PendingAssociatedReceiver<blink::mojom::ServiceWorkerContainerHost> - host_receiver = - host_remote.BindNewEndpointAndPassDedicatedReceiverForTesting(); + host_receiver = host_remote.BindNewEndpointAndPassDedicatedReceiver(); mojo::AssociatedRemote<blink::mojom::ServiceWorkerContainer> container_remote; auto container_receiver = - container_remote.BindNewEndpointAndPassDedicatedReceiverForTesting(); + container_remote.BindNewEndpointAndPassDedicatedReceiver(); auto provider_context = base::MakeRefCounted<ServiceWorkerProviderContext>( blink::mojom::ServiceWorkerContainerType::kForWindow, std::move(container_receiver), host_remote.Unbind(), @@ -443,10 +440,10 @@ // ServiceWorkerContainer request. mojo::AssociatedRemote<blink::mojom::ServiceWorkerContainerHost> host_remote; FakeServiceWorkerContainerHost host( - host_remote.BindNewEndpointAndPassDedicatedReceiverForTesting()); + host_remote.BindNewEndpointAndPassDedicatedReceiver()); mojo::AssociatedRemote<blink::mojom::ServiceWorkerContainer> container_remote; auto container_receiver = - container_remote.BindNewEndpointAndPassDedicatedReceiverForTesting(); + container_remote.BindNewEndpointAndPassDedicatedReceiver(); // (1) Test if setting the controller via the CTOR works. @@ -659,7 +656,7 @@ mojo::AssociatedRemote<blink::mojom::ServiceWorkerContainer> container_remote; auto container_receiver = - container_remote.BindNewEndpointAndPassDedicatedReceiverForTesting(); + container_remote.BindNewEndpointAndPassDedicatedReceiver(); auto provider_context = base::MakeRefCounted<ServiceWorkerProviderContext>( blink::mojom::ServiceWorkerContainerType::kForWindow, std::move(container_receiver), @@ -682,12 +679,11 @@ mojo::AssociatedRemote<blink::mojom::ServiceWorkerContainerHost> host_remote; mojo::PendingAssociatedReceiver<blink::mojom::ServiceWorkerContainerHost> - host_receiver = - host_remote.BindNewEndpointAndPassDedicatedReceiverForTesting(); + host_receiver = host_remote.BindNewEndpointAndPassDedicatedReceiver(); mojo::AssociatedRemote<blink::mojom::ServiceWorkerContainer> container_remote; auto container_receiver = - container_remote.BindNewEndpointAndPassDedicatedReceiverForTesting(); + container_remote.BindNewEndpointAndPassDedicatedReceiver(); auto provider_context = base::MakeRefCounted<ServiceWorkerProviderContext>( blink::mojom::ServiceWorkerContainerType::kForWindow, std::move(container_receiver), host_remote.Unbind(), @@ -711,12 +707,11 @@ TEST_F(ServiceWorkerProviderContextTest, CountFeature) { mojo::AssociatedRemote<blink::mojom::ServiceWorkerContainerHost> host_remote; mojo::PendingAssociatedReceiver<blink::mojom::ServiceWorkerContainerHost> - host_receiver = - host_remote.BindNewEndpointAndPassDedicatedReceiverForTesting(); + host_receiver = host_remote.BindNewEndpointAndPassDedicatedReceiver(); mojo::AssociatedRemote<blink::mojom::ServiceWorkerContainer> container_remote; auto container_receiver = - container_remote.BindNewEndpointAndPassDedicatedReceiverForTesting(); + container_remote.BindNewEndpointAndPassDedicatedReceiver(); auto provider_context = base::MakeRefCounted<ServiceWorkerProviderContext>( blink::mojom::ServiceWorkerContainerType::kForWindow, std::move(container_receiver), host_remote.Unbind(), @@ -764,11 +759,10 @@ // Make the container host and container pointers. mojo::AssociatedRemote<blink::mojom::ServiceWorkerContainerHost> host_remote; mojo::PendingAssociatedReceiver<blink::mojom::ServiceWorkerContainerHost> - host_receiver = - host_remote.BindNewEndpointAndPassDedicatedReceiverForTesting(); + host_receiver = host_remote.BindNewEndpointAndPassDedicatedReceiver(); mojo::AssociatedRemote<blink::mojom::ServiceWorkerContainer> container_remote; auto container_receiver = - container_remote.BindNewEndpointAndPassDedicatedReceiverForTesting(); + container_remote.BindNewEndpointAndPassDedicatedReceiver(); // Make the provider context. auto provider_context = base::MakeRefCounted<ServiceWorkerProviderContext>( @@ -813,11 +807,10 @@ // Make the container host and container pointers. mojo::AssociatedRemote<blink::mojom::ServiceWorkerContainerHost> host_remote; mojo::PendingAssociatedReceiver<blink::mojom::ServiceWorkerContainerHost> - host_receiver = - host_remote.BindNewEndpointAndPassDedicatedReceiverForTesting(); + host_receiver = host_remote.BindNewEndpointAndPassDedicatedReceiver(); mojo::AssociatedRemote<blink::mojom::ServiceWorkerContainer> container_remote; auto container_receiver = - container_remote.BindNewEndpointAndPassDedicatedReceiverForTesting(); + container_remote.BindNewEndpointAndPassDedicatedReceiver(); // Make the ServiceWorkerProviderContext, passing it the controller, // container, and container host.
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 9f5dd16..444ee759 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -387,6 +387,7 @@ deps = [ ":content_test_mojo_bindings", "//base/third_party/dynamic_annotations", + "//build:chromeos_buildflags", "//cc:test_support", "//components/viz/client", "//components/viz/host",
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 85e4be0..00b788d2 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
@@ -130,11 +130,13 @@ crbug.com/1081973 [ win vulkan passthrough ] conformance2/textures/misc/compressed-tex-image.html [ Failure ] crbug.com/angleproject/4417 [ win d3d11 ] conformance2/rendering/framebuffer-render-to-layer.html [ Failure ] crbug.com/angleproject/4417 [ win d3d11 ] conformance2/rendering/framebuffer-render-to-layer-angle-issue.html [ Failure ] +crbug.com/1127867 [ win d3d11 ] conformance2/textures/image_data/tex-3d-rgb565-rgb-unsigned_byte.html [ RetryOnFailure ] # Intel flaky issues crbug.com/1122744 [ win d3d11 intel ] conformance/textures/misc/texparameter-test.html [ RetryOnFailure ] crbug.com/912579 [ 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 [ RetryOnFailure ] +crbug.com/1127867 [ win 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 ]
diff --git a/content/test/mock_widget.cc b/content/test/mock_widget.cc index 418be6b..e7e601d 100644 --- a/content/test/mock_widget.cc +++ b/content/test/mock_widget.cc
@@ -12,7 +12,7 @@ mojo::PendingAssociatedRemote<blink::mojom::Widget> MockWidget::GetNewRemote() { blink_widget_.reset(); - return blink_widget_.BindNewEndpointAndPassDedicatedRemoteForTesting(); + return blink_widget_.BindNewEndpointAndPassDedicatedRemote(); } const std::vector<blink::VisualProperties>&
diff --git a/content/test/test_render_frame.cc b/content/test/test_render_frame.cc index 49b353a..1986f5ee 100644 --- a/content/test/test_render_frame.cc +++ b/content/test/test_render_frame.cc
@@ -283,8 +283,7 @@ mojom::CommitNavigationParamsPtr commit_params) { mock_navigation_client_.reset(); BindNavigationClient( - mock_navigation_client_ - .BindNewEndpointAndPassDedicatedReceiverForTesting()); + mock_navigation_client_.BindNewEndpointAndPassDedicatedReceiver()); std::unique_ptr<blink::PendingURLLoaderFactoryBundle> pending_factory_bundle = ChildPendingURLLoaderFactoryBundle::CreateFromDefaultFactoryImpl( std::make_unique<network::NotImplementedURLLoaderFactory>()); @@ -314,8 +313,7 @@ const base::Optional<std::string>& error_page_content) { mock_navigation_client_.reset(); BindNavigationClient( - mock_navigation_client_ - .BindNewEndpointAndPassDedicatedReceiverForTesting()); + mock_navigation_client_.BindNewEndpointAndPassDedicatedReceiver()); std::unique_ptr<blink::PendingURLLoaderFactoryBundle> pending_factory_bundle = ChildPendingURLLoaderFactoryBundle::CreateFromDefaultFactoryImpl( std::make_unique<network::NotImplementedURLLoaderFactory>());
diff --git a/content/test/test_render_view_host.cc b/content/test/test_render_view_host.cc index 5cd069a9..01efd67 100644 --- a/content/test/test_render_view_host.cc +++ b/content/test/test_render_view_host.cc
@@ -280,17 +280,17 @@ mojo::AssociatedRemote<blink::mojom::WidgetHost> blink_widget_host; mojo::AssociatedRemote<blink::mojom::Widget> blink_widget; auto blink_widget_receiver = - blink_widget.BindNewEndpointAndPassDedicatedReceiverForTesting(); + blink_widget.BindNewEndpointAndPassDedicatedReceiver(); GetWidget()->BindWidgetInterfaces( - blink_widget_host.BindNewEndpointAndPassDedicatedReceiverForTesting(), + blink_widget_host.BindNewEndpointAndPassDedicatedReceiver(), blink_widget.Unbind()); mojo::AssociatedRemote<blink::mojom::FrameWidgetHost> frame_widget_host; mojo::AssociatedRemote<blink::mojom::FrameWidget> frame_widget; auto frame_widget_receiver = - frame_widget.BindNewEndpointAndPassDedicatedReceiverForTesting(); + frame_widget.BindNewEndpointAndPassDedicatedReceiver(); GetWidget()->BindFrameWidgetInterfaces( - frame_widget_host.BindNewEndpointAndPassDedicatedReceiverForTesting(), + frame_widget_host.BindNewEndpointAndPassDedicatedReceiver(), frame_widget.Unbind()); main_frame->SetRenderFrameCreated(true);
diff --git a/content/test/test_render_widget_host.cc b/content/test/test_render_widget_host.cc index f2940a9f..5e16091 100644 --- a/content/test/test_render_widget_host.cc +++ b/content/test/test_render_widget_host.cc
@@ -33,9 +33,9 @@ mojo::AssociatedRemote<blink::mojom::WidgetHost> blink_widget_host; mojo::AssociatedRemote<blink::mojom::Widget> blink_widget; auto blink_widget_receiver = - blink_widget.BindNewEndpointAndPassDedicatedReceiverForTesting(); + blink_widget.BindNewEndpointAndPassDedicatedReceiver(); BindWidgetInterfaces( - blink_widget_host.BindNewEndpointAndPassDedicatedReceiverForTesting(), + blink_widget_host.BindNewEndpointAndPassDedicatedReceiver(), blink_widget.Unbind()); }
diff --git a/device/BUILD.gn b/device/BUILD.gn index 932276b..6396a142 100644 --- a/device/BUILD.gn +++ b/device/BUILD.gn
@@ -20,6 +20,8 @@ test("device_unittests") { sources = [ "base/synchronization/one_writer_seqlock_unittest.cc", + "bluetooth/adapter_unittest.cc", + "bluetooth/advertisement_unittest.cc", "bluetooth/bluetooth_adapter_android_unittest.cc", "bluetooth/bluetooth_adapter_mac_metrics_unittest.mm", "bluetooth/bluetooth_adapter_mac_unittest.mm", @@ -144,12 +146,14 @@ "fido/ctap_request_unittest.cc", "fido/ctap_response_unittest.cc", "fido/fake_fido_discovery_unittest.cc", + "fido/fido_device_authenticator_unittest.cc", "fido/fido_device_discovery_unittest.cc", "fido/fido_parsing_utils_unittest.cc", "fido/fido_request_handler_unittest.cc", "fido/get_assertion_handler_unittest.cc", "fido/get_assertion_task_unittest.cc", "fido/hid/fido_hid_message_unittest.cc", + "fido/large_blob_unittest.cc", "fido/mac/browsing_data_deletion_unittest.mm", "fido/mac/credential_metadata_unittest.cc", "fido/mac/get_assertion_operation_unittest_mac.mm",
diff --git a/device/bluetooth/BUILD.gn b/device/bluetooth/BUILD.gn index e7c5f8f..a27105b6 100644 --- a/device/bluetooth/BUILD.gn +++ b/device/bluetooth/BUILD.gn
@@ -36,6 +36,8 @@ "//device/bluetooth/public/mojom/gatt_result_type_converter.h", "adapter.cc", "adapter.h", + "advertisement.cc", + "advertisement.h", "device.cc", "device.h", "discovery_session.cc",
diff --git a/device/bluetooth/adapter.cc b/device/bluetooth/adapter.cc index 4ff570e..13f0a70 100644 --- a/device/bluetooth/adapter.cc +++ b/device/bluetooth/adapter.cc
@@ -12,6 +12,7 @@ #include "base/callback_helpers.h" #include "base/memory/ptr_util.h" #include "build/build_config.h" +#include "device/bluetooth/advertisement.h" #include "device/bluetooth/bluetooth_socket.h" #include "device/bluetooth/device.h" #include "device/bluetooth/discovery_session.h" @@ -86,6 +87,31 @@ std::move(callback).Run(); } +void Adapter::RegisterAdvertisement(const device::BluetoothUUID& service_uuid, + const std::vector<uint8_t>& service_data, + RegisterAdvertisementCallback callback) { + auto advertisement_data = + std::make_unique<device::BluetoothAdvertisement::Data>( + device::BluetoothAdvertisement::ADVERTISEMENT_TYPE_BROADCAST); + + auto uuid_list = std::make_unique<device::BluetoothAdvertisement::UUIDList>(); + uuid_list->push_back(service_uuid.value()); + advertisement_data->set_service_uuids(std::move(uuid_list)); + + auto service_data_map = + std::make_unique<device::BluetoothAdvertisement::ServiceData>(); + service_data_map->emplace(service_uuid.value(), service_data); + advertisement_data->set_service_data(std::move(service_data_map)); + + auto copyable_callback = base::AdaptCallbackForRepeating(std::move(callback)); + adapter_->RegisterAdvertisement( + std::move(advertisement_data), + base::BindOnce(&Adapter::OnRegisterAdvertisement, + weak_ptr_factory_.GetWeakPtr(), copyable_callback), + base::BindOnce(&Adapter::OnRegisterAdvertisementError, + weak_ptr_factory_.GetWeakPtr(), copyable_callback)); +} + void Adapter::SetDiscoverable(bool discoverable, SetDiscoverableCallback callback) { auto copyable_callback = base::AdaptCallbackForRepeating(std::move(callback)); @@ -205,6 +231,23 @@ /*device=*/mojo::NullRemote()); } +void Adapter::OnRegisterAdvertisement( + RegisterAdvertisementCallback callback, + scoped_refptr<device::BluetoothAdvertisement> advertisement) { + mojo::PendingRemote<mojom::Advertisement> pending_advertisement; + mojo::MakeSelfOwnedReceiver( + std::make_unique<Advertisement>(std::move(advertisement)), + pending_advertisement.InitWithNewPipeAndPassReceiver()); + std::move(callback).Run(std::move(pending_advertisement)); +} + +void Adapter::OnRegisterAdvertisementError( + RegisterAdvertisementCallback callback, + device::BluetoothAdvertisement::ErrorCode error_code) { + DLOG(ERROR) << "Failed to register advertisement, error code: " << error_code; + std::move(callback).Run(/*advertisement=*/mojo::NullRemote()); +} + void Adapter::OnSetDiscoverable(SetDiscoverableCallback callback) { std::move(callback).Run(/*success=*/true); }
diff --git a/device/bluetooth/adapter.h b/device/bluetooth/adapter.h index 196ff885..f9d113a 100644 --- a/device/bluetooth/adapter.h +++ b/device/bluetooth/adapter.h
@@ -11,6 +11,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "device/bluetooth/bluetooth_adapter.h" +#include "device/bluetooth/bluetooth_advertisement.h" #include "device/bluetooth/bluetooth_gatt_connection.h" #include "device/bluetooth/public/cpp/bluetooth_uuid.h" #include "device/bluetooth/public/mojom/adapter.mojom.h" @@ -37,6 +38,9 @@ void GetInfo(GetInfoCallback callback) override; void AddObserver(mojo::PendingRemote<mojom::AdapterObserver> observer, AddObserverCallback callback) override; + void RegisterAdvertisement(const device::BluetoothUUID& service_uuid, + const std::vector<uint8_t>& service_data, + RegisterAdvertisementCallback callback) override; void SetDiscoverable(bool discoverable, SetDiscoverableCallback callback) override; void SetName(const std::string& name, SetNameCallback callback) override; @@ -74,6 +78,13 @@ void OnConnectError(ConnectToDeviceCallback callback, device::BluetoothDevice::ConnectErrorCode error_code); + void OnRegisterAdvertisement( + RegisterAdvertisementCallback callback, + scoped_refptr<device::BluetoothAdvertisement> advertisement); + void OnRegisterAdvertisementError( + RegisterAdvertisementCallback callback, + device::BluetoothAdvertisement::ErrorCode error_code); + void OnSetDiscoverable(SetDiscoverableCallback callback); void OnSetDiscoverableError(SetDiscoverableCallback callback);
diff --git a/device/bluetooth/adapter_unittest.cc b/device/bluetooth/adapter_unittest.cc new file mode 100644 index 0000000..e6e98d0 --- /dev/null +++ b/device/bluetooth/adapter_unittest.cc
@@ -0,0 +1,126 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/bluetooth/adapter.h" + +#include "base/callback_helpers.h" +#include "base/run_loop.h" +#include "base/test/bind_test_util.h" +#include "base/test/task_environment.h" +#include "device/bluetooth/bluetooth_advertisement.h" +#include "device/bluetooth/test/mock_bluetooth_adapter.h" +#include "device/bluetooth/test/mock_bluetooth_advertisement.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/cpp/bindings/remote.h" +#include "testing/gtest/include/gtest/gtest.h" + +using ::testing::_; +using testing::NiceMock; +using testing::Return; + +namespace { + +const char kServiceId[] = "00000000-0000-0000-0000-000000000001"; +const char kDeviceServiceDataStr[] = "ServiceData"; + +std::vector<uint8_t> GetByteVector(const std::string& str) { + return std::vector<uint8_t>(str.begin(), str.end()); +} + +class MockBluetoothAdapterWithAdvertisements + : public device::MockBluetoothAdapter { + public: + void RegisterAdvertisement( + std::unique_ptr<device::BluetoothAdvertisement::Data> advertisement_data, + device::BluetoothAdapter::CreateAdvertisementCallback callback, + device::BluetoothAdapter::AdvertisementErrorCallback error_callback) + override { + last_register_advertisement_args_ = + std::make_pair(*advertisement_data->service_uuids(), + *advertisement_data->service_data()); + + if (should_advertisement_registration_succeed_) { + std::move(callback).Run( + base::MakeRefCounted<device::MockBluetoothAdvertisement>()); + } else { + std::move(error_callback) + .Run(device::BluetoothAdvertisement::ErrorCode:: + INVALID_ADVERTISEMENT_ERROR_CODE); + } + } + + bool should_advertisement_registration_succeed_ = true; + base::Optional<std::pair<device::BluetoothAdvertisement::UUIDList, + device::BluetoothAdvertisement::ServiceData>> + last_register_advertisement_args_; + + protected: + ~MockBluetoothAdapterWithAdvertisements() override = default; +}; + +} // namespace + +namespace bluetooth { + +class AdapterTest : public testing::Test { + public: + AdapterTest() = default; + ~AdapterTest() override = default; + AdapterTest(const AdapterTest&) = delete; + AdapterTest& operator=(const AdapterTest&) = delete; + + void SetUp() override { + mock_bluetooth_adapter_ = base::MakeRefCounted< + NiceMock<MockBluetoothAdapterWithAdvertisements>>(); + ON_CALL(*mock_bluetooth_adapter_, IsPresent()).WillByDefault(Return(true)); + ON_CALL(*mock_bluetooth_adapter_, IsPowered()).WillByDefault(Return(true)); + + adapter_ = std::make_unique<Adapter>(mock_bluetooth_adapter_); + } + + protected: + void VerifyRegisterAdvertisement(bool should_succeed) { + mock_bluetooth_adapter_->should_advertisement_registration_succeed_ = + should_succeed; + + auto service_data = GetByteVector(kDeviceServiceDataStr); + mojo::Remote<mojom::Advertisement> advertisement; + + base::RunLoop run_loop; + adapter_->RegisterAdvertisement( + device::BluetoothUUID(kServiceId), service_data, + base::BindLambdaForTesting([&](mojo::PendingRemote<mojom::Advertisement> + pending_advertisement) { + EXPECT_EQ(should_succeed, pending_advertisement.is_valid()); + run_loop.Quit(); + })); + run_loop.Run(); + + auto& uuid_list = + mock_bluetooth_adapter_->last_register_advertisement_args_->first; + EXPECT_EQ(1u, uuid_list.size()); + EXPECT_EQ(kServiceId, uuid_list[0]); + EXPECT_EQ( + service_data, + mock_bluetooth_adapter_->last_register_advertisement_args_->second.at( + kServiceId)); + } + + scoped_refptr<NiceMock<MockBluetoothAdapterWithAdvertisements>> + mock_bluetooth_adapter_; + std::unique_ptr<Adapter> adapter_; + + private: + base::test::TaskEnvironment task_environment_; +}; + +TEST_F(AdapterTest, TestRegisterAdvertisement_Success) { + VerifyRegisterAdvertisement(/*should_succeed=*/true); +} + +TEST_F(AdapterTest, TestRegisterAdvertisement_Error) { + VerifyRegisterAdvertisement(/*should_succeed=*/false); +} + +} // namespace bluetooth
diff --git a/device/bluetooth/advertisement.cc b/device/bluetooth/advertisement.cc new file mode 100644 index 0000000..cdb8265 --- /dev/null +++ b/device/bluetooth/advertisement.cc
@@ -0,0 +1,46 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/bluetooth/advertisement.h" + +#include "base/bind.h" +#include "base/callback_helpers.h" + +namespace bluetooth { + +Advertisement::Advertisement( + scoped_refptr<device::BluetoothAdvertisement> bluetooth_advertisement) + : bluetooth_advertisement_(std::move(bluetooth_advertisement)) {} + +Advertisement::~Advertisement() { + Unregister(base::DoNothing()); +} + +void Advertisement::Unregister(UnregisterCallback callback) { + if (!bluetooth_advertisement_) + return; + + auto copyable_callback = base::AdaptCallbackForRepeating(std::move(callback)); + bluetooth_advertisement_->Unregister( + base::BindOnce(&Advertisement::OnUnregister, + weak_ptr_factory_.GetWeakPtr(), copyable_callback), + base::BindOnce(&Advertisement::OnUnregisterError, + weak_ptr_factory_.GetWeakPtr(), copyable_callback)); +} + +void Advertisement::OnUnregister(UnregisterCallback callback) { + bluetooth_advertisement_.reset(); + std::move(callback).Run(); +} + +void Advertisement::OnUnregisterError( + UnregisterCallback callback, + device::BluetoothAdvertisement::ErrorCode error_code) { + DLOG(ERROR) << "Failed to unregister advertisement, error code: " + << error_code; + bluetooth_advertisement_.reset(); + std::move(callback).Run(); +} + +} // namespace bluetooth
diff --git a/device/bluetooth/advertisement.h b/device/bluetooth/advertisement.h new file mode 100644 index 0000000..7746681 --- /dev/null +++ b/device/bluetooth/advertisement.h
@@ -0,0 +1,43 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_BLUETOOTH_ADVERTISEMENT_H_ +#define DEVICE_BLUETOOTH_ADVERTISEMENT_H_ + +#include "base/memory/ref_counted.h" +#include "device/bluetooth/bluetooth_advertisement.h" +#include "device/bluetooth/public/mojom/adapter.mojom.h" + +namespace bluetooth { + +// Implementation of Mojo Advertisement in +// device/bluetooth/public/mojom/adapter.mojom. +// Uses the platform abstraction of //device/bluetooth. +// An instance of this class is constructed by Adapter and strongly bound to its +// MessagePipe. When the instance is destroyed, the underlying +// BluetoothAdvertisement is destroyed. +class Advertisement : public mojom::Advertisement { + public: + explicit Advertisement( + scoped_refptr<device::BluetoothAdvertisement> bluetooth_advertisement); + ~Advertisement() override; + Advertisement(const Advertisement&) = delete; + Advertisement& operator=(const Advertisement&) = delete; + + // mojom::Advertisement: + void Unregister(UnregisterCallback callback) override; + + private: + void OnUnregister(UnregisterCallback callback); + void OnUnregisterError(UnregisterCallback callback, + device::BluetoothAdvertisement::ErrorCode error_code); + + scoped_refptr<device::BluetoothAdvertisement> bluetooth_advertisement_; + + base::WeakPtrFactory<Advertisement> weak_ptr_factory_{this}; +}; + +} // namespace bluetooth + +#endif // DEVICE_BLUETOOTH_ADVERTISEMENT_H_
diff --git a/device/bluetooth/advertisement_unittest.cc b/device/bluetooth/advertisement_unittest.cc new file mode 100644 index 0000000..2dd863c --- /dev/null +++ b/device/bluetooth/advertisement_unittest.cc
@@ -0,0 +1,73 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/bluetooth/advertisement.h" + +#include "base/run_loop.h" +#include "base/test/task_environment.h" +#include "device/bluetooth/bluetooth_advertisement.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +class FakeBluetoothAdvertisement : public device::BluetoothAdvertisement { + public: + // device::BluetoothAdvertisement: + void Unregister(SuccessCallback success_callback, + ErrorCallback error_callback) override { + called_unregister_ = true; + std::move(success_callback).Run(); + } + + bool called_unregister() { return called_unregister_; } + + private: + ~FakeBluetoothAdvertisement() override = default; + + bool called_unregister_ = false; +}; + +} // namespace + +namespace bluetooth { + +class AdvertisementTest : public testing::Test { + public: + AdvertisementTest() = default; + ~AdvertisementTest() override = default; + AdvertisementTest(const AdvertisementTest&) = delete; + AdvertisementTest& operator=(const AdvertisementTest&) = delete; + + void SetUp() override { + fake_bluetooth_advertisement_ = + base::MakeRefCounted<FakeBluetoothAdvertisement>(); + advertisement_ = + std::make_unique<Advertisement>(fake_bluetooth_advertisement_); + } + + protected: + scoped_refptr<FakeBluetoothAdvertisement> fake_bluetooth_advertisement_; + std::unique_ptr<Advertisement> advertisement_; + + private: + base::test::TaskEnvironment task_environment_; +}; + +TEST_F(AdvertisementTest, TestOnDestroyCallsUnregister) { + // When destroyed, |advertisement_| is expected to tear down its + // BluetoothAdvertisement. + ASSERT_FALSE(fake_bluetooth_advertisement_->called_unregister()); + advertisement_.reset(); + EXPECT_TRUE(fake_bluetooth_advertisement_->called_unregister()); +} + +TEST_F(AdvertisementTest, TestUnregister) { + ASSERT_FALSE(fake_bluetooth_advertisement_->called_unregister()); + base::RunLoop run_loop; + advertisement_->Unregister(run_loop.QuitClosure()); + run_loop.Run(); + EXPECT_TRUE(fake_bluetooth_advertisement_->called_unregister()); +} + +} // namespace bluetooth
diff --git a/device/bluetooth/public/mojom/adapter.mojom b/device/bluetooth/public/mojom/adapter.mojom index 24a9ab1..5d7fc04a 100644 --- a/device/bluetooth/public/mojom/adapter.mojom +++ b/device/bluetooth/public/mojom/adapter.mojom
@@ -49,6 +49,22 @@ bool discovering; }; +// Represents an ongoing BLE advertisement. Releasing it will release the +// underlying object and stop the advertisement, but callers should prefer to +// let a call to Unregister() to finish first. +// Note: Methods which are declared [Sync] are for use by +// //chrome/services/sharing/nearby; all other usage of their synchronous +// signatures is strongly discouraged. +interface Advertisement { + // Use to gracefully stop advertising before destroying the message pipe. The + // reply callback can be used to synchronize an attempt to re-register an + // advertisement; attempting to register an advertisement without first + // releasing limited advertisement slots in the hardware may fail with a + // busy error. + [Sync] + Unregister() => (); +}; + // Represents a request to discover nearby devices. // Note: Methods which are declared [Sync] are for use by // //chrome/services/sharing/nearby; all other usage of their synchronous @@ -128,6 +144,22 @@ [Sync] AddObserver(pending_remote<AdapterObserver> observer) => (); + // Requests the adapter to broadcast a BLE advertisement on |service_id| with + // the associated packet |service_data|. Returns null if advertisement is not + // registered successfully. + // Important notes: + // * This method registers a "non-connectable" advertisement. Any future + // effort to allow this API to support "connectable" advertisements would + // also require the addition of an API to support hosting a GATT server. + // * Bluetooth chips generally can only broadcast a few advertisements, + // sometimes even only one, simultaneously. This can be mitigated by + // operating systems "rotating" advertisements in the higher software layer, + // as Chrome OS does. Non-Chrome OS clients of this API are responsible for + // understanding their host OS's and/or hardware's limitations. + [Sync] + RegisterAdvertisement(UUID service_id, array<uint8> service_data) => + (pending_remote<Advertisement>? advertisement); + // Requests the local device to make itself discoverable to nearby remote // devices. [Sync]
diff --git a/device/fido/BUILD.gn b/device/fido/BUILD.gn index a5a5d64b..0c071c7 100644 --- a/device/fido/BUILD.gn +++ b/device/fido/BUILD.gn
@@ -160,6 +160,8 @@ "hid/fido_hid_message.h", "hid/fido_hid_packet.cc", "hid/fido_hid_packet.h", + "large_blob.cc", + "large_blob.h", "make_credential_request_handler.cc", "make_credential_request_handler.h", "make_credential_task.cc",
diff --git a/device/fido/bio/enrollment.h b/device/fido/bio/enrollment.h index 92ff22a0..77ee7dc 100644 --- a/device/fido/bio/enrollment.h +++ b/device/fido/bio/enrollment.h
@@ -145,7 +145,7 @@ ~BioEnrollmentRequest(); private: - BioEnrollmentRequest(Version); + explicit BioEnrollmentRequest(Version); }; struct COMPONENT_EXPORT(DEVICE_FIDO) BioEnrollmentResponse {
diff --git a/device/fido/ctap_get_assertion_request.h b/device/fido/ctap_get_assertion_request.h index 72858c0..bec6388 100644 --- a/device/fido/ctap_get_assertion_request.h +++ b/device/fido/ctap_get_assertion_request.h
@@ -19,6 +19,7 @@ #include "device/fido/cable/cable_discovery_data.h" #include "device/fido/client_data.h" #include "device/fido/fido_constants.h" +#include "device/fido/large_blob.h" #include "device/fido/pin.h" #include "device/fido/public_key_credential_descriptor.h" @@ -57,6 +58,10 @@ // it will be the first element and all others will have |credential_id|s. // Elements are sorted by |credential_id|s, where present. std::vector<PRFInput> prf_inputs; + + // large_blob_operation indicates whether we should attempt to read or write a + // large blob after a successful assertion. + LargeBlobOperation large_blob_operation; }; // Object that encapsulates request parameters for AuthenticatorGetAssertion as
diff --git a/device/fido/device_response_converter.cc b/device/fido/device_response_converter.cc index 7e6e910..002fc03 100644 --- a/device/fido/device_response_converter.cc +++ b/device/fido/device_response_converter.cc
@@ -67,7 +67,7 @@ return CtapDeviceResponseCode::kCtap2ErrInvalidCBOR; auto code = static_cast<CtapDeviceResponseCode>(buffer[0]); - return base::Contains(GetCtapResponseCodeList(), code) + return base::Contains(kCtapResponseCodeList, code) ? code : CtapDeviceResponseCode::kCtap2ErrInvalidCBOR; }
diff --git a/device/fido/fido_authenticator.cc b/device/fido/fido_authenticator.cc index 653b48f..abd4025 100644 --- a/device/fido/fido_authenticator.cc +++ b/device/fido/fido_authenticator.cc
@@ -128,6 +128,21 @@ NOTREACHED(); } +void FidoAuthenticator::WriteLargeBlob( + const std::vector<uint8_t>& large_blob, + const LargeBlobKey& large_blob_key, + const base::Optional<pin::TokenResponse> pin_uv_auth_token, + base::OnceCallback<void(CtapDeviceResponseCode)> callback) { + NOTREACHED(); +} + +void FidoAuthenticator::ReadLargeBlob( + const std::vector<const LargeBlobKey>& large_blob_keys, + const base::Optional<pin::TokenResponse> pin_uv_auth_token, + LargeBlobReadCallback callback) { + NOTREACHED(); +} + base::Optional<base::span<const int32_t>> FidoAuthenticator::GetAlgorithms() { return base::nullopt; }
diff --git a/device/fido/fido_authenticator.h b/device/fido/fido_authenticator.h index ad98403..71657de4 100644 --- a/device/fido/fido_authenticator.h +++ b/device/fido/fido_authenticator.h
@@ -5,6 +5,7 @@ #ifndef DEVICE_FIDO_FIDO_AUTHENTICATOR_H_ #define DEVICE_FIDO_FIDO_AUTHENTICATOR_H_ +#include <cstdint> #include <string> #include "base/callback_forward.h" @@ -20,8 +21,10 @@ #include "device/fido/authenticator_supported_options.h" #include "device/fido/bio/enrollment.h" #include "device/fido/credential_management.h" +#include "device/fido/fido_constants.h" #include "device/fido/fido_request_handler_base.h" #include "device/fido/fido_transport_protocol.h" +#include "device/fido/large_blob.h" namespace device { @@ -70,6 +73,10 @@ using BioEnrollmentCallback = base::OnceCallback<void(CtapDeviceResponseCode, base::Optional<BioEnrollmentResponse>)>; + using LargeBlobReadCallback = base::OnceCallback<void( + CtapDeviceResponseCode, + base::Optional<std::vector<std::pair<LargeBlobKey, std::vector<uint8_t>>>> + callback)>; FidoAuthenticator() = default; virtual ~FidoAuthenticator() = default; @@ -202,6 +209,21 @@ std::vector<uint8_t> template_id, BioEnrollmentCallback); + // Large blob commands. + // Attempts to write a |large_blob| into the credential. If there is an + // existing credential for the |large_blob_key|, it will be overwritten. + virtual void WriteLargeBlob( + const std::vector<uint8_t>& large_blob, + const LargeBlobKey& large_blob_key, + base::Optional<pin::TokenResponse> pin_uv_auth_token, + base::OnceCallback<void(CtapDeviceResponseCode)> callback); + // Attempts to read large blobs from the credential encrypted with + // |large_blob_keys|. Returns a map of keys to their blobs. + virtual void ReadLargeBlob( + const std::vector<const LargeBlobKey>& large_blob_keys, + base::Optional<pin::TokenResponse> pin_uv_auth_token, + LargeBlobReadCallback callback); + // GetAlgorithms returns the list of supported COSEAlgorithmIdentifiers, or // |nullopt| if this is unknown and thus all requests should be tried in case // they work.
diff --git a/device/fido/fido_constants.h b/device/fido/fido_constants.h index 2f03c37d..b7c62f0 100644 --- a/device/fido/fido_constants.h +++ b/device/fido/fido_constants.h
@@ -88,7 +88,7 @@ kCtap2ErrLimitExceeded = 0x15, kCtap2ErrUnsupportedExtension = 0x16, kCtap2ErrTooManyElements = 0x17, - kCtap2ErrExtensionNotSupported = 0x18, + kCtap2ErrLargeBlobStorageFull = 0x18, kCtap2ErrCredentialExcluded = 0x19, kCtap2ErrProcesssing = 0x21, kCtap2ErrInvalidCredential = 0x22, @@ -116,6 +116,7 @@ kCtap2ErrPinTokenExpired = 0x38, kCtap2ErrRequestTooLarge = 0x39, kCtap2ErrUvBlocked = 0x3C, + kCtap2ErrIntegrityFailure = 0x3D, kCtap2ErrOther = 0x7F, kCtap2ErrSpecLast = 0xDF, kCtap2ErrExtensionFirst = 0xE0, @@ -124,57 +125,58 @@ kCtap2ErrVendorLast = 0xFF }; -constexpr std::array<CtapDeviceResponseCode, 49> GetCtapResponseCodeList() { - return {CtapDeviceResponseCode::kSuccess, - CtapDeviceResponseCode::kCtap1ErrInvalidCommand, - CtapDeviceResponseCode::kCtap1ErrInvalidParameter, - CtapDeviceResponseCode::kCtap1ErrInvalidLength, - CtapDeviceResponseCode::kCtap1ErrInvalidSeq, - CtapDeviceResponseCode::kCtap1ErrTimeout, - CtapDeviceResponseCode::kCtap1ErrChannelBusy, - CtapDeviceResponseCode::kCtap1ErrLockRequired, - CtapDeviceResponseCode::kCtap1ErrInvalidChannel, - CtapDeviceResponseCode::kCtap2ErrCBORUnexpectedType, - CtapDeviceResponseCode::kCtap2ErrInvalidCBOR, - CtapDeviceResponseCode::kCtap2ErrMissingParameter, - CtapDeviceResponseCode::kCtap2ErrLimitExceeded, - CtapDeviceResponseCode::kCtap2ErrUnsupportedExtension, - CtapDeviceResponseCode::kCtap2ErrTooManyElements, - CtapDeviceResponseCode::kCtap2ErrExtensionNotSupported, - CtapDeviceResponseCode::kCtap2ErrCredentialExcluded, - CtapDeviceResponseCode::kCtap2ErrProcesssing, - CtapDeviceResponseCode::kCtap2ErrInvalidCredential, - CtapDeviceResponseCode::kCtap2ErrUserActionPending, - CtapDeviceResponseCode::kCtap2ErrOperationPending, - CtapDeviceResponseCode::kCtap2ErrNoOperations, - CtapDeviceResponseCode::kCtap2ErrUnsupportedAlgorithm, - CtapDeviceResponseCode::kCtap2ErrOperationDenied, - CtapDeviceResponseCode::kCtap2ErrKeyStoreFull, - CtapDeviceResponseCode::kCtap2ErrNotBusy, - CtapDeviceResponseCode::kCtap2ErrNoOperationPending, - CtapDeviceResponseCode::kCtap2ErrUnsupportedOption, - CtapDeviceResponseCode::kCtap2ErrInvalidOption, - CtapDeviceResponseCode::kCtap2ErrKeepAliveCancel, - CtapDeviceResponseCode::kCtap2ErrNoCredentials, - CtapDeviceResponseCode::kCtap2ErrUserActionTimeout, - CtapDeviceResponseCode::kCtap2ErrNotAllowed, - CtapDeviceResponseCode::kCtap2ErrPinInvalid, - CtapDeviceResponseCode::kCtap2ErrPinBlocked, - CtapDeviceResponseCode::kCtap2ErrPinAuthInvalid, - CtapDeviceResponseCode::kCtap2ErrPinAuthBlocked, - CtapDeviceResponseCode::kCtap2ErrPinNotSet, - CtapDeviceResponseCode::kCtap2ErrPinRequired, - CtapDeviceResponseCode::kCtap2ErrPinPolicyViolation, - CtapDeviceResponseCode::kCtap2ErrPinTokenExpired, - CtapDeviceResponseCode::kCtap2ErrRequestTooLarge, - CtapDeviceResponseCode::kCtap2ErrUvBlocked, - CtapDeviceResponseCode::kCtap2ErrOther, - CtapDeviceResponseCode::kCtap2ErrSpecLast, - CtapDeviceResponseCode::kCtap2ErrExtensionFirst, - CtapDeviceResponseCode::kCtap2ErrExtensionLast, - CtapDeviceResponseCode::kCtap2ErrVendorFirst, - CtapDeviceResponseCode::kCtap2ErrVendorLast}; -} +constexpr std::array<CtapDeviceResponseCode, 50> kCtapResponseCodeList{ + CtapDeviceResponseCode::kSuccess, + CtapDeviceResponseCode::kCtap1ErrInvalidCommand, + CtapDeviceResponseCode::kCtap1ErrInvalidParameter, + CtapDeviceResponseCode::kCtap1ErrInvalidLength, + CtapDeviceResponseCode::kCtap1ErrInvalidSeq, + CtapDeviceResponseCode::kCtap1ErrTimeout, + CtapDeviceResponseCode::kCtap1ErrChannelBusy, + CtapDeviceResponseCode::kCtap1ErrLockRequired, + CtapDeviceResponseCode::kCtap1ErrInvalidChannel, + CtapDeviceResponseCode::kCtap2ErrCBORUnexpectedType, + CtapDeviceResponseCode::kCtap2ErrInvalidCBOR, + CtapDeviceResponseCode::kCtap2ErrMissingParameter, + CtapDeviceResponseCode::kCtap2ErrLimitExceeded, + CtapDeviceResponseCode::kCtap2ErrUnsupportedExtension, + CtapDeviceResponseCode::kCtap2ErrTooManyElements, + CtapDeviceResponseCode::kCtap2ErrLargeBlobStorageFull, + CtapDeviceResponseCode::kCtap2ErrCredentialExcluded, + CtapDeviceResponseCode::kCtap2ErrProcesssing, + CtapDeviceResponseCode::kCtap2ErrInvalidCredential, + CtapDeviceResponseCode::kCtap2ErrUserActionPending, + CtapDeviceResponseCode::kCtap2ErrOperationPending, + CtapDeviceResponseCode::kCtap2ErrNoOperations, + CtapDeviceResponseCode::kCtap2ErrUnsupportedAlgorithm, + CtapDeviceResponseCode::kCtap2ErrOperationDenied, + CtapDeviceResponseCode::kCtap2ErrKeyStoreFull, + CtapDeviceResponseCode::kCtap2ErrNotBusy, + CtapDeviceResponseCode::kCtap2ErrNoOperationPending, + CtapDeviceResponseCode::kCtap2ErrUnsupportedOption, + CtapDeviceResponseCode::kCtap2ErrInvalidOption, + CtapDeviceResponseCode::kCtap2ErrKeepAliveCancel, + CtapDeviceResponseCode::kCtap2ErrNoCredentials, + CtapDeviceResponseCode::kCtap2ErrUserActionTimeout, + CtapDeviceResponseCode::kCtap2ErrNotAllowed, + CtapDeviceResponseCode::kCtap2ErrPinInvalid, + CtapDeviceResponseCode::kCtap2ErrPinBlocked, + CtapDeviceResponseCode::kCtap2ErrPinAuthInvalid, + CtapDeviceResponseCode::kCtap2ErrPinAuthBlocked, + CtapDeviceResponseCode::kCtap2ErrPinNotSet, + CtapDeviceResponseCode::kCtap2ErrPinRequired, + CtapDeviceResponseCode::kCtap2ErrPinPolicyViolation, + CtapDeviceResponseCode::kCtap2ErrPinTokenExpired, + CtapDeviceResponseCode::kCtap2ErrRequestTooLarge, + CtapDeviceResponseCode::kCtap2ErrUvBlocked, + CtapDeviceResponseCode::kCtap2ErrIntegrityFailure, + CtapDeviceResponseCode::kCtap2ErrOther, + CtapDeviceResponseCode::kCtap2ErrSpecLast, + CtapDeviceResponseCode::kCtap2ErrExtensionFirst, + CtapDeviceResponseCode::kCtap2ErrExtensionLast, + CtapDeviceResponseCode::kCtap2ErrVendorFirst, + CtapDeviceResponseCode::kCtap2ErrVendorLast, +}; // Commands supported by CTAPHID device as specified in // https://fidoalliance.org/specs/fido-v2.0-rd-20170927/fido-client-to-authenticator-protocol-v2.0-rd-20170927.html#ctaphid-commands @@ -232,6 +234,7 @@ kAuthenticatorClientPin = 0x06, kAuthenticatorReset = 0x07, kAuthenticatorBioEnrollment = 0x09, + kAuthenticatorLargeBlobs = 0x0C, kAuthenticatorBioEnrollmentPreview = 0x40, kAuthenticatorCredentialManagement = 0x0a, kAuthenticatorCredentialManagementPreview = 0x41,
diff --git a/device/fido/fido_device_authenticator.cc b/device/fido/fido_device_authenticator.cc index 2779c22a..99ce668 100644 --- a/device/fido/fido_device_authenticator.cc +++ b/device/fido/fido_device_authenticator.cc
@@ -4,6 +4,7 @@ #include "device/fido/fido_device_authenticator.h" +#include <algorithm> #include <numeric> #include <utility> @@ -16,9 +17,11 @@ #include "device/fido/ctap_get_assertion_request.h" #include "device/fido/ctap_make_credential_request.h" #include "device/fido/features.h" +#include "device/fido/fido_constants.h" #include "device/fido/fido_device.h" #include "device/fido/fido_parsing_utils.h" #include "device/fido/get_assertion_task.h" +#include "device/fido/large_blob.h" #include "device/fido/make_credential_task.h" #include "device/fido/pin.h" #include "device/fido/u2f_command_constructor.h" @@ -730,6 +733,193 @@ std::move(callback), base::BindOnce(&BioEnrollmentResponse::Parse)); } +void FidoDeviceAuthenticator::WriteLargeBlob( + const std::vector<uint8_t>& large_blob, + const LargeBlobKey& large_blob_key, + const base::Optional<pin::TokenResponse> pin_uv_auth_token, + base::OnceCallback<void(CtapDeviceResponseCode)> callback) { + auto pin_uv_auth_token_copy = pin_uv_auth_token; + FetchLargeBlobArray( + pin_uv_auth_token_copy, LargeBlobArrayReader(), + base::BindOnce(&FidoDeviceAuthenticator::OnHaveLargeBlobArrayForWrite, + weak_factory_.GetWeakPtr(), large_blob, large_blob_key, + std::move(pin_uv_auth_token), std::move(callback))); +} + +void FidoDeviceAuthenticator::ReadLargeBlob( + const std::vector<const LargeBlobKey>& large_blob_keys, + const base::Optional<pin::TokenResponse> pin_uv_auth_token, + LargeBlobReadCallback callback) { + FetchLargeBlobArray( + std::move(pin_uv_auth_token), LargeBlobArrayReader(), + base::BindOnce(&FidoDeviceAuthenticator::OnHaveLargeBlobArrayForRead, + weak_factory_.GetWeakPtr(), large_blob_keys, + std::move(callback))); +} + +void FidoDeviceAuthenticator::FetchLargeBlobArray( + const base::Optional<pin::TokenResponse> pin_uv_auth_token, + LargeBlobArrayReader large_blob_array_reader, + base::OnceCallback<void(CtapDeviceResponseCode, + base::Optional<LargeBlobArrayReader>)> callback) { + size_t bytes_to_read = max_large_blob_fragment_length(); + LargeBlobsRequest request = + LargeBlobsRequest::ForRead(bytes_to_read, large_blob_array_reader.size()); + if (pin_uv_auth_token) { + request.SetPinParam(*pin_uv_auth_token); + } + RunOperation<LargeBlobsRequest, LargeBlobsResponse>( + std::move(request), + base::BindOnce(&FidoDeviceAuthenticator::OnReadLargeBlobFragment, + weak_factory_.GetWeakPtr(), bytes_to_read, + std::move(large_blob_array_reader), + std::move(pin_uv_auth_token), std::move(callback)), + base::BindOnce(&LargeBlobsResponse::ParseForRead, bytes_to_read)); +} + +void FidoDeviceAuthenticator::OnReadLargeBlobFragment( + const size_t bytes_requested, + LargeBlobArrayReader large_blob_array_reader, + const base::Optional<pin::TokenResponse> pin_uv_auth_token, + base::OnceCallback<void(CtapDeviceResponseCode, + base::Optional<LargeBlobArrayReader>)> callback, + CtapDeviceResponseCode status, + base::Optional<LargeBlobsResponse> response) { + if (status != CtapDeviceResponseCode::kSuccess) { + std::move(callback).Run(status, base::nullopt); + return; + } + + DCHECK(response && response->config()); + large_blob_array_reader.Append(*response->config()); + + if (response->config()->size() == bytes_requested) { + // More data may be available, read the next fragment. + FetchLargeBlobArray(std::move(pin_uv_auth_token), + std::move(large_blob_array_reader), + std::move(callback)); + return; + } + + std::move(callback).Run(CtapDeviceResponseCode::kSuccess, + std::move(large_blob_array_reader)); +} + +void FidoDeviceAuthenticator::OnHaveLargeBlobArrayForWrite( + const std::vector<uint8_t>& large_blob, + const LargeBlobKey& large_blob_key, + const base::Optional<pin::TokenResponse> pin_uv_auth_token, + base::OnceCallback<void(CtapDeviceResponseCode)> callback, + CtapDeviceResponseCode status, + base::Optional<LargeBlobArrayReader> large_blob_array_reader) { + if (status != CtapDeviceResponseCode::kSuccess) { + std::move(callback).Run(status); + return; + } + + base::Optional<std::vector<LargeBlobData>> large_blob_array = + large_blob_array_reader->Materialize(); + if (!large_blob_array) { + // The large blob array is corrupted. Replace it completely with a new one. + // TODO(nsatragno): but maybe we want to do something else like trying + // again? It might have been corrupted while transported. Decide when we + // have hardware to test. + large_blob_array.emplace(); + return; + } + + auto existing_large_blob = + std::find_if(large_blob_array->begin(), large_blob_array->end(), + [&large_blob_key](const LargeBlobData& blob) { + return blob.Decrypt(large_blob_key); + }); + + LargeBlobData new_large_blob_data(large_blob_key, large_blob); + if (existing_large_blob != large_blob_array->end()) { + *existing_large_blob = std::move(new_large_blob_data); + } else { + large_blob_array->emplace_back(std::move(new_large_blob_data)); + } + + WriteLargeBlobArray(std::move(pin_uv_auth_token), + LargeBlobArrayWriter(*large_blob_array), + std::move(callback)); +} + +void FidoDeviceAuthenticator::WriteLargeBlobArray( + const base::Optional<pin::TokenResponse> pin_uv_auth_token, + LargeBlobArrayWriter large_blob_array_writer, + base::OnceCallback<void(CtapDeviceResponseCode)> callback) { + LargeBlobArrayFragment fragment = + large_blob_array_writer.Pop(max_large_blob_fragment_length()); + + LargeBlobsRequest request = LargeBlobsRequest::ForWrite( + std::move(fragment), large_blob_array_writer.size()); + if (pin_uv_auth_token) { + request.SetPinParam(*pin_uv_auth_token); + } + RunOperation<LargeBlobsRequest, LargeBlobsResponse>( + std::move(request), + base::BindOnce(&FidoDeviceAuthenticator::OnWriteLargeBlobFragment, + weak_factory_.GetWeakPtr(), + std::move(large_blob_array_writer), + std::move(pin_uv_auth_token), std::move(callback)), + base::BindOnce(&LargeBlobsResponse::ParseForWrite)); +} + +void FidoDeviceAuthenticator::OnWriteLargeBlobFragment( + LargeBlobArrayWriter large_blob_array_writer, + const base::Optional<pin::TokenResponse> pin_uv_auth_token, + base::OnceCallback<void(CtapDeviceResponseCode)> callback, + CtapDeviceResponseCode status, + base::Optional<LargeBlobsResponse> response) { + if (status != CtapDeviceResponseCode::kSuccess) { + std::move(callback).Run(status); + return; + } + + if (large_blob_array_writer.has_remaining_fragments()) { + WriteLargeBlobArray(std::move(pin_uv_auth_token), + std::move(large_blob_array_writer), + std::move(callback)); + return; + } + + std::move(callback).Run(CtapDeviceResponseCode::kSuccess); +} + +void FidoDeviceAuthenticator::OnHaveLargeBlobArrayForRead( + const std::vector<const LargeBlobKey>& large_blob_keys, + LargeBlobReadCallback callback, + CtapDeviceResponseCode status, + base::Optional<LargeBlobArrayReader> large_blob_array_reader) { + if (status != CtapDeviceResponseCode::kSuccess) { + std::move(callback).Run(status, base::nullopt); + return; + } + + base::Optional<std::vector<LargeBlobData>> large_blob_array = + large_blob_array_reader->Materialize(); + if (!large_blob_array) { + std::move(callback).Run(CtapDeviceResponseCode::kCtap2ErrIntegrityFailure, + base::nullopt); + return; + } + + std::vector<std::pair<LargeBlobKey, std::vector<uint8_t>>> result; + for (const LargeBlobData& blob : *large_blob_array) { + for (const LargeBlobKey& key : large_blob_keys) { + base::Optional<std::vector<uint8_t>> plaintext = blob.Decrypt(key); + if (plaintext) { + result.emplace_back(std::make_pair(key, std::move(*plaintext))); + break; + } + } + } + + std::move(callback).Run(CtapDeviceResponseCode::kSuccess, std::move(result)); +} + base::Optional<base::span<const int32_t>> FidoDeviceAuthenticator::GetAlgorithms() { if (device_->supported_protocol() == ProtocolVersion::kU2f) { @@ -883,6 +1073,13 @@ base::BindOnce(&pin::TokenResponse::Parse, std::move(shared_key))); } +size_t FidoDeviceAuthenticator::max_large_blob_fragment_length() { + return device_->device_info()->max_msg_size + ? *device_->device_info()->max_msg_size - + kLargeBlobReadEncodingOverhead + : kLargeBlobDefaultMaxFragmentLength; +} + base::WeakPtr<FidoAuthenticator> FidoDeviceAuthenticator::GetWeakPtr() { return weak_factory_.GetWeakPtr(); }
diff --git a/device/fido/fido_device_authenticator.h b/device/fido/fido_device_authenticator.h index 8a2a26d..286640c 100644 --- a/device/fido/fido_device_authenticator.h +++ b/device/fido/fido_device_authenticator.h
@@ -17,7 +17,10 @@ #include "build/build_config.h" #include "device/fido/ctap2_device_operation.h" #include "device/fido/fido_authenticator.h" +#include "device/fido/fido_constants.h" #include "device/fido/fido_request_handler_base.h" +#include "device/fido/large_blob.h" +#include "device/fido/pin.h" namespace device { @@ -93,6 +96,14 @@ void BioEnrollDelete(const pin::TokenResponse&, std::vector<uint8_t> template_id, BioEnrollmentCallback) override; + void WriteLargeBlob( + const std::vector<uint8_t>& large_blob, + const LargeBlobKey& large_blob_key, + base::Optional<pin::TokenResponse> pin_uv_auth_token, + base::OnceCallback<void(CtapDeviceResponseCode)> callback) override; + void ReadLargeBlob(const std::vector<const LargeBlobKey>& large_blob_keys, + base::Optional<pin::TokenResponse> pin_uv_auth_token, + LargeBlobReadCallback callback) override; base::Optional<base::span<const int32_t>> GetAlgorithms() override; void Reset(ResetCallback callback) override; @@ -171,6 +182,42 @@ CtapDeviceResponseCode status, base::Optional<pin::KeyAgreementResponse> key); + void FetchLargeBlobArray( + base::Optional<pin::TokenResponse> pin_uv_auth_token, + LargeBlobArrayReader large_blob_array_reader, + base::OnceCallback<void(CtapDeviceResponseCode, + base::Optional<LargeBlobArrayReader>)> callback); + void WriteLargeBlobArray( + base::Optional<pin::TokenResponse> pin_uv_auth_token, + LargeBlobArrayWriter large_blob_array_writer, + base::OnceCallback<void(CtapDeviceResponseCode)> callback); + void OnReadLargeBlobFragment( + const size_t bytes_requested, + LargeBlobArrayReader large_blob_array_reader, + base::Optional<pin::TokenResponse> pin_uv_auth_token, + base::OnceCallback<void(CtapDeviceResponseCode, + base::Optional<LargeBlobArrayReader>)> callback, + CtapDeviceResponseCode status, + base::Optional<LargeBlobsResponse> response); + void OnWriteLargeBlobFragment( + LargeBlobArrayWriter large_blob_array_writer, + base::Optional<pin::TokenResponse> pin_uv_auth_token, + base::OnceCallback<void(CtapDeviceResponseCode)> callback, + CtapDeviceResponseCode status, + base::Optional<LargeBlobsResponse> response); + void OnHaveLargeBlobArrayForWrite( + const std::vector<uint8_t>& large_blob, + const LargeBlobKey& large_blob_key, + base::Optional<pin::TokenResponse> pin_uv_auth_token, + base::OnceCallback<void(CtapDeviceResponseCode)> callback, + CtapDeviceResponseCode status, + base::Optional<LargeBlobArrayReader> large_blob_array_reader); + void OnHaveLargeBlobArrayForRead( + const std::vector<const LargeBlobKey>& large_blob_keys, + LargeBlobReadCallback callback, + CtapDeviceResponseCode status, + base::Optional<LargeBlobArrayReader> large_blob_array_reader); + template <typename... Args> void TaskClearProxy(base::OnceCallback<void(Args...)> callback, Args... args); template <typename... Args> @@ -198,6 +245,8 @@ CtapDeviceResponseCode status, base::Optional<EnumerateCredentialsResponse> response); + size_t max_large_blob_fragment_length(); + const std::unique_ptr<FidoDevice> device_; base::Optional<AuthenticatorSupportedOptions> options_; std::unique_ptr<FidoTask> task_;
diff --git a/device/fido/fido_device_authenticator_unittest.cc b/device/fido/fido_device_authenticator_unittest.cc new file mode 100644 index 0000000..b9076a8 --- /dev/null +++ b/device/fido/fido_device_authenticator_unittest.cc
@@ -0,0 +1,140 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/fido/fido_device_authenticator.h" + +#include <memory> + +#include "base/memory/scoped_refptr.h" +#include "base/optional.h" +#include "base/test/task_environment.h" +#include "device/fido/fido_constants.h" +#include "device/fido/fido_parsing_utils.h" +#include "device/fido/large_blob.h" +#include "device/fido/test_callback_receiver.h" +#include "device/fido/virtual_ctap2_device.h" +#include "device/fido/virtual_fido_device.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace device { + +namespace { + +using WriteCallback = + device::test::ValueCallbackReceiver<CtapDeviceResponseCode>; +using ReadCallback = device::test::StatusAndValueCallbackReceiver< + CtapDeviceResponseCode, + base::Optional<std::vector<std::pair<LargeBlobKey, std::vector<uint8_t>>>>>; + +constexpr LargeBlobKey kDummyKey = {{0x01}}; +constexpr std::array<uint8_t, 4> kSmallBlob = {'l', 'u', 'm', 'a'}; +constexpr size_t kMaxStorageSize = 4096; + +class FidoDeviceAuthenticatorTest : public testing::Test { + public: + void SetUp() override { + VirtualCtap2Device::Config config; + config.pin_support = true; + config.large_blob_support = true; + config.resident_key_support = true; + config.available_large_blob_storage = kMaxStorageSize; + + authenticator_state_ = base::MakeRefCounted<VirtualFidoDevice::State>(); + auto virtual_device = + std::make_unique<VirtualCtap2Device>(authenticator_state_, config); + authenticator_ = + std::make_unique<FidoDeviceAuthenticator>(std::move(virtual_device)); + + device::test::TestCallbackReceiver<> callback; + authenticator_->InitializeAuthenticator(callback.callback()); + callback.WaitForCallback(); + } + + protected: + void SetPin() { + authenticator_state_->pin = "1234"; + authenticator_state_->pin_retries = device::kMaxPinRetries; + } + + scoped_refptr<VirtualFidoDevice::State> authenticator_state_; + std::unique_ptr<FidoDeviceAuthenticator> authenticator_; + + private: + base::test::SingleThreadTaskEnvironment task_environment_; +}; + +TEST_F(FidoDeviceAuthenticatorTest, TestReadEmptyLargeBlob) { + ReadCallback callback; + authenticator_->ReadLargeBlob({kDummyKey}, base::nullopt, + callback.callback()); + + callback.WaitForCallback(); + EXPECT_EQ(CtapDeviceResponseCode::kSuccess, callback.status()); + EXPECT_EQ(0u, callback.value()->size()); +} + +TEST_F(FidoDeviceAuthenticatorTest, TestReadInvalidLargeBlob) { + authenticator_state_->large_blob[0] += 1; + ReadCallback callback; + authenticator_->ReadLargeBlob({kDummyKey}, base::nullopt, + callback.callback()); + + callback.WaitForCallback(); + EXPECT_EQ(CtapDeviceResponseCode::kCtap2ErrIntegrityFailure, + callback.status()); + EXPECT_FALSE(callback.value()); +} + +// Test reading and writing a blob that fits in a single fragment. +TEST_F(FidoDeviceAuthenticatorTest, TestWriteSmallBlob) { + std::vector<uint8_t> small_blob = fido_parsing_utils::Materialize(kSmallBlob); + WriteCallback write_callback; + authenticator_->WriteLargeBlob(small_blob, {kDummyKey}, base::nullopt, + write_callback.callback()); + + write_callback.WaitForCallback(); + ASSERT_EQ(CtapDeviceResponseCode::kSuccess, write_callback.value()); + + ReadCallback read_callback; + authenticator_->ReadLargeBlob({kDummyKey}, base::nullopt, + read_callback.callback()); + read_callback.WaitForCallback(); + ASSERT_EQ(CtapDeviceResponseCode::kSuccess, read_callback.status()); + auto large_blob_array = read_callback.value(); + ASSERT_TRUE(large_blob_array); + ASSERT_EQ(1u, large_blob_array->size()); + EXPECT_EQ(kDummyKey, large_blob_array->at(0).first); + EXPECT_EQ(small_blob, large_blob_array->at(0).second); +} + +// Test reading and writing a blob that must fit in multiple fragments. +TEST_F(FidoDeviceAuthenticatorTest, TestWriteLargeBlob) { + std::vector<uint8_t> large_blob; + large_blob.reserve(2048); + for (size_t i = 0; i < large_blob.capacity(); ++i) { + large_blob.emplace_back(i % 0xFF); + } + + WriteCallback write_callback; + authenticator_->WriteLargeBlob(large_blob, {kDummyKey}, base::nullopt, + write_callback.callback()); + + write_callback.WaitForCallback(); + ASSERT_EQ(CtapDeviceResponseCode::kSuccess, write_callback.value()); + + ReadCallback read_callback; + authenticator_->ReadLargeBlob({kDummyKey}, base::nullopt, + read_callback.callback()); + read_callback.WaitForCallback(); + ASSERT_EQ(CtapDeviceResponseCode::kSuccess, read_callback.status()); + auto large_blob_array = read_callback.value(); + ASSERT_TRUE(large_blob_array); + ASSERT_EQ(1u, large_blob_array->size()); + EXPECT_EQ(kDummyKey, large_blob_array->at(0).first); + EXPECT_EQ(large_blob, large_blob_array->at(0).second); +} + +} // namespace + +} // namespace device
diff --git a/device/fido/large_blob.cc b/device/fido/large_blob.cc new file mode 100644 index 0000000..47aba0a6 --- /dev/null +++ b/device/fido/large_blob.cc
@@ -0,0 +1,265 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/fido/large_blob.h" +#include "base/containers/span.h" +#include "components/cbor/reader.h" +#include "components/cbor/writer.h" +#include "crypto/sha2.h" +#include "device/fido/fido_parsing_utils.h" +#include "device/fido/pin.h" + +namespace device { + +namespace { +// The number of bytes the large blob validation hash is truncated to. +constexpr size_t kTruncatedHashBytes = 16; +} // namespace + +LargeBlobArrayFragment::LargeBlobArrayFragment(const std::vector<uint8_t> bytes, + const size_t offset) + : bytes(std::move(bytes)), offset(offset) {} +LargeBlobArrayFragment::~LargeBlobArrayFragment() = default; +LargeBlobArrayFragment::LargeBlobArrayFragment(LargeBlobArrayFragment&&) = + default; + +bool VerifyLargeBlobArrayIntegrity(base::span<const uint8_t> large_blob_array) { + if (large_blob_array.size() <= kTruncatedHashBytes) { + return false; + } + const size_t trail_offset = large_blob_array.size() - kTruncatedHashBytes; + std::array<uint8_t, crypto::kSHA256Length> large_blob_hash = + crypto::SHA256Hash(large_blob_array.subspan(0, trail_offset)); + + base::span<const uint8_t> large_blob_trail = + large_blob_array.subspan(trail_offset); + return std::equal(large_blob_hash.begin(), + large_blob_hash.begin() + kTruncatedHashBytes, + large_blob_trail.begin(), large_blob_trail.end()); +} + +// static +LargeBlobsRequest LargeBlobsRequest::ForRead(size_t bytes, size_t offset) { + DCHECK_GT(bytes, 0u); + LargeBlobsRequest request; + request.get_ = bytes; + request.offset_ = offset; + return request; +} + +// static +LargeBlobsRequest LargeBlobsRequest::ForWrite(LargeBlobArrayFragment fragment, + size_t length) { + LargeBlobsRequest request; + if (fragment.offset == 0) { + request.length_ = length; + } + request.offset_ = fragment.offset; + request.set_ = std::move(fragment.bytes); + return request; +} + +LargeBlobsRequest::LargeBlobsRequest() = default; +LargeBlobsRequest::LargeBlobsRequest(LargeBlobsRequest&& other) = default; +LargeBlobsRequest::~LargeBlobsRequest() = default; + +void LargeBlobsRequest::SetPinParam( + const pin::TokenResponse& pin_uv_auth_token) { + // TODO(nsatragno): implement & test pin uv auth token. +} + +// static +base::Optional<LargeBlobsResponse> LargeBlobsResponse::ParseForRead( + const size_t bytes_to_read, + const base::Optional<cbor::Value>& cbor_response) { + if (!cbor_response || !cbor_response->is_map()) { + return base::nullopt; + } + + const cbor::Value::MapValue& map = cbor_response->GetMap(); + auto it = + map.find(cbor::Value(static_cast<int>(LargeBlobsResponseKey::kConfig))); + if (it == map.end() || !it->second.is_bytestring()) { + return base::nullopt; + } + + const std::vector<uint8_t>& config = it->second.GetBytestring(); + if (config.size() > bytes_to_read) { + return base::nullopt; + } + + return LargeBlobsResponse(std::move(config)); +} + +// static +base::Optional<LargeBlobsResponse> LargeBlobsResponse::ParseForWrite( + const base::Optional<cbor::Value>& cbor_response) { + // For writing, we expect an empty response. + if (cbor_response) { + return base::nullopt; + } + + return LargeBlobsResponse(); +} + +LargeBlobsResponse::LargeBlobsResponse( + base::Optional<std::vector<uint8_t>> config) + : config_(std::move(config)) {} +LargeBlobsResponse::LargeBlobsResponse(LargeBlobsResponse&& other) = default; +LargeBlobsResponse& LargeBlobsResponse::operator=(LargeBlobsResponse&& other) = + default; +LargeBlobsResponse::~LargeBlobsResponse() = default; + +std::pair<CtapRequestCommand, base::Optional<cbor::Value>> +AsCTAPRequestValuePair(const LargeBlobsRequest& request) { + cbor::Value::MapValue map; + if (request.get_) { + map.emplace(static_cast<int>(LargeBlobsRequestKey::kGet), *request.get_); + } + if (request.set_) { + map.emplace(static_cast<int>(LargeBlobsRequestKey::kSet), *request.set_); + } + map.emplace(static_cast<int>(LargeBlobsRequestKey::kOffset), request.offset_); + if (request.length_) { + map.emplace(static_cast<int>(LargeBlobsRequestKey::kLength), + *request.length_); + } + if (request.pin_uv_auth_param_) { + map.emplace(static_cast<int>(LargeBlobsRequestKey::kPinUvAuthParam), + *request.pin_uv_auth_param_); + } + if (request.pin_uv_auth_protocol_) { + map.emplace(static_cast<int>(LargeBlobsRequestKey::kPinUvAuthProtocol), + *request.pin_uv_auth_protocol_); + } + return std::make_pair(CtapRequestCommand::kAuthenticatorLargeBlobs, + cbor::Value(std::move(map))); +} + +// static. +base::Optional<LargeBlobData> LargeBlobData::Parse(const cbor::Value& value) { + if (!value.is_map()) { + return base::nullopt; + } + const cbor::Value::MapValue& map = value.GetMap(); + auto ciphertext_it = + map.find(cbor::Value(static_cast<int>(LargeBlobDataKeys::kCiphertext))); + if (ciphertext_it == map.end() || !ciphertext_it->second.is_bytestring()) { + return base::nullopt; + } + auto nonce_it = + map.find(cbor::Value(static_cast<int>(LargeBlobDataKeys::kNonce))); + if (nonce_it == map.end() || !nonce_it->second.is_bytestring()) { + return base::nullopt; + } + auto orig_size_it = + map.find(cbor::Value(static_cast<int>(LargeBlobDataKeys::kOrigSize))); + if (orig_size_it == map.end() || !orig_size_it->second.is_unsigned()) { + return base::nullopt; + } + return LargeBlobData(ciphertext_it->second.GetBytestring(), + nonce_it->second.GetBytestring(), + orig_size_it->second.GetUnsigned()); +} + +LargeBlobData::LargeBlobData(std::vector<uint8_t> ciphertext, + std::vector<uint8_t> nonce, + int64_t orig_size) + : ciphertext_(std::move(ciphertext)), + nonce_(std::move(nonce)), + orig_size_(std::move(orig_size)) {} +LargeBlobData::LargeBlobData(LargeBlobKey key, std::vector<uint8_t> blob) { + // TODO(nsatragno): implement encrypting the data. For now, just store and + // return the blob as plaintext. + orig_size_ = blob.size(); + ciphertext_ = blob; +} +LargeBlobData::LargeBlobData(LargeBlobData&&) = default; +LargeBlobData& LargeBlobData::operator=(LargeBlobData&&) = default; +LargeBlobData::~LargeBlobData() = default; + +bool LargeBlobData::operator==(const LargeBlobData& other) const { + return ciphertext_ == other.ciphertext_ && nonce_ == other.nonce_ && + orig_size_ == other.orig_size_; +} + +base::Optional<std::vector<uint8_t>> LargeBlobData::Decrypt( + LargeBlobKey key) const { + // TODO(nsatragno): implement decrypting the data. For now, store and return + // the blob as plaintext. + return ciphertext_; +} + +cbor::Value::MapValue LargeBlobData::AsCBOR() const { + cbor::Value::MapValue map; + map.emplace(static_cast<int>(LargeBlobDataKeys::kCiphertext), ciphertext_); + map.emplace(static_cast<int>(LargeBlobDataKeys::kNonce), nonce_); + map.emplace(static_cast<int>(LargeBlobDataKeys::kOrigSize), orig_size_); + return map; +} + +LargeBlobArrayReader::LargeBlobArrayReader() = default; +LargeBlobArrayReader::LargeBlobArrayReader(LargeBlobArrayReader&&) = default; +LargeBlobArrayReader::~LargeBlobArrayReader() = default; + +void LargeBlobArrayReader::Append(const std::vector<uint8_t>& fragment) { + bytes_.insert(bytes_.end(), fragment.begin(), fragment.end()); +} + +base::Optional<std::vector<LargeBlobData>> LargeBlobArrayReader::Materialize() { + if (!VerifyLargeBlobArrayIntegrity(bytes_)) { + return base::nullopt; + } + + base::span<const uint8_t> cbor_bytes = + base::make_span(bytes_.data(), bytes_.size() - kTruncatedHashBytes); + base::Optional<cbor::Value> cbor = cbor::Reader::Read(cbor_bytes); + if (!cbor || !cbor->is_array()) { + return base::nullopt; + } + + std::vector<LargeBlobData> large_blob_array; + const cbor::Value::ArrayValue& array = cbor->GetArray(); + for (const cbor::Value& value : array) { + base::Optional<LargeBlobData> large_blob_data = LargeBlobData::Parse(value); + if (!large_blob_data) { + continue; + } + + large_blob_array.emplace_back(std::move(*large_blob_data)); + } + + return large_blob_array; +} + +LargeBlobArrayWriter::LargeBlobArrayWriter( + const std::vector<LargeBlobData>& large_blob_array) { + cbor::Value::ArrayValue array; + for (const LargeBlobData& large_blob_data : large_blob_array) { + array.emplace_back(large_blob_data.AsCBOR()); + } + bytes_ = *cbor::Writer::Write(cbor::Value(array)); + + std::array<uint8_t, crypto::kSHA256Length> large_blob_hash = + crypto::SHA256Hash(bytes_); + bytes_.insert(bytes_.end(), large_blob_hash.begin(), + large_blob_hash.begin() + kTruncatedHashBytes); + DCHECK(VerifyLargeBlobArrayIntegrity(bytes_)); +} +LargeBlobArrayWriter::LargeBlobArrayWriter(LargeBlobArrayWriter&&) = default; +LargeBlobArrayWriter::~LargeBlobArrayWriter() = default; + +LargeBlobArrayFragment LargeBlobArrayWriter::Pop(size_t length) { + CHECK(has_remaining_fragments()); + length = std::min(length, bytes_.size() - offset_); + + LargeBlobArrayFragment fragment{ + fido_parsing_utils::Materialize( + base::make_span(bytes_.data() + offset_, length)), + offset_}; + offset_ += length; + return fragment; +} + +} // namespace device
diff --git a/device/fido/large_blob.h b/device/fido/large_blob.h new file mode 100644 index 0000000..3ed5036 --- /dev/null +++ b/device/fido/large_blob.h
@@ -0,0 +1,201 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_FIDO_LARGE_BLOB_H_ +#define DEVICE_FIDO_LARGE_BLOB_H_ + +#include <cstdint> +#include <cstdlib> +#include <vector> + +#include "base/component_export.h" +#include "device/fido/fido_constants.h" +#include "device/fido/pin.h" + +namespace device { + +// https://drafts.fidoalliance.org/fido-2/stable-links-to-latest/fido-client-to-authenticator-protocol.html#largeBlobsRW +enum class LargeBlobsRequestKey : uint8_t { + kGet = 0x01, + kSet = 0x02, + kOffset = 0x03, + kLength = 0x04, + kPinUvAuthParam = 0x05, + kPinUvAuthProtocol = 0x06, +}; + +// https://drafts.fidoalliance.org/fido-2/stable-links-to-latest/fido-client-to-authenticator-protocol.html#largeBlobsRW +enum class LargeBlobsResponseKey : uint8_t { + kConfig = 0x01, +}; + +// https://drafts.fidoalliance.org/fido-2/stable-links-to-latest/fido-client-to-authenticator-protocol.html#large-blob +enum class LargeBlobDataKeys : uint8_t { + kCiphertext = 0x01, + kNonce = 0x02, + kOrigSize = 0x03, +}; + +enum class LargeBlobOperation { + kNone, + kRead, + kWrite, +}; + +using LargeBlobKey = std::array<uint8_t, kLargeBlobKeyLength>; + +constexpr size_t kLargeBlobDefaultMaxFragmentLength = 960; +constexpr size_t kLargeBlobReadEncodingOverhead = 64; + +struct COMPONENT_EXPORT(DEVICE_FIDO) LargeBlobArrayFragment { + LargeBlobArrayFragment(std::vector<uint8_t> bytes, size_t offset); + ~LargeBlobArrayFragment(); + LargeBlobArrayFragment(const LargeBlobArrayFragment&) = delete; + LargeBlobArrayFragment operator=(const LargeBlobArrayFragment&) = delete; + LargeBlobArrayFragment(LargeBlobArrayFragment&&); + const std::vector<uint8_t> bytes; + const size_t offset; +}; + +COMPONENT_EXPORT(DEVICE_FIDO) +bool VerifyLargeBlobArrayIntegrity(base::span<const uint8_t> large_blob_array); + +class LargeBlobsRequest { + public: + ~LargeBlobsRequest(); + LargeBlobsRequest(const LargeBlobsRequest&) = delete; + LargeBlobsRequest operator=(const LargeBlobsRequest&) = delete; + LargeBlobsRequest(LargeBlobsRequest&& other); + + static LargeBlobsRequest ForRead(size_t bytes, size_t offset); + static LargeBlobsRequest ForWrite(LargeBlobArrayFragment fragment, + size_t length); + + void SetPinParam(const pin::TokenResponse& pin_uv_auth_token); + + friend std::pair<CtapRequestCommand, base::Optional<cbor::Value>> + AsCTAPRequestValuePair(const LargeBlobsRequest& request); + + private: + LargeBlobsRequest(); + + base::Optional<int64_t> get_; + base::Optional<std::vector<uint8_t>> set_; + int64_t offset_ = 0; + base::Optional<int64_t> length_; + base::Optional<std::vector<uint8_t>> pin_uv_auth_param_; + base::Optional<int64_t> pin_uv_auth_protocol_; +}; + +class LargeBlobsResponse { + public: + LargeBlobsResponse(const LargeBlobsResponse&) = delete; + LargeBlobsResponse operator=(const LargeBlobsResponse&) = delete; + LargeBlobsResponse(LargeBlobsResponse&& other); + LargeBlobsResponse& operator=(LargeBlobsResponse&&); + ~LargeBlobsResponse(); + + static base::Optional<LargeBlobsResponse> ParseForRead( + size_t bytes_to_read, + const base::Optional<cbor::Value>& cbor_response); + static base::Optional<LargeBlobsResponse> ParseForWrite( + const base::Optional<cbor::Value>& cbor_response); + + base::Optional<std::vector<uint8_t>> config() { return config_; } + + private: + explicit LargeBlobsResponse( + base::Optional<std::vector<uint8_t>> config = base::nullopt); + + base::Optional<std::vector<uint8_t>> config_; +}; + +// Represents the large-blob map structure +// https://drafts.fidoalliance.org/fido-2/stable-links-to-latest/fido-client-to-authenticator-protocol.html#large-blob +class COMPONENT_EXPORT(DEVICE_FIDO) LargeBlobData { + public: + static base::Optional<LargeBlobData> Parse(const cbor::Value& cbor_response); + + LargeBlobData(LargeBlobKey key, std::vector<uint8_t> blob); + LargeBlobData(const LargeBlobData&) = delete; + LargeBlobData operator=(const LargeBlobData&) = delete; + LargeBlobData(LargeBlobData&&); + LargeBlobData& operator=(LargeBlobData&&); + ~LargeBlobData(); + bool operator==(const LargeBlobData&) const; + + base::Optional<std::vector<uint8_t>> Decrypt(LargeBlobKey key) const; + cbor::Value::MapValue AsCBOR() const; + + private: + LargeBlobData(std::vector<uint8_t> ciphertext, + std::vector<uint8_t> nonce, + int64_t orig_size); + std::vector<uint8_t> ciphertext_; + std::vector<uint8_t> nonce_; + int64_t orig_size_; +}; + +// Reading large blob arrays is done in chunks. This class provides facilities +// to assemble together those chunks. +class COMPONENT_EXPORT(DEVICE_FIDO) LargeBlobArrayReader { + public: + LargeBlobArrayReader(); + LargeBlobArrayReader(const LargeBlobArrayReader&) = delete; + LargeBlobArrayReader operator=(const LargeBlobArrayReader&) = delete; + LargeBlobArrayReader(LargeBlobArrayReader&&); + ~LargeBlobArrayReader(); + + // Appends a fragment to the large blob array. + void Append(const std::vector<uint8_t>& fragment); + + // Verifies the integrity of the large blob array. This should be called after + // all fragments have been |Append|ed. + // If successful, parses and returns the array. + base::Optional<std::vector<LargeBlobData>> Materialize(); + + // Returns the current size of the array fragments. + size_t size() const { return bytes_.size(); } + + private: + std::vector<uint8_t> bytes_; +}; + +// Writing large blob arrays is done in chunks. This class provides facilities +// to divide a blob into chunks. +class COMPONENT_EXPORT(DEVICE_FIDO) LargeBlobArrayWriter { + public: + explicit LargeBlobArrayWriter( + const std::vector<LargeBlobData>& large_blob_array); + LargeBlobArrayWriter(const LargeBlobArrayWriter&) = delete; + LargeBlobArrayWriter operator=(const LargeBlobArrayWriter&) = delete; + LargeBlobArrayWriter(LargeBlobArrayWriter&&); + ~LargeBlobArrayWriter(); + + // Extracts a fragment with |length|. Can only be called if + // has_remaining_fragments() is true. + LargeBlobArrayFragment Pop(size_t length); + + // Returns the current size of the array fragments. + size_t size() const { return bytes_.size(); } + + // Returns true if there are remaining fragments to be written, false + // otherwise. + bool has_remaining_fragments() const { return offset_ < size(); } + + void set_bytes_for_testing(std::vector<uint8_t> bytes) { + bytes_ = std::move(bytes); + } + + private: + std::vector<uint8_t> bytes_; + size_t offset_ = 0; +}; + +std::pair<CtapRequestCommand, base::Optional<cbor::Value>> +AsCTAPRequestValuePair(const LargeBlobsRequest& request); + +} // namespace device + +#endif // DEVICE_FIDO_LARGE_BLOB_H_
diff --git a/device/fido/large_blob_unittest.cc b/device/fido/large_blob_unittest.cc new file mode 100644 index 0000000..408f5fe2 --- /dev/null +++ b/device/fido/large_blob_unittest.cc
@@ -0,0 +1,143 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/fido/large_blob.h" + +#include "base/optional.h" +#include "device/fido/fido_parsing_utils.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace device { + +namespace { + +class FidoLargeBlobTest : public testing::Test {}; + +// An empty CBOR array (0x80) followed by LEFT(SHA-256(h'80'), 16). +const std::array<uint8_t, 17> kValidEmptyLargeBlobArray = { + 0x80, 0x76, 0xbe, 0x8b, 0x52, 0x8d, 0x00, 0x75, 0xf7, + 0xaa, 0xe9, 0x8d, 0x6f, 0xa5, 0x7a, 0x6d, 0x3c}; + +// Something that is not an empty CBOR array (0x10) followed by +// LEFT(SHA-256(h'10'), 16). +const std::array<uint8_t, 17> kInvalidLargeBlobArray = { + 0x10, 0xc5, 0x55, 0xea, 0xb4, 0x5d, 0x08, 0x84, 0x5a, + 0xe9, 0xf1, 0x0d, 0x45, 0x2a, 0x99, 0xbf, 0xcb}; + +// An "valid" CBOR large blob array with two entries. The first entry is not a +// valid large blob map structure. The second entry is valid. +const std::array<uint8_t, 35> kValidLargeBlobArray = { + 0x82, 0xA2, 0x02, 0x42, 0x11, 0x11, 0x03, 0x02, 0xA3, 0x01, 0x42, 0x22, + 0x22, 0x02, 0x42, 0x33, 0x33, 0x03, 0x02, 0x53, 0x5b, 0xaa, 0xd2, 0x7a, + 0x26, 0x68, 0x34, 0x9e, 0xc3, 0x90, 0xd3, 0x9a, 0x1c, 0x0a, 0xae}; + +TEST_F(FidoLargeBlobTest, VerifyLargeBlobArrayIntegrityValid) { + std::vector<uint8_t> large_blob_array = + fido_parsing_utils::Materialize(kValidEmptyLargeBlobArray); + EXPECT_TRUE(VerifyLargeBlobArrayIntegrity(large_blob_array)); +} + +TEST_F(FidoLargeBlobTest, VerifyLargeBlobArrayIntegrityInvalid) { + std::vector<uint8_t> large_blob_array = + fido_parsing_utils::Materialize(kValidEmptyLargeBlobArray); + large_blob_array[0] += 1; + EXPECT_FALSE(VerifyLargeBlobArrayIntegrity(large_blob_array)); + + large_blob_array = fido_parsing_utils::Materialize(kValidEmptyLargeBlobArray); + large_blob_array.erase(large_blob_array.begin()); + EXPECT_FALSE(VerifyLargeBlobArrayIntegrity(large_blob_array)); +} + +TEST_F(FidoLargeBlobTest, LargeBlobArrayReader_MaterializeEmpty) { + LargeBlobArrayReader large_blob_array_reader; + large_blob_array_reader.Append( + fido_parsing_utils::Materialize(kValidEmptyLargeBlobArray)); + EXPECT_EQ(0u, large_blob_array_reader.Materialize()->size()); +} + +TEST_F(FidoLargeBlobTest, LargeBlobArrayReader_MaterializeInvalidCbor) { + LargeBlobArrayReader large_blob_array_reader; + large_blob_array_reader.Append( + fido_parsing_utils::Materialize(kInvalidLargeBlobArray)); + EXPECT_FALSE(large_blob_array_reader.Materialize()); +} + +TEST_F(FidoLargeBlobTest, LargeBlobArrayReader_MaterializeInvalidHash) { + std::vector<uint8_t> large_blob_array = + fido_parsing_utils::Materialize(kValidEmptyLargeBlobArray); + large_blob_array[0] += 1; + LargeBlobArrayReader large_blob_array_reader; + large_blob_array_reader.Append( + fido_parsing_utils::Materialize(large_blob_array)); + EXPECT_FALSE(large_blob_array_reader.Materialize()); +} + +TEST_F(FidoLargeBlobTest, LargeBlobArrayReader_MaterializeValid) { + LargeBlobArrayReader large_blob_array_reader; + large_blob_array_reader.Append( + fido_parsing_utils::Materialize(kValidLargeBlobArray)); + std::vector<LargeBlobData> vector = *large_blob_array_reader.Materialize(); + EXPECT_EQ(1u, vector.size()); +} + +// Test popping the large blob array in a fragment size that does not evenly +// divide the length of the array. +TEST_F(FidoLargeBlobTest, LargeBlobArrayWriter_PopUnevenly) { + const size_t fragment_size = 8; + const size_t expected_fragments = + kValidLargeBlobArray.size() / fragment_size + 1; + size_t fragments = 0; + ASSERT_NE(0u, kValidLargeBlobArray.size() % fragment_size); + + LargeBlobArrayWriter large_blob_array_writer({}); + std::vector<uint8_t> large_blob_array = + fido_parsing_utils::Materialize(kValidLargeBlobArray); + large_blob_array_writer.set_bytes_for_testing(large_blob_array); + std::vector<uint8_t> reconstructed; + EXPECT_TRUE(large_blob_array_writer.has_remaining_fragments()); + while (large_blob_array_writer.has_remaining_fragments()) { + LargeBlobArrayFragment fragment = + large_blob_array_writer.Pop(fragment_size); + ++fragments; + reconstructed.insert(reconstructed.end(), fragment.bytes.begin(), + fragment.bytes.end()); + EXPECT_EQ(fragments != expected_fragments, + large_blob_array_writer.has_remaining_fragments()); + } + + EXPECT_EQ(expected_fragments, fragments); + EXPECT_EQ(large_blob_array, reconstructed); +} + +// Test popping the large blob array in a fragment size that evenly divides the +// length of the array. +TEST_F(FidoLargeBlobTest, LargeBlobArrayFragments_PopEvenly) { + const size_t fragment_size = 7; + const size_t expected_fragments = kValidLargeBlobArray.size() / fragment_size; + size_t fragments = 0; + ASSERT_EQ(0u, kValidLargeBlobArray.size() % fragment_size); + + LargeBlobArrayWriter large_blob_array_writer({}); + std::vector<uint8_t> large_blob_array = + fido_parsing_utils::Materialize(kValidLargeBlobArray); + large_blob_array_writer.set_bytes_for_testing(large_blob_array); + std::vector<uint8_t> reconstructed; + EXPECT_TRUE(large_blob_array_writer.has_remaining_fragments()); + while (large_blob_array_writer.has_remaining_fragments()) { + LargeBlobArrayFragment fragment = + large_blob_array_writer.Pop(fragment_size); + ++fragments; + reconstructed.insert(reconstructed.end(), fragment.bytes.begin(), + fragment.bytes.end()); + EXPECT_EQ(fragments != expected_fragments, + large_blob_array_writer.has_remaining_fragments()); + } + + EXPECT_EQ(expected_fragments, fragments); + EXPECT_EQ(large_blob_array, reconstructed); +} + +} // namespace + +} // namespace device
diff --git a/device/fido/pin.h b/device/fido/pin.h index ef91cb7..42b2ed6 100644 --- a/device/fido/pin.h +++ b/device/fido/pin.h
@@ -31,7 +31,7 @@ kGetAssertion = 0x02, kCredentialManagement = 0x04, kBioEnrollment = 0x08, - kPlatformConfiguration = 0x10, + kLargeBlobWrite = 0x10, }; // kProtocolVersion is the version of the PIN protocol that this code @@ -246,7 +246,7 @@ // decrypt a response, the shared key from the request is needed. Once a pin- // token has been decrypted, it can be used to calculate the pinAuth parameters // needed to show user-verification in future operations. -class TokenResponse { +class COMPONENT_EXPORT(DEVICE_FIDO) TokenResponse { public: ~TokenResponse(); TokenResponse(const TokenResponse&);
diff --git a/device/fido/virtual_ctap2_device.cc b/device/fido/virtual_ctap2_device.cc index c32beb47..fb4c5b4b 100644 --- a/device/fido/virtual_ctap2_device.cc +++ b/device/fido/virtual_ctap2_device.cc
@@ -24,12 +24,14 @@ #include "crypto/ec_private_key.h" #include "device/fido/authenticator_get_assertion_response.h" #include "device/fido/authenticator_make_credential_response.h" +#include "device/fido/authenticator_supported_options.h" #include "device/fido/bio/enrollment.h" #include "device/fido/credential_management.h" #include "device/fido/ctap_get_assertion_request.h" #include "device/fido/ctap_make_credential_request.h" #include "device/fido/fido_constants.h" #include "device/fido/fido_parsing_utils.h" +#include "device/fido/large_blob.h" #include "device/fido/opaque_attestation_statement.h" #include "device/fido/p256_public_key.h" #include "device/fido/pin.h" @@ -55,12 +57,24 @@ {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}}; +// Some commands that validate PinUvAuthTokens include this padding to ensure a +// PinUvAuthParam cannot be reused across different commands. +constexpr std::array<uint8_t, 32> kPinUvAuthTokenSafetyPadding = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + constexpr uint8_t kSupportedPermissionsMask = static_cast<uint8_t>(pin::Permissions::kMakeCredential) | static_cast<uint8_t>(pin::Permissions::kGetAssertion) | static_cast<uint8_t>(pin::Permissions::kCredentialManagement) | static_cast<uint8_t>(pin::Permissions::kBioEnrollment); +constexpr std::array<uint8_t, 4> Uint32LittleEndian(int64_t value) { + return {value & 0xFF, value >> 8 & 0xFF, value >> 16 & 0xFF, + value >> 24 & 0xFF}; +} + struct PinUvAuthTokenPermissions { uint8_t permissions; base::Optional<std::string> rp_id; @@ -664,6 +678,9 @@ case CtapRequestCommand::kAuthenticatorBioEnrollmentPreview: response_code = OnBioEnrollment(request_bytes, &response_data); break; + case CtapRequestCommand::kAuthenticatorLargeBlobs: + response_code = OnLargeBlobs(request_bytes, &response_data); + break; default: break; } @@ -1391,7 +1408,7 @@ if (request.large_blob_key) { if (!config_.large_blob_support) { - return CtapDeviceResponseCode::kCtap2ErrExtensionNotSupported; + return CtapDeviceResponseCode::kCtap2ErrUnsupportedExtension; } if (registration.second->large_blob_key) { assertion.set_large_blob_key(*registration.second->large_blob_key); @@ -2162,6 +2179,160 @@ return CtapDeviceResponseCode::kSuccess; } +CtapDeviceResponseCode VirtualCtap2Device::OnLargeBlobs( + base::span<const uint8_t> request_bytes, + std::vector<uint8_t>* response) { + if (!config_.large_blob_support) { + DLOG(ERROR) << "Large blob not supported"; + return CtapDeviceResponseCode::kCtap2ErrUnsupportedExtension; + } + + // Read request bytes into |cbor::Value::MapValue|. + const auto& cbor_request = cbor::Reader::Read(request_bytes); + if (!cbor_request || !cbor_request->is_map()) { + return CtapDeviceResponseCode::kCtap2ErrCBORUnexpectedType; + } + const auto& request_map = cbor_request->GetMap(); + + const auto offset_it = request_map.find( + cbor::Value(static_cast<uint8_t>(LargeBlobsRequestKey::kOffset))); + if (offset_it == request_map.end() || !offset_it->second.is_unsigned()) { + return CtapDeviceResponseCode::kCtap1ErrInvalidParameter; + } + const size_t offset = offset_it->second.GetUnsigned(); + + const auto get_it = request_map.find( + cbor::Value(static_cast<uint8_t>(LargeBlobsRequestKey::kGet))); + const auto set_it = request_map.find( + cbor::Value(static_cast<uint8_t>(LargeBlobsRequestKey::kSet))); + if ((get_it == request_map.end() && set_it == request_map.end()) || + (get_it != request_map.end() && set_it != request_map.end())) { + return CtapDeviceResponseCode::kCtap1ErrInvalidParameter; + } + if ((get_it != request_map.end() && !get_it->second.is_unsigned()) || + (set_it != request_map.end() && !set_it->second.is_bytestring())) { + return CtapDeviceResponseCode::kCtap1ErrInvalidParameter; + } + const auto length_it = request_map.find( + cbor::Value(static_cast<uint8_t>(LargeBlobsRequestKey::kLength))); + const size_t max_fragment_length = kLargeBlobDefaultMaxFragmentLength; + + if (get_it != request_map.end()) { + if (length_it != request_map.end()) { + return CtapDeviceResponseCode::kCtap1ErrInvalidParameter; + } + const size_t get = get_it->second.GetUnsigned(); + if (get > max_fragment_length) { + return CtapDeviceResponseCode::kCtap1ErrInvalidLength; + } + if (offset > mutable_state()->large_blob.size()) { + return CtapDeviceResponseCode::kCtap1ErrInvalidParameter; + } + cbor::Value::MapValue response_map; + response_map.emplace( + static_cast<uint8_t>(LargeBlobsResponseKey::kConfig), + base::make_span( + mutable_state()->large_blob.data() + offset, + std::min(get, mutable_state()->large_blob.size() - offset))); + *response = + cbor::Writer::Write(cbor::Value(std::move(response_map))).value(); + } else { + DCHECK(set_it != request_map.end()); + const std::vector<uint8_t>& set = set_it->second.GetBytestring(); + if (set.size() > max_fragment_length) { + return CtapDeviceResponseCode::kCtap1ErrInvalidLength; + } + if (offset == 0) { + if (length_it == request_map.end() || !length_it->second.is_unsigned()) { + return CtapDeviceResponseCode::kCtap1ErrInvalidParameter; + } + const size_t length = length_it->second.GetUnsigned(); + if (length > config_.available_large_blob_storage) { + return CtapDeviceResponseCode::kCtap2ErrLargeBlobStorageFull; + } + constexpr size_t kMinBlobLength = 17; + if (length < kMinBlobLength) { + return CtapDeviceResponseCode::kCtap1ErrInvalidParameter; + } + mutable_state()->large_blob_expected_length = length; + mutable_state()->large_blob_expected_next_offset = 0; + } else { + if (length_it != request_map.end()) { + return CtapDeviceResponseCode::kCtap1ErrInvalidParameter; + } + } + + if (offset != mutable_state()->large_blob_expected_next_offset) { + return CtapDeviceResponseCode::kCtap1ErrInvalidSeq; + } + + if (device_info_->options.client_pin_availability == + AuthenticatorSupportedOptions::ClientPinAvailability:: + kSupportedAndPinSet || + device_info_->options.user_verification_availability == + AuthenticatorSupportedOptions::UserVerificationAvailability:: + kSupportedAndConfigured) { + // If the device is protected by some sort of user verification: + const auto pin_uv_auth_param_it = request_map.find(cbor::Value( + static_cast<uint8_t>(LargeBlobsRequestKey::kPinUvAuthParam))); + const auto pin_uv_auth_protocol_it = request_map.find(cbor::Value( + static_cast<uint8_t>(LargeBlobsRequestKey::kPinUvAuthProtocol))); + if (pin_uv_auth_param_it == request_map.end() || + !pin_uv_auth_param_it->second.is_bytestring() || + pin_uv_auth_protocol_it == request_map.end() || + !pin_uv_auth_protocol_it->second.is_unsigned()) { + return CtapDeviceResponseCode::kCtap2ErrOperationDenied; + } + if (pin_uv_auth_protocol_it->second.GetUnsigned() != + pin::kProtocolVersion) { + return CtapDeviceResponseCode::kCtap2ErrPinAuthInvalid; + } + if (!(mutable_state()->pin_uv_token_permissions & + static_cast<uint8_t>(pin::Permissions::kLargeBlobWrite))) { + return CtapDeviceResponseCode::kCtap2ErrPinAuthInvalid; + } + + // verify(pinUvAuthToken, + // 32×0xff || h’0c00' || uint32LittleEndian(offset) || + // contents of set byte string, i.e. not including an outer CBOR + // tag with major type two, + // pinUvAuthParam) + std::vector<uint8_t> pinauth_bytes; + pinauth_bytes.insert(pinauth_bytes.begin(), + kPinUvAuthTokenSafetyPadding.begin(), + kPinUvAuthTokenSafetyPadding.end()); + pinauth_bytes.insert(pinauth_bytes.end(), {0x0c, 0x00}); + auto offset_vec = Uint32LittleEndian(offset); + pinauth_bytes.insert(pinauth_bytes.end(), offset_vec.begin(), + offset_vec.end()); + pinauth_bytes.insert(pinauth_bytes.end(), set.begin(), set.end()); + if (!CheckPINToken(mutable_state()->pin_token, + pin_uv_auth_param_it->second.GetBytestring(), + pinauth_bytes)) { + return CtapDeviceResponseCode::kCtap2ErrPinAuthInvalid; + } + } + if (offset + set.size() > mutable_state()->large_blob_expected_length) { + return CtapDeviceResponseCode::kCtap1ErrInvalidParameter; + } + if (offset == 0) { + mutable_state()->large_blob_buffer.clear(); + } + mutable_state()->large_blob_buffer.insert( + mutable_state()->large_blob_buffer.end(), set.begin(), set.end()); + mutable_state()->large_blob_expected_next_offset = + mutable_state()->large_blob_buffer.size(); + if (mutable_state()->large_blob_buffer.size() == + mutable_state()->large_blob_expected_length) { + if (!VerifyLargeBlobArrayIntegrity(mutable_state()->large_blob_buffer)) { + return CtapDeviceResponseCode::kCtap2ErrIntegrityFailure; + } + mutable_state()->large_blob = mutable_state()->large_blob_buffer; + } + } + return CtapDeviceResponseCode::kSuccess; +} + void VirtualCtap2Device::InitPendingRPs() { mutable_state()->pending_rps.clear(); std::set<std::string> rp_ids;
diff --git a/device/fido/virtual_ctap2_device.h b/device/fido/virtual_ctap2_device.h index 3db8f2a..19f148d 100644 --- a/device/fido/virtual_ctap2_device.h +++ b/device/fido/virtual_ctap2_device.h
@@ -69,6 +69,11 @@ bool cred_protect_support = false; bool hmac_secret_support = false; bool large_blob_support = false; + // The space available to store a large blob. In real authenticators this + // may change depending on the number of resident credentials. We treat this + // as a fixed size area for the large blob. + size_t available_large_blob_storage = 1024; + IncludeCredential include_credential_in_assertion_response = IncludeCredential::ONLY_IF_NEEDED; @@ -218,6 +223,8 @@ std::vector<uint8_t>* response); CtapDeviceResponseCode OnBioEnrollment(base::span<const uint8_t> request, std::vector<uint8_t>* response); + CtapDeviceResponseCode OnLargeBlobs(base::span<const uint8_t> request, + std::vector<uint8_t>* response); CtapDeviceResponseCode OnAuthenticatorGetInfo( std::vector<uint8_t>* response) const;
diff --git a/device/fido/virtual_fido_device.h b/device/fido/virtual_fido_device.h index 5e80237..d3e8e95 100644 --- a/device/fido/virtual_fido_device.h +++ b/device/fido/virtual_fido_device.h
@@ -226,6 +226,17 @@ // expected sequence of requests was sent. std::vector<size_t> allow_list_sizes; + // The large-blob array. This is initialized to an empty CBOR array (0x80) + // followed by LEFT(SHA-256(h'80'), 16). + std::vector<uint8_t> large_blob = {0x80, 0x76, 0xbe, 0x8b, 0x52, 0x8d, + 0x00, 0x75, 0xf7, 0xaa, 0xe9, 0x8d, + 0x6f, 0xa5, 0x7a, 0x6d, 0x3c}; + // Buffer that gets progressively filled with large blob fragments until + // committed. + std::vector<uint8_t> large_blob_buffer; + uint64_t large_blob_expected_next_offset = 0; + uint64_t large_blob_expected_length = 0; + FidoTransportProtocol transport = FidoTransportProtocol::kUsbHumanInterfaceDevice;
diff --git a/docs/mac/triage.md b/docs/mac/triage.md index 3408e12..20690c3 100644 --- a/docs/mac/triage.md +++ b/docs/mac/triage.md
@@ -146,7 +146,7 @@ * Admin * Blink * Infra -* Internals>Headless, Network, Plugins, Printing, Skia, Views +* Internals>Cast, Headless, Network, Plugins, Printing, Skia, Views * IO>Bluetooth, USB * Platform * Services>Chromoting @@ -156,6 +156,6 @@ [unconfirmed]: https://bugs.chromium.org/p/chromium/issues/list?q=OS%3DMac%20status%3AUnconfirmed%20-component%3ABlink%2CEnterprise%2CInternals%3ENetwork%2CPlatform%3EDevtools%2CServices%3ESyncs%2CUI%3EBrowser%3EPasswords&can=2 [untriaged-m]: https://bugs.chromium.org/p/chromium/issues/list?q=has%3AMac%20status%3AUntriaged&can=2 -[untriaged-c]: https://bugs.chromium.org/p/chromium/issues/list?q=OS%3DMac%20-OS%3DWindows%2CLinux%2CChrome%2CAndroid%2CiOS%20status%3AUntriaged%20-component%3AAdmin%2CBlink%2CInfra%2CInternals%3EHeadless%2CInternals%3ENetwork%2CInternals%3EPlugins%3EPDF%2CInternals%3EPrinting%2CInternals%3ESkia%2CInternals%3EUpdater%2CInternals%3EViews%2CIO%3EBluetooth%2CIO%3EUSB%2CPlatform%2CServices%3EChromoting%2CTest%3ETelemetry%2CUI%3EBrowser%3EWebAppInstalls%2CPlatform%3EWebAppProvider%2CUI%3EBrowser%3EWebUI&can=2 +[untriaged-c]: https://bugs.chromium.org/p/chromium/issues/list?q=OS%3DMac%20-OS%3DWindows%2CLinux%2CChrome%2CAndroid%2CiOS%20status%3AUntriaged%20-component%3AAdmin%2CBlink%2CInfra%2CInternals%3ECast%2CInternals%3EHeadless%2CInternals%3ENetwork%2CInternals%3EPlugins%3EPDF%2CInternals%3EPrinting%2CInternals%3ESkia%2CInternals%3EUpdater%2CInternals%3EViews%2CIO%3EBluetooth%2CIO%3EUSB%2CPlatform%2CServices%3EChromoting%2CTest%3ETelemetry%2CUI%3EBrowser%3EWebAppInstalls%2CPlatform%3EWebAppProvider%2CUI%3EBrowser%3EWebUI&can=2 [available]: https://bugs.chromium.org/p/chromium/issues/list?q=has%3AMac%20status%3AAvailable&can=2 [assigned]: https://bugs.chromium.org/p/chromium/issues/list?q=has%3AMac%20status%3AAssigned&can=2
diff --git a/docs/tab_helpers.md b/docs/tab_helpers.md index 3a63a25b8..9f0ca4f 100644 --- a/docs/tab_helpers.md +++ b/docs/tab_helpers.md
@@ -50,6 +50,8 @@ : public content::WebContentsObserver, public content::WebContentsUserData<TitleLoggerTabHelper> { public: + TitleLoggerTabHelper(const TitleLoggerTabHelper&) = delete; + TitleLoggerTabHelper& operator=(const TitleLoggerTabHelper&) = delete; ~TitleLoggerTabHelper() override; // content::WebContentsObserver @@ -60,8 +62,6 @@ private: explicit TitleLoggerTabHelper(content::WebContents* web_contents); friend class content::WebContentsUserData<TitleLoggerTabHelper>; - - DISALLOW_COPY_AND_ASSIGN(TitleLoggerTabHelper); }; ```
diff --git a/docs/webui_in_components.md b/docs/webui_in_components.md index 006f3f7..67b0154 100644 --- a/docs/webui_in_components.md +++ b/docs/webui_in_components.md
@@ -142,9 +142,10 @@ class HelloWorldUI : public content::WebUIController { public: explicit HelloWorldUI(content::WebUI* web_ui); + HelloWorldUI(const HelloWorldUI&) = delete; + HelloWorldUI& operator=(const HelloWorldUI&) = delete; ~HelloWorldUI() override; private: - DISALLOW_COPY_AND_ASSIGN(HelloWorldUI); }; #endif // COMPONENTS_HELLO_WORLD_HELLO_WORLD_UI_H_ @@ -257,8 +258,6 @@ + private: + // Add two numbers together using integer arithmetic. + void AddNumbers(const base::ListValue* args); - - DISALLOW_COPY_AND_ASSIGN(HelloWorldUI); }; ```
diff --git a/extensions/browser/BUILD.gn b/extensions/browser/BUILD.gn index ad55e02d..b4aae04fb 100644 --- a/extensions/browser/BUILD.gn +++ b/extensions/browser/BUILD.gn
@@ -535,6 +535,7 @@ "//chromeos/dbus/upstart", "//chromeos/login/login_state", "//chromeos/network", + "//components/crash/content/browser/error_reporting:mock_crash_endpoint", ] } } @@ -580,8 +581,6 @@ if (is_chromeos) { sources += [ - "api/crash_report_private/mock_crash_endpoint.cc", - "api/crash_report_private/mock_crash_endpoint.h", "api/feedback_private/mock_feedback_service.cc", "api/feedback_private/mock_feedback_service.h", ]
diff --git a/extensions/browser/api/crash_report_private/BUILD.gn b/extensions/browser/api/crash_report_private/BUILD.gn index 7d9b411..bf2b0f8 100644 --- a/extensions/browser/api/crash_report_private/BUILD.gn +++ b/extensions/browser/api/crash_report_private/BUILD.gn
@@ -14,12 +14,8 @@ ] deps = [ - "//components/crash/core/app", - "//components/feedback", + "//components/crash/content/browser/error_reporting", "//content/public/browser", "//extensions/common/api", - "//net", - "//services/network:network_service", - "//services/network/public/cpp", ] }
diff --git a/extensions/browser/api/crash_report_private/DEPS b/extensions/browser/api/crash_report_private/DEPS index d2cde66..c0cd4158 100644 --- a/extensions/browser/api/crash_report_private/DEPS +++ b/extensions/browser/api/crash_report_private/DEPS
@@ -1,10 +1,4 @@ include_rules = [ - "+components/crash/core/app/client_upload_info.h", - "+components/feedback/redaction_tool.h", + "+components/crash/content/browser/error_reporting", ] -specific_include_rules = { - "mock_crash_endpoint.cc": [ - "+components/crash/core/app/crash_reporter_client.h", - ], -}
diff --git a/extensions/browser/api/crash_report_private/crash_report_private_api.cc b/extensions/browser/api/crash_report_private/crash_report_private_api.cc index a9658eb..362c825 100644 --- a/extensions/browser/api/crash_report_private/crash_report_private_api.cc +++ b/extensions/browser/api/crash_report_private/crash_report_private_api.cc
@@ -4,21 +4,9 @@ #include "extensions/browser/api/crash_report_private/crash_report_private_api.h" -#include "base/no_destructor.h" -#include "base/strings/strcat.h" -#include "base/strings/stringprintf.h" -#include "base/system/sys_info.h" -#include "base/task/task_traits.h" -#include "base/task/thread_pool.h" #include "base/time/default_clock.h" -#include "components/crash/core/app/client_upload_info.h" -#include "components/feedback/redaction_tool.h" -#include "content/public/browser/browser_context.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/storage_partition.h" -#include "net/base/escape.h" -#include "services/network/public/cpp/resource_request.h" -#include "services/network/public/cpp/simple_url_loader.h" +#include "components/crash/content/browser/error_reporting/javascript_error_report.h" +#include "components/crash/content/browser/error_reporting/send_javascript_error_report.h" namespace extensions { namespace api { @@ -30,171 +18,6 @@ base::Clock* g_clock = base::DefaultClock::GetInstance(); -#if defined(GOOGLE_CHROME_BUILD) -constexpr char kCrashEndpointUrl[] = "https://clients2.google.com/cr/report"; -#else -constexpr char kCrashEndpointUrl[] = ""; -#endif - -std::string& GetCrashEndpoint() { - static base::NoDestructor<std::string> crash_endpoint(kCrashEndpointUrl); - return *crash_endpoint; -} - -constexpr int kCrashEndpointResponseMaxSizeInBytes = 1024; - -void OnRequestComplete(std::unique_ptr<network::SimpleURLLoader> url_loader, - base::OnceCallback<void()> callback, - std::unique_ptr<std::string> response_body) { - if (response_body) { - DVLOG(1) << "Uploaded crash report. ID: " << *response_body; - } else { - LOG(ERROR) << "Failed to upload crash report"; - } - std::move(callback).Run(); -} - -// Sometimes, the stack trace will contain an error message as the first line, -// which confuses the Crash server. This function deletes it if it is present. -std::string RemoveErrorMessageFromStackTrace(const std::string& stack_trace, - const std::string& error_message) { - // Return the original stack trace if the error message is not present. - const auto error_message_index = stack_trace.find(error_message); - if (error_message_index == std::string::npos) - return stack_trace; - - // If the stack trace only contains one line, then delete the whole trace. - const auto first_line_end_index = stack_trace.find('\n'); - if (first_line_end_index == std::string::npos) - return std::string(); - - // Otherwise, delete the first line. - return stack_trace.substr(first_line_end_index + 1); -} - -using ParameterMap = std::map<std::string, std::string>; - -std::string BuildPostRequestQueryString(const ParameterMap& params) { - std::vector<std::string> query_parts; - for (const auto& kv : params) { - query_parts.push_back(base::StrCat( - {kv.first, "=", - net::EscapeQueryParamValue(kv.second, /* use_plus */ false)})); - } - return base::JoinString(query_parts, "&"); -} - -struct PlatformInfo { - std::string product_name; - std::string version; - std::string channel; - std::string platform; - std::string os_version; -}; - -PlatformInfo GetPlatformInfo() { - PlatformInfo info; - crash_reporter::GetClientProductNameAndVersion(&info.product_name, - &info.version, &info.channel); - - int32_t os_major_version = 0; - int32_t os_minor_version = 0; - int32_t os_bugfix_version = 0; - base::SysInfo::OperatingSystemVersionNumbers( - &os_major_version, &os_minor_version, &os_bugfix_version); - - info.os_version = base::StringPrintf("%d.%d.%d", os_major_version, - os_minor_version, os_bugfix_version); - return info; -} - -void SendReport(scoped_refptr<network::SharedURLLoaderFactory> loader_factory, - const GURL& url, - const std::string& body, - base::OnceCallback<void()> callback) { - auto resource_request = std::make_unique<network::ResourceRequest>(); - resource_request->method = "POST"; - resource_request->url = url; - - const auto traffic_annotation = - net::DefineNetworkTrafficAnnotation("javascript_report_error", R"( - semantics { - sender: "JavaScript error reporter" - description: - "Chrome can send JavaScript errors that occur within built-in " - "component extensions. If enabled, the error message, along " - "with information about Chrome and the operating system." - trigger: - "A JavaScript error occurs in a Chrome component extension" - data: - "The JavaScript error message, the version and channel of Chrome, " - "the URL of the extension, the line and column number where the " - "error occurred, and a stack trace of the error." - destination: GOOGLE_OWNED_SERVICE - } - )"); - - DVLOG(1) << "Sending crash report: " << resource_request->url; - - auto url_loader = network::SimpleURLLoader::Create( - std::move(resource_request), traffic_annotation); - - if (!body.empty()) { - url_loader->AttachStringForUpload(body, "text/plain"); - } - - network::SimpleURLLoader* loader = url_loader.get(); - loader->DownloadToString( - loader_factory.get(), - base::BindOnce(&OnRequestComplete, std::move(url_loader), - std::move(callback)), - kCrashEndpointResponseMaxSizeInBytes); -} - -void ReportJavaScriptError( - scoped_refptr<network::SharedURLLoaderFactory> loader_factory, - const crash_report_private::ErrorInfo& error, - base::OnceCallback<void()> callback, - const std::string& redacted_message) { - const auto platform = GetPlatformInfo(); - - const GURL source(error.url); - const auto product = error.product ? *error.product : platform.product_name; - const auto version = error.version ? *error.version : platform.version; - - ParameterMap params; - params["prod"] = net::EscapeQueryParamValue(product, /* use_plus */ false); - params["ver"] = net::EscapeQueryParamValue(version, /* use_plus */ false); - params["type"] = "JavascriptError"; - params["error_message"] = redacted_message; - params["browser"] = "Chrome"; - params["browser_version"] = platform.version; - params["channel"] = platform.channel; - params["os"] = "ChromeOS"; - params["os_version"] = platform.os_version; - params["full_url"] = source.spec(); - params["url"] = source.path(); - params["src"] = source.spec(); - if (error.line_number) - params["line"] = *error.line_number; - if (error.column_number) - params["column"] = *error.column_number; - - const GURL url(base::StrCat( - {GetCrashEndpoint(), "?", BuildPostRequestQueryString(params)})); - const std::string body = - error.stack_trace - ? RemoveErrorMessageFromStackTrace(*error.stack_trace, error.message) - : ""; - - SendReport(loader_factory, url, body, std::move(callback)); -} - -std::string RedactErrorMessage(const std::string& message) { - return feedback::RedactionTool(/*first_party_extension_ids=*/nullptr) - .Redact(message); -} - } // namespace CrashReportPrivateReportErrorFunction::CrashReportPrivateReportErrorFunction() = @@ -209,45 +32,42 @@ g_clock->Now() - g_last_called_time < base::TimeDelta::FromHours(1)) { return RespondNow(Error("Too many calls to this API")); } + g_last_called_time = base::Time::Now(); // TODO(https://crbug.com/986166): Use crash_reporter for Chrome OS. const auto params = crash_report_private::ReportError::Params::Create(*args_); EXTENSION_FUNCTION_VALIDATE(params.get()); - // Consent checking may be blocking, so do it on a separate thread to avoid - // blocking the UI thread. - base::ThreadPool::PostTaskAndReplyWithResult( - FROM_HERE, {base::MayBlock()}, - base::BindOnce(&crash_reporter::GetClientCollectStatsConsent), - base::BindOnce( - &CrashReportPrivateReportErrorFunction::OnConsentCheckCompleted, this, - std::move(params->info))); - - return RespondLater(); -} - -void CrashReportPrivateReportErrorFunction::OnConsentCheckCompleted( - crash_report_private::ErrorInfo info, - bool consented) { - // Do not report errors if the user did not give consent for crash reporting. - if (!consented) { - Respond(NoArguments()); - return; + JavaScriptErrorReport error_report; + error_report.message = std::move(params->info.message); + error_report.url = std::move(params->info.url); + if (params->info.product) { + error_report.product = std::move(*params->info.product); } - scoped_refptr<network::SharedURLLoaderFactory> loader_factory = - content::BrowserContext::GetDefaultStoragePartition(browser_context()) - ->GetURLLoaderFactoryForBrowserProcess(); + if (params->info.version) { + error_report.version = std::move(*params->info.version); + } - // Don't redact the report on the UI thread as it can take some time. - base::ThreadPool::PostTaskAndReplyWithResult( - FROM_HERE, base::BindOnce(&RedactErrorMessage, info.message), - base::BindOnce( - &ReportJavaScriptError, std::move(loader_factory), std::move(info), - base::BindOnce( - &CrashReportPrivateReportErrorFunction::OnReportComplete, this))); + if (params->info.line_number) { + error_report.line_number = *params->info.line_number; + } - g_last_called_time = base::Time::Now(); + if (params->info.column_number) { + error_report.column_number = *params->info.column_number; + } + + if (params->info.stack_trace) { + error_report.stack_trace = std::move(*params->info.stack_trace); + } + + SendJavaScriptErrorReport( + std::move(error_report), + base::BindOnce(&CrashReportPrivateReportErrorFunction::OnReportComplete, + this), + browser_context()); + + return RespondLater(); } void CrashReportPrivateReportErrorFunction::OnReportComplete() { @@ -258,9 +78,5 @@ g_clock = clock; } -void SetCrashEndpointForTesting(const std::string& endpoint) { - GetCrashEndpoint() = endpoint; -} - } // namespace api } // namespace extensions
diff --git a/extensions/browser/api/crash_report_private/crash_report_private_api.h b/extensions/browser/api/crash_report_private/crash_report_private_api.h index 0a7c7af..fd3eab2 100644 --- a/extensions/browser/api/crash_report_private/crash_report_private_api.h +++ b/extensions/browser/api/crash_report_private/crash_report_private_api.h
@@ -29,8 +29,6 @@ ResponseAction Run() override; private: - void OnConsentCheckCompleted(crash_report_private::ErrorInfo info, - bool consented); void OnReportComplete(); DISALLOW_COPY_AND_ASSIGN(CrashReportPrivateReportErrorFunction); @@ -38,8 +36,6 @@ void SetClockForTesting(base::Clock* clock); -void SetCrashEndpointForTesting(const std::string& endpoint); - } // namespace api } // namespace extensions
diff --git a/extensions/browser/api/crash_report_private/crash_report_private_apitest.cc b/extensions/browser/api/crash_report_private/crash_report_private_apitest.cc index 30c2a8f4..86378103 100644 --- a/extensions/browser/api/crash_report_private/crash_report_private_apitest.cc +++ b/extensions/browser/api/crash_report_private/crash_report_private_apitest.cc
@@ -4,9 +4,9 @@ #include "base/system/sys_info.h" #include "base/test/simple_test_clock.h" +#include "components/crash/content/browser/error_reporting/mock_crash_endpoint.h" #include "content/public/test/browser_task_environment.h" #include "extensions/browser/api/crash_report_private/crash_report_private_api.h" -#include "extensions/browser/api/crash_report_private/mock_crash_endpoint.h" #include "extensions/browser/browsertest_util.h" #include "extensions/common/switches.h" #include "extensions/shell/test/shell_apitest.h" @@ -76,7 +76,7 @@ } protected: - const MockCrashEndpoint::Report& last_report() { + const base::Optional<MockCrashEndpoint::Report>& last_report() { return crash_endpoint_->last_report(); } const Extension* extension_; @@ -97,40 +97,47 @@ ExecuteScriptInBackgroundPage(browser_context(), extension_->id(), kTestScript); - EXPECT_EQ(last_report().query, + const base::Optional<MockCrashEndpoint::Report>& report = last_report(); + ASSERT_TRUE(report); + EXPECT_EQ(report->query, "browser=Chrome&browser_version=1.2.3.4&channel=Stable&" "error_message=hi&full_url=http%3A%2F%2Fwww.test.com%2F&" "os=ChromeOS&os_version=" + GetOsVersion() + - "&prod=Chrome%2520(Chrome%2520OS)&src=http%3A%2F%2Fwww.test." + "&prod=Chrome_ChromeOS&src=http%3A%2F%2Fwww.test." "com%2F&type=JavascriptError&url=%2F&ver=1.2.3.4"); - EXPECT_EQ(last_report().content, ""); + EXPECT_EQ(report->content, ""); } IN_PROC_BROWSER_TEST_F(CrashReportPrivateApiTest, ExtraParamsAndStackTrace) { - constexpr char kTestScript[] = R"( + constexpr char kTestScript[] = R"-( chrome.crashReportPrivate.reportError({ message: "hi", url: "http://www.test.com/foo", - product: "TestApp", + product: "Chrome (Chrome OS)", version: "1.0.0.0", lineNumber: 123, columnNumber: 456, stackTrace: " at <anonymous>:1:1", }, () => window.domAutomationController.send("")); - )"; + )-"; ExecuteScriptInBackgroundPage(browser_context(), extension_->id(), kTestScript); - EXPECT_EQ(last_report().query, - "browser=Chrome&browser_version=1.2.3.4&channel=Stable&column=%C8&" + const base::Optional<MockCrashEndpoint::Report>& report = last_report(); + ASSERT_TRUE(report); + // The product name is escaped twice. The first time, it becomes + // "Chrome%20(Chrome%20OS)" and then the second escapes the '%' into '%25'. + EXPECT_EQ(report->query, + "browser=Chrome&browser_version=1.2.3.4&channel=Stable&column=456&" "error_message=hi&full_url=http%3A%2F%2Fwww.test.com%2Ffoo" - "&line=%7B&os=ChromeOS&os_version=" + + "&line=123&os=ChromeOS&os_version=" + GetOsVersion() + - "&prod=TestApp&src=http%3A%2F%2Fwww.test.com%2Ffoo&type=" - "JavascriptError&url=%2Ffoo&ver=1.0.0.0"); - EXPECT_EQ(last_report().content, " at <anonymous>:1:1"); + "&prod=Chrome%2520(Chrome%2520OS)&" + "src=http%3A%2F%2Fwww.test.com%2Ffoo&" + "type=JavascriptError&url=%2Ffoo&ver=1.0.0.0"); + EXPECT_EQ(report->content, " at <anonymous>:1:1"); } IN_PROC_BROWSER_TEST_F(CrashReportPrivateApiTest, StackTraceWithErrorMessage) { @@ -149,17 +156,19 @@ ExecuteScriptInBackgroundPage(browser_context(), extension_->id(), kTestScript); - EXPECT_EQ(last_report().query, - "browser=Chrome&browser_version=1.2.3.4&channel=Stable&column=%C8&" + const base::Optional<MockCrashEndpoint::Report>& report = last_report(); + ASSERT_TRUE(report); + EXPECT_EQ(report->query, + "browser=Chrome&browser_version=1.2.3.4&channel=Stable&column=456&" "error_message=hi&full_url=http%3A%2F%2Fwww.test.com%2Ffoo&" - "line=%7B&os=ChromeOS&os_version=" + + "line=123&os=ChromeOS&os_version=" + GetOsVersion() + "&prod=TestApp&src=http%3A%2F%2Fwww.test.com%2Ffoo&type=" "JavascriptError&url=%2Ffoo&ver=1.0.0.0"); - EXPECT_EQ(last_report().content, ""); + EXPECT_EQ(report->content, ""); } -IN_PROC_BROWSER_TEST_F(CrashReportPrivateApiTest, AnonymizeMessage) { +IN_PROC_BROWSER_TEST_F(CrashReportPrivateApiTest, RedactMessage) { // We use the feedback APIs redaction tool, which scrubs many different types // of PII. As a sanity check, test if MAC addresses are redacted. constexpr char kTestScript[] = R"( @@ -176,15 +185,17 @@ ExecuteScriptInBackgroundPage(browser_context(), extension_->id(), kTestScript); - EXPECT_EQ(last_report().query, - "browser=Chrome&browser_version=1.2.3.4&channel=Stable&column=%C8&" + const base::Optional<MockCrashEndpoint::Report>& report = last_report(); + ASSERT_TRUE(report); + EXPECT_EQ(report->query, + "browser=Chrome&browser_version=1.2.3.4&channel=Stable&column=456&" "error_message=%5BMAC%20OUI%3D06%3A00%3A00%20IFACE%3D1%5D&" - "full_url=http%3A%2F%2Fwww.test.com%2Ffoo&line=%7B&os=ChromeOS&" + "full_url=http%3A%2F%2Fwww.test.com%2Ffoo&line=123&os=ChromeOS&" "os_version=" + GetOsVersion() + "&prod=TestApp&src=http%3A%2F%2Fwww.test.com%2Ffoo&type=" "JavascriptError&url=%2Ffoo&ver=1.0.0.0"); - EXPECT_EQ(last_report().content, ""); + EXPECT_EQ(report->content, ""); } IN_PROC_BROWSER_TEST_F(CrashReportPrivateApiTest, Throttling) { @@ -238,8 +249,8 @@ EXPECT_EQ("", ExecuteScriptInBackgroundPage(browser_context(), extension_->id(), kTestScript)); // The server should not receive any reports. - EXPECT_EQ(last_report().query, ""); - EXPECT_EQ(last_report().content, ""); + const base::Optional<MockCrashEndpoint::Report>& report = last_report(); + EXPECT_FALSE(report); } } // namespace extensions
diff --git a/extensions/docs/api_functions.md b/extensions/docs/api_functions.md index 081f578..6839f80 100644 --- a/extensions/docs/api_functions.md +++ b/extensions/docs/api_functions.md
@@ -97,14 +97,14 @@ DECLARE_EXTENSION_FUNCTION("gizmo.frobulate", GIZMO_FROBULATE) GizmoFrobulateFunction(); + GizmoFrobulateFunction(const GizmoFrobulateFunction&) = delete; + GizmoFrobulateFunction& operator=(const GizmoFrobulateFunction&) = delete; private: ~GizmoFrobulateFunction() override; // ExtensionFunction: ResponseAction Run() override; - - DISALLOW_COPY_AND_ASSIGN(GizmoFrobulateFunction); }; ```
diff --git a/google_apis/gcm/base/socket_stream.cc b/google_apis/gcm/base/socket_stream.cc index 65510186..2bc252f81 100644 --- a/google_apis/gcm/base/socket_stream.cc +++ b/google_apis/gcm/base/socket_stream.cc
@@ -216,7 +216,6 @@ DCHECK_LT(error, net::ERR_IO_PENDING); ResetInternal(); last_error_ = error; - LOG(ERROR) << "Closing stream with result " << error; } SocketOutputStream::SocketOutputStream(
diff --git a/gpu/config/gpu_driver_bug_list.json b/gpu/config/gpu_driver_bug_list.json index 98159da..a63d44f 100644 --- a/gpu/config/gpu_driver_bug_list.json +++ b/gpu/config/gpu_driver_bug_list.json
@@ -3543,6 +3543,22 @@ "features": [ "reset_vp_when_colorspace_changes" ] + }, + { + "id": 351, + "cr_bugs": [1079393], + "description": "Some Intel GPUs have NV12 overlay support, but aren't advertised.", + "os": { + "type": "win" + }, + "vendor_id": "0x8086", + "device_id": ["0x5906", "0x5913", "0x5916", "0x5921", "0x5926", "0x590e", + "0x5915", "0x591e", "0x5902", "0x5917", "0x590b", "0x5908", + "0x591b", "0x593b", "0x590a", "0x591a", "0x591d", "0x5923", + "0x5927", "0x5932", "0x592b", "0x592a", "0x593a", "0x593d"], + "features": [ + "force_nv12_overlay_support" + ] } ] }
diff --git a/gpu/config/gpu_workaround_list.txt b/gpu/config/gpu_workaround_list.txt index 1e064f7..fc52c0ff 100644 --- a/gpu/config/gpu_workaround_list.txt +++ b/gpu/config/gpu_workaround_list.txt
@@ -72,6 +72,7 @@ force_high_performance_gpu force_int_or_srgb_cube_texture_complete force_low_power_gpu +force_nv12_overlay_support force_rgb10a2_overlay_support_flags force_update_scissor_state_when_binding_fbo0 get_frag_data_info_bug
diff --git a/gpu/ipc/service/gpu_init.cc b/gpu/ipc/service/gpu_init.cc index b3dd888..7a4deca1 100644 --- a/gpu/ipc/service/gpu_init.cc +++ b/gpu/ipc/service/gpu_init.cc
@@ -96,6 +96,9 @@ gpu::ENABLE_BGRA8_OVERLAYS_WITH_YUV_OVERLAY_SUPPORT)) { gl::DirectCompositionSurfaceWin::EnableBGRA8OverlaysWithYUVOverlaySupport(); } + if (gpu_feature_info.IsWorkaroundEnabled(gpu::FORCE_NV12_OVERLAY_SUPPORT)) { + gl::DirectCompositionSurfaceWin::ForceNV12OverlaySupport(); + } DCHECK(gpu_info); CollectHardwareOverlayInfo(&gpu_info->overlay_info); #elif defined(OS_ANDROID)
diff --git a/infra/config/generated/commit-queue.cfg b/infra/config/generated/commit-queue.cfg index e1e8d71..b01ed8a 100644 --- a/infra/config/generated/commit-queue.cfg +++ b/infra/config/generated/commit-queue.cfg
@@ -1015,6 +1015,10 @@ includable_only: true } builders { + name: "chromium/try/linux-inverse-fieldtrials-fyi-rel" + includable_only: true + } + builders { name: "chromium/try/linux-lacros-fyi-rel" includable_only: true }
diff --git a/infra/config/generated/cr-buildbucket.cfg b/infra/config/generated/cr-buildbucket.cfg index dd345a15..95795a3 100644 --- a/infra/config/generated/cr-buildbucket.cfg +++ b/infra/config/generated/cr-buildbucket.cfg
@@ -10818,6 +10818,35 @@ } } builders { + name: "linux-inverse-fieldtrials-fyi-rel" + swarming_host: "chromium-swarm.appspot.com" + swarming_tags: "vpython:native-python-wrapper" + dimensions: "builderless:1" + dimensions: "cores:8" + dimensions: "cpu:x86-64" + dimensions: "os:Ubuntu-16.04" + dimensions: "pool:luci.chromium.ci" + dimensions: "ssd:0" + exe { + cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" + cipd_version: "refs/heads/master" + cmd: "recipes" + } + properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"builder_group\":\"chromium.fyi\",\"recipe\":\"chromium\"}" + execution_timeout_secs: 36000 + build_numbers: YES + service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" + resultdb { + enable: true + bq_exports { + project: "luci-resultdb" + dataset: "chromium" + table: "ci_test_results" + test_results {} + } + } + } + builders { name: "linux-lacros-builder-fyi-rel" swarming_host: "chromium-swarm.appspot.com" swarming_tags: "vpython:native-python-wrapper" @@ -23405,6 +23434,43 @@ } } builders { + name: "linux-inverse-fieldtrials-fyi-rel" + swarming_host: "chromium-swarm.appspot.com" + swarming_tags: "vpython:native-python-wrapper" + dimensions: "builderless:1" + dimensions: "cores:8" + dimensions: "cpu:x86-64" + dimensions: "os:Ubuntu-16.04" + dimensions: "pool:luci.chromium.try" + dimensions: "ssd:0" + exe { + cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" + cipd_version: "refs/heads/master" + cmd: "recipes" + } + properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}" + execution_timeout_secs: 14400 + expiration_secs: 7200 + caches { + name: "win_toolchain" + path: "win_toolchain" + } + build_numbers: YES + service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" + task_template_canary_percentage { + value: 5 + } + resultdb { + enable: true + bq_exports { + project: "luci-resultdb" + dataset: "chromium" + table: "try_test_results" + test_results {} + } + } + } + builders { name: "linux-lacros-fyi-rel" swarming_host: "chromium-swarm.appspot.com" swarming_tags: "vpython:native-python-wrapper"
diff --git a/infra/config/generated/luci-milo.cfg b/infra/config/generated/luci-milo.cfg index 923bdb7..6bb8463 100644 --- a/infra/config/generated/luci-milo.cfg +++ b/infra/config/generated/luci-milo.cfg
@@ -6689,6 +6689,10 @@ category: "linux" } builders { + name: "buildbucket/luci.chromium.ci/linux-inverse-fieldtrials-fyi-rel" + category: "linux" + } + builders { name: "buildbucket/luci.chromium.ci/linux-lacros-builder-fyi-rel" category: "linux" } @@ -7949,1436 +7953,6 @@ include_experimental_builds: true } consoles { - id: "chromium.goma.migration" - name: "chromium.goma.migration" - repo_url: "https://chromium.googlesource.com/chromium/src" - refs: "regexp:refs/heads/master" - manifest_name: "REVISION" - builders { - name: "buildbucket/luci.chromium.ci/VR Linux" - category: "week1|linux" - short_name: "vr" - } - builders { - name: "buildbucket/luci.chromium.ci/Mojo Linux" - category: "week1|linux" - short_name: "mojo" - } - builders { - name: "buildbucket/luci.chromium.ci/Linux Builder (dbg)" - category: "week1|linux|dbg" - } - builders { - name: "buildbucket/luci.chromium.ci/Linux Builder (dbg)(32)" - category: "week1|linux|dbg" - short_name: "32bit" - } - builders { - name: "buildbucket/luci.chromium.ci/Linux CFI" - category: "week1|linux|cfi" - } - builders { - name: "buildbucket/luci.chromium.ci/Linux MSan Builder" - category: "week1|linux" - short_name: "msan" - } - builders { - name: "buildbucket/luci.chromium.ci/Afl Upload Linux ASan" - category: "week1|linux" - short_name: "afl-asan" - } - builders { - name: "buildbucket/luci.chromium.ci/WebKit Linux ASAN" - category: "week1|linux|webkit" - short_name: "asan" - } - builders { - name: "buildbucket/luci.chromium.ci/WebKit Linux Leak" - category: "week1|linux|webkit" - short_name: "leak" - } - builders { - name: "buildbucket/luci.chromium.ci/WebKit Linux MSAN" - category: "week1|linux|webkit" - short_name: "msan" - } - builders { - name: "buildbucket/luci.chromium.ci/Android FYI 32 Vk Release (Pixel 2)" - category: "week2a|android|32" - short_name: "p2" - } - builders { - name: "buildbucket/luci.chromium.ci/Android FYI 32 dEQP Vk Release (Pixel 2)" - category: "week2a|android|32deqp" - short_name: "p2" - } - builders { - name: "buildbucket/luci.chromium.ci/Android FYI 64 Vk Release (Pixel 2)" - category: "week2a|android|64" - short_name: "p2" - } - builders { - name: "buildbucket/luci.chromium.ci/Android FYI 64 dEQP Vk Release (Pixel 2)" - category: "week2a|android|64deqp" - short_name: "p2" - } - builders { - name: "buildbucket/luci.chromium.ci/Android FYI Release (NVIDIA Shield TV)" - category: "week2a|android|rel" - short_name: "shdtv" - } - builders { - name: "buildbucket/luci.chromium.ci/Android FYI Release (Nexus 5)" - category: "week2a|android|rel" - short_name: "n5" - } - builders { - name: "buildbucket/luci.chromium.ci/Android FYI Release (Nexus 5X)" - category: "week2a|android|rel" - short_name: "n5x" - } - builders { - name: "buildbucket/luci.chromium.ci/Android FYI Release (Nexus 6)" - category: "week2a|android|rel" - short_name: "n6" - } - builders { - name: "buildbucket/luci.chromium.ci/Android FYI Release (Nexus 6P)" - category: "week2a|android|rel" - short_name: "n6p" - } - builders { - name: "buildbucket/luci.chromium.ci/Android FYI Release (Nexus 9)" - category: "week2a|android|rel" - short_name: "n9" - } - builders { - name: "buildbucket/luci.chromium.ci/Android FYI Release (Pixel 2)" - category: "week2a|android|rel" - short_name: "p2" - } - builders { - name: "buildbucket/luci.chromium.ci/Android FYI dEQP Release (Nexus 5X)" - category: "week2a|android|deqp" - short_name: "n5x" - } - builders { - name: "buildbucket/luci.chromium.ci/Deterministic Android" - category: "week2a|android|det" - } - builders { - name: "buildbucket/luci.chromium.ci/Deterministic Android (dbg)" - category: "week2a|android|det" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.chromium.webrtc.fyi/WebRTC Chromium FYI Android Builder" - category: "week2b|android|release" - short_name: "32" - } - builders { - name: "buildbucket/luci.chromium.webrtc.fyi/WebRTC Chromium FYI Android Builder (dbg)" - category: "week2b|android|debug|builder" - short_name: "32" - } - builders { - name: "buildbucket/luci.chromium.webrtc.fyi/WebRTC Chromium FYI Android Builder ARM64 (dbg)" - category: "week2b|android|debug|builder" - short_name: "64" - } - builders { - name: "buildbucket/luci.chromium.webrtc.fyi/WebRTC Chromium FYI Linux Builder" - category: "week2b|linux|release" - short_name: "bld" - } - builders { - name: "buildbucket/luci.chromium.webrtc.fyi/WebRTC Chromium FYI Linux Builder (dbg)" - category: "week2b|linux|debug" - short_name: "bld" - } - builders { - name: "buildbucket/luci.chromium.webrtc.fyi/WebRTC Chromium FYI Mac Builder" - category: "week2b|mac|release" - short_name: "bld" - } - builders { - name: "buildbucket/luci.chromium.webrtc.fyi/WebRTC Chromium FYI Mac Builder (dbg)" - category: "week2b|mac|debug" - short_name: "bld" - } - builders { - name: "buildbucket/luci.chromium.webrtc/WebRTC Chromium Android Builder" - category: "week2b|android" - short_name: "bld" - } - builders { - name: "buildbucket/luci.chromium.webrtc/WebRTC Chromium Linux Builder" - category: "week2b|linux" - short_name: "bld" - } - builders { - name: "buildbucket/luci.chromium.webrtc/WebRTC Chromium Mac Builder" - category: "week2b|mac" - short_name: "bld" - } - builders { - name: "buildbucket/luci.chromium.ci/Mac ASAN Release" - category: "week2c|mac|asan" - } - builders { - name: "buildbucket/luci.chromium.ci/Mac ASAN Release Media" - category: "week2c|mac|asan" - short_name: "media" - } - builders { - name: "buildbucket/luci.chromium.ci/Mac ASan 64 Builder" - category: "week2c|mac|asan" - short_name: "64" - } - builders { - name: "buildbucket/luci.chromium.ci/Libfuzzer Upload Mac ASan" - category: "week2c|mac|asan" - short_name: "fuzz" - } - builders { - name: "buildbucket/luci.chromium.ci/Android CFI" - category: "week2c|android" - short_name: "cfi" - } - builders { - name: "buildbucket/luci.chromium.ci/Site Isolation Android" - category: "week2c|android" - short_name: "isolate" - } - builders { - name: "buildbucket/luci.chromium.ci/Mojo Android" - category: "week2c|android" - short_name: "mojo" - } - builders { - name: "buildbucket/luci.chromium.ci/Android x64 Builder (dbg)" - category: "week2c|android|dbg" - short_name: "x64" - } - builders { - name: "buildbucket/luci.chromium.ci/Android x86 Builder (dbg)" - category: "week2c|android|dbg" - short_name: "x86" - } - builders { - name: "buildbucket/luci.chromium.ci/Android WebView L (dbg)" - category: "week2c|android|dbg|webview" - short_name: "l" - } - builders { - name: "buildbucket/luci.chromium.ci/Android WebView M (dbg)" - category: "week2c|android|dbg|webview" - short_name: "m" - } - builders { - name: "buildbucket/luci.chromium.ci/Android WebView N (dbg)" - category: "week2c|android|dbg|webview" - short_name: "n" - } - builders { - name: "buildbucket/luci.chromium.ci/Android WebView O (dbg)" - category: "week2c|android|dbg|webview" - short_name: "o" - } - builders { - name: "buildbucket/luci.chromium.ci/Android WebView P FYI (rel)" - category: "week2c|android|rel|webview" - short_name: "p" - } - builders { - name: "buildbucket/luci.chromium.ci/Dawn Linux x64 Builder" - category: "week2d|linux|dawn" - } - builders { - name: "buildbucket/luci.chromium.ci/Dawn Linux x64 DEPS Builder" - category: "week2d|linux|dawn" - short_name: "deps" - } - builders { - name: "buildbucket/luci.chromium.ci/GPU FYI Linux Builder" - category: "week2d|linux|gpu|fyi" - } - builders { - name: "buildbucket/luci.chromium.ci/GPU FYI Linux Builder (dbg)" - category: "week2d|linux|gpu|fyi" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.chromium.ci/GPU FYI Linux Ozone Builder" - category: "week2d|linux|gpu|fyi" - short_name: "ozone" - } - builders { - name: "buildbucket/luci.chromium.ci/GPU FYI Linux dEQP Builder" - category: "week2d|linux|gpu|fyi" - short_name: "deqp" - } - builders { - name: "buildbucket/luci.chromium.ci/Linux FYI GPU TSAN Release" - category: "week2d|linux|gpu|fyi" - short_name: "tsan" - } - builders { - name: "buildbucket/luci.chromium.ci/GPU Linux Builder (dbg)" - category: "week2d|linux|gpu" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.chromium.ci/Linux Viz" - category: "week2d|linux" - short_name: "viz" - } - builders { - name: "buildbucket/luci.chromium.ci/Linux remote_run Builder" - category: "week2d|linux" - short_name: "rem" - } - builders { - name: "buildbucket/luci.chromium.ci/Closure Compilation Linux" - category: "week2d|linux" - short_name: "clsr" - } - builders { - name: "buildbucket/luci.chromium.ci/Deterministic Linux" - category: "week2d|linux|det" - } - builders { - name: "buildbucket/luci.chromium.ci/Deterministic Linux (dbg)" - category: "week2d|linux|det" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.chromium.ci/Dawn Mac x64 Builder" - category: "week2d|mac|dawn" - } - builders { - name: "buildbucket/luci.chromium.ci/Dawn Mac x64 DEPS Builder" - category: "week2d|mac|dawn" - short_name: "deps" - } - builders { - name: "buildbucket/luci.chromium.ci/GPU FYI Mac Builder" - category: "week2d|mac|gpu|fyi" - } - builders { - name: "buildbucket/luci.chromium.ci/GPU FYI Mac Builder (dbg)" - category: "week2d|mac|gpu|fyi" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.chromium.ci/GPU FYI Mac dEQP Builder" - category: "week2d|mac|gpu|fyi" - short_name: "deqp" - } - builders { - name: "buildbucket/luci.chromium.ci/Mac FYI GPU ASAN Release" - category: "week2d|mac|gpu|fyi" - short_name: "asan" - } - builders { - name: "buildbucket/luci.chromium.ci/GPU Mac Builder (dbg)" - category: "week2d|mac|gpu" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.chromium.ci/Mac deterministic" - category: "week2d|mac|det" - } - builders { - name: "buildbucket/luci.chromium.ci/Mac deterministic (dbg)" - category: "week2d|mac|det" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.chromium.ci/Linux Builder" - category: "week2.5|linux" - } - builders { - name: "buildbucket/luci.chromium.ci/GPU Linux Builder" - category: "week2.5|linux" - short_name: "gpu" - } - builders { - name: "buildbucket/luci.chromium.ci/linux-ozone-rel" - category: "week3a|linux" - short_name: "ozone" - } - builders { - name: "buildbucket/luci.chromium.ci/linux-annotator-rel" - category: "week3a|linux" - short_name: "anno" - } - builders { - name: "buildbucket/luci.chromium.ci/linux-code-coverage" - category: "week3a|linux" - short_name: "code" - } - builders { - name: "buildbucket/luci.chromium.ci/linux-blink-animation-use-time-delta" - category: "week3a|linux|blink" - short_name: "anim" - } - builders { - name: "buildbucket/luci.chromium.ci/linux-blink-heap-concurrent-marking-tsan-rel" - category: "week3a|linux|blink" - short_name: "tsan" - } - builders { - name: "buildbucket/luci.chromium.ci/linux-blink-heap-verification" - category: "week3a|linux|blink" - short_name: "ver" - } - builders { - name: "buildbucket/luci.chromium.ci/linux-chromium-tests-staging-builder" - category: "week3a|linux" - short_name: "crtests" - } - builders { - name: "buildbucket/luci.chromium.ci/android-cronet-arm-dbg" - category: "week3b|android|cronet|arm" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.chromium.ci/android-cronet-arm-rel" - category: "week3b|android|cronet|arm" - } - builders { - name: "buildbucket/luci.chromium.ci/android-cronet-asan-arm-rel" - category: "week3b|android|cronet|arm" - short_name: "asan" - } - builders { - name: "buildbucket/luci.chromium.ci/android-cronet-kitkat-arm-rel" - category: "week3b|android|cronet|arm" - short_name: "kkat" - } - builders { - name: "buildbucket/luci.chromium.ci/android-cronet-lollipop-arm-rel" - category: "week3b|android|cronet|arm" - short_name: "lpop" - } - builders { - name: "buildbucket/luci.chromium.ci/android-cronet-arm64-rel" - category: "week3b|android|cronet|arm64" - } - builders { - name: "buildbucket/luci.chromium.ci/android-cronet-arm64-dbg" - category: "week3b|android|cronet|arm64" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.chromium.ci/android-cronet-marshmallow-arm64-rel" - category: "week3b|android|cronet|arm64" - short_name: "marsh" - } - builders { - name: "buildbucket/luci.chromium.ci/android-cronet-marshmallow-arm64-perf-rel" - category: "week3b|android|cronet|arm64" - short_name: "perf" - } - builders { - name: "buildbucket/luci.chromium.ci/android-cronet-x86-rel" - category: "week3b|android|cronet|x86" - } - builders { - name: "buildbucket/luci.chromium.ci/android-cronet-x86-dbg" - category: "week3b|android|cronet|x86" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.chromium.ci/android-incremental-dbg" - category: "week3b|android" - short_name: "inc" - } - builders { - name: "buildbucket/luci.chromium.ci/android-mojo-webview-rel" - category: "week3b|android" - short_name: "mojo" - } - builders { - name: "buildbucket/luci.chromium.ci/android-pie-arm64-dbg" - category: "week3b|linux" - short_name: "pie" - } - builders { - name: "buildbucket/luci.chromium.ci/mac-code-coverage" - category: "week3c|mac" - short_name: "code" - } - builders { - name: "buildbucket/luci.chromium.ci/mac-hermetic-upgrade-rel" - category: "week3c|mac" - short_name: "herm" - } - builders { - name: "buildbucket/luci.chromium.ci/mac-mojo-rel" - category: "week3c|mac" - short_name: "mojo" - } - builders { - name: "buildbucket/luci.chromium.ci/mac-osxbeta-rel" - category: "week3c|mac" - short_name: "osx" - } - builders { - name: "buildbucket/luci.chromium.ci/Mac Builder" - category: "week3c|mac" - } - builders { - name: "buildbucket/luci.chromium.ci/Mac Builder (dbg)" - category: "week3c|mac" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.chromium.ci/GPU Mac Builder" - category: "week3c|mac" - short_name: "gpu" - } - builders { - name: "buildbucket/luci.chromium.ci/Libfuzzer Upload Linux ASan" - category: "week4|linux" - short_name: "asan" - } - builders { - name: "buildbucket/luci.chromium.ci/Libfuzzer Upload Linux ASan Debug" - category: "week4|linux" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.chromium.ci/Libfuzzer Upload Linux MSan" - category: "week4|linux" - short_name: "msan" - } - builders { - name: "buildbucket/luci.chromium.ci/Libfuzzer Upload Linux UBSan" - category: "week4|linux" - short_name: "ubsan" - } - builders { - name: "buildbucket/luci.chromium.ci/Libfuzzer Upload Linux V8-ARM64 ASan" - category: "week4|linux|v8arm" - short_name: "asan" - } - builders { - name: "buildbucket/luci.chromium.ci/Libfuzzer Upload Linux V8-ARM64 ASan Debug" - category: "week4|linux|v8arm" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.chromium.ci/Libfuzzer Upload Linux32 ASan" - category: "week4|linux32" - short_name: "asan" - } - builders { - name: "buildbucket/luci.chromium.ci/Libfuzzer Upload Linux32 ASan Debug" - category: "week4|linux32" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.chromium.ci/Libfuzzer Upload Linux32 V8-ARM ASan" - category: "week4|linux32|v8arm" - short_name: "asan" - } - builders { - name: "buildbucket/luci.chromium.ci/Libfuzzer Upload Linux32 V8-ARM ASan Debug" - category: "week4|linux32|v8arm" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.chromium.ci/ASan Debug (32-bit x86 with V8-ARM)" - category: "week5|asan" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.chromium.ci/ASan Release (32-bit x86 with V8-ARM)" - category: "week5|asan" - short_name: "rel" - } - builders { - name: "buildbucket/luci.chromium.ci/ASan Release Media (32-bit x86 with V8-ARM)" - category: "week5|asan" - short_name: "media" - } - builders { - name: "buildbucket/luci.chromium.ci/ASAN Debug" - category: "week6|asan" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.chromium.ci/ASAN Release" - category: "week6|asan" - short_name: "rel" - } - builders { - name: "buildbucket/luci.chromium.ci/ASAN Release Media" - category: "week6|asan" - short_name: "media" - } - builders { - name: "buildbucket/luci.chromium.ci/MSAN Release (chained origins)" - category: "week7|msan" - short_name: "chain" - } - builders { - name: "buildbucket/luci.chromium.ci/MSAN Release (no origins)" - category: "week7|msan" - short_name: "none" - } - builders { - name: "buildbucket/luci.chromium.ci/TSAN Release" - category: "week8|tsan" - short_name: "rel" - } - builders { - name: "buildbucket/luci.chromium.ci/TSAN Debug" - category: "week8|tsan" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.chromium.ci/UBSan Release" - category: "week9|ubsan" - } - builders { - name: "buildbucket/luci.chromium.ci/UBSan vptr Release" - category: "week9|ubsan|vptr" - short_name: "rel" - } - builders { - name: "buildbucket/luci.chromium.ci/UBSanVptr Linux" - category: "week9|ubsan|vptr" - short_name: "lnx" - } - builders { - name: "buildbucket/luci.chromium.ci/Cast Android (dbg)" - category: "week10|android" - } - builders { - name: "buildbucket/luci.chromium.ci/Cast Audio Linux" - category: "week10|linux" - short_name: "audio" - } - builders { - name: "buildbucket/luci.chromium.ci/Cast Linux" - category: "week10|linux" - } - builders { - name: "buildbucket/luci.chromium.ci/Fuchsia ARM64" - category: "week11|fuchsia|arm64" - } - builders { - name: "buildbucket/luci.chromium.ci/fuchsia-arm64-cast" - category: "week11|fuchsia|arm64" - short_name: "cast" - } - builders { - name: "buildbucket/luci.chromium.ci/Fuchsia x64" - category: "week11|fuchsia|x64" - } - builders { - name: "buildbucket/luci.chromium.ci/fuchsia-x64-cast" - category: "week11|fuchsia|x64" - short_name: "cast" - } - builders { - name: "buildbucket/luci.chromium.ci/fuchsia-fyi-arm64-rel" - category: "week11|fuchsia|fyi" - short_name: "arm64" - } - builders { - name: "buildbucket/luci.chromium.ci/fuchsia-fyi-x64-dbg" - category: "week11|fuchsia|fyi" - short_name: "x64 dbg" - } - builders { - name: "buildbucket/luci.chromium.ci/fuchsia-fyi-x64-rel" - category: "week11|fuchsia|fyi" - short_name: "x64 rel" - } - builders { - name: "buildbucket/luci.chromium.ci/android-marshmallow-arm64-rel" - category: "week13|android" - short_name: "marsh" - } - builders { - name: "buildbucket/luci.chromium.ci/Android Release (Nexus 5X)" - category: "week13|android" - short_name: "n5x" - } - builders { - name: "buildbucket/luci.chromium.ci/Linux ASan LSan Builder" - category: "week14a|linux" - short_name: "asanlsan" - } - builders { - name: "buildbucket/luci.chromium.ci/Linux TSan Builder" - category: "week14a|linux" - short_name: "tsan" - } - builders { - name: "buildbucket/luci.chromium.ci/Android ASAN (dbg)" - category: "week14b|android" - short_name: "asanlsan" - } - builders { - name: "buildbucket/luci.chromium.ci/Android arm Builder (dbg)" - category: "week14b|android" - short_name: "tsan" - } - builders { - name: "buildbucket/luci.chromium.ci/Android arm64 Builder (dbg)" - category: "week14b|android" - short_name: "tsan" - } - builders { - name: "buildbucket/luci.chromium.ci/fuchsia-x64-dbg" - category: "week15a|fuchsia" - short_name: "x64dbg" - } - builders { - name: "buildbucket/luci.chromium.ci/linux-archive-dbg" - category: "week15a|linux|archive" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.chromium.ci/linux-archive-rel" - category: "week15a|linux|archive" - short_name: "rel" - } - builders { - name: "buildbucket/luci.chromium.ci/linux-bfcache-rel" - category: "week15a|linux" - short_name: "bfc" - } - builders { - name: "buildbucket/luci.chromium.ci/linux-fieldtrial-rel" - category: "week15a|linux" - short_name: "field" - } - builders { - name: "buildbucket/luci.chromium.ci/android-archive-rel" - category: "week15b|android|archive" - short_name: "rel" - } - builders { - name: "buildbucket/luci.chromium.ci/android-archive-dbg" - category: "week15b|android|archive" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.chromium.ci/android-asan" - category: "week15b|android" - short_name: "asan" - } - builders { - name: "buildbucket/luci.chromium.ci/android-bfcache-rel" - category: "week15b|android" - short_name: "bfc" - } - builders { - name: "buildbucket/luci.chromium.ci/android-code-coverage" - category: "week15b|android" - short_name: "code" - } - builders { - name: "buildbucket/luci.chromium.ci/android-pie-arm64-rel" - category: "week15b|android|pie" - short_name: "arm64" - } - builders { - name: "buildbucket/luci.chromium.ci/android-pie-x86-rel" - category: "week15b|android|pie" - short_name: "x86" - } - builders { - name: "buildbucket/luci.chromium.ci/GPU FYI Perf Android 64 Builder" - category: "week15b|android|gpu" - short_name: "perf64" - } - builders { - name: "buildbucket/luci.chromium.ci/mac-archive-rel" - category: "week15b|mac|archive" - short_name: "rel" - } - builders { - name: "buildbucket/luci.chromium.ci/mac-archive-dbg" - category: "week15b|mac|archive" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.chromium.ci/android-marshmallow-x86-rel-non-cq" - category: "week16b" - short_name: "marsh" - } - builders { - name: "buildbucket/luci.chromium.ci/Android FYI 64 Perf (Pixel 2)" - category: "week16b" - short_name: "pxl2" - } - builders { - name: "buildbucket/luci.chromium.ci/linux-swangle-tot-angle-x64" - category: "week17|swangle|angle" - short_name: "x64" - } - builders { - name: "buildbucket/luci.chromium.ci/linux-swangle-tot-angle-x86" - category: "week17|swangle|angle" - short_name: "x86" - } - builders { - name: "buildbucket/luci.chromium.ci/linux-swangle-tot-swiftshader-x64" - category: "week17|swangle|swift" - short_name: "x64" - } - builders { - name: "buildbucket/luci.chromium.ci/linux-swangle-tot-swiftshader-x86" - category: "week17|swangle|swift" - short_name: "x86" - } - builders { - name: "buildbucket/luci.chromium.ci/linux-swangle-x64" - category: "week17|swangle" - short_name: "x64" - } - builders { - name: "buildbucket/luci.chromium.ci/linux-swangle-x86" - category: "week17|swangle" - short_name: "x86" - } - builders { - name: "buildbucket/luci.chromium.ci/android-code-coverage-native" - category: "misc|android" - } - builders { - name: "buildbucket/luci.chromium.ci/Win ASan Release" - category: "win|week1|asan" - } - builders { - name: "buildbucket/luci.chromium.ci/Win ASan Release Media" - category: "win|week1|asan" - short_name: "media" - } - builders { - name: "buildbucket/luci.chromium.ci/win10-code-coverage" - category: "win|week1.1" - short_name: "code" - } - builders { - name: "buildbucket/luci.chromium.ci/Win x64 Builder (dbg)" - category: "win|week1.5" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.chromium.ci/win-archive-dbg" - category: "win|week1.5|archive" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.chromium.ci/win-archive-rel" - category: "win|week1.5|archive" - short_name: "rel" - } - builders { - name: "buildbucket/luci.chromium.ci/Dawn Win10 x64 Builder" - category: "win|week2|dawn" - } - builders { - name: "buildbucket/luci.chromium.ci/Dawn Win10 x64 DEPS Builder" - category: "win|week2|dawn" - short_name: "deps" - } - builders { - name: "buildbucket/luci.chromium.ci/GPU Win x64 Builder (dbg)" - category: "win|week2|gpu" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.chromium.ci/GPU FYI XR Win x64 Builder" - category: "win|week2|gpu|fyi" - short_name: "xr" - } - builders { - name: "buildbucket/luci.chromium.ci/GPU FYI Win x64 dEQP Builder" - category: "win|week2|gpu|fyi" - short_name: "deqp" - } - builders { - name: "buildbucket/luci.chromium.ci/GPU FYI Win x64 DX12 Vulkan Builder" - category: "win|week2|gpu|fyi|dx12" - short_name: "rel" - } - builders { - name: "buildbucket/luci.chromium.ci/GPU FYI Win x64 DX12 Vulkan Builder (dbg)" - category: "win|week2|gpu|fyi|dx12" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.chromium.ci/GPU FYI Win x64 Builder" - category: "win|week2|gpu|fyi" - short_name: "rel" - } - builders { - name: "buildbucket/luci.chromium.ci/GPU FYI Win x64 Builder (dbg)" - category: "win|week2|gpu|fyi" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.chromium.ci/Win Builder" - category: "win|week3" - short_name: "rel" - } - builders { - name: "buildbucket/luci.chromium.ci/Win Builder (dbg)" - category: "win|week3" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.chromium.ci/GPU FYI Win Builder" - category: "win|week3|gpu|fyi" - short_name: "rel" - } - builders { - name: "buildbucket/luci.chromium.ci/GPU FYI Win Builder (dbg)" - category: "win|week3|gpu|fyi" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.chromium.ci/GPU FYI Win dEQP Builder" - category: "win|week3|gpu|fyi" - short_name: "deqp" - } - builders { - name: "buildbucket/luci.chromium.ci/Dawn Win10 x86 Builder" - category: "win|week3|dawn" - short_name: "rel" - } - builders { - name: "buildbucket/luci.chromium.ci/Dawn Win10 x86 DEPS Builder" - category: "win|week3|dawn" - short_name: "deps" - } - builders { - name: "buildbucket/luci.chromium.ci/win32-archive-rel" - category: "win|week4|win32" - short_name: "rel" - } - builders { - name: "buildbucket/luci.chromium.ci/win32-archive-dbg" - category: "win|week4|win32" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.chromium.ci/win32-arm64-rel" - category: "win|week4|win32" - short_name: "arm" - } - builders { - name: "buildbucket/luci.chromium.ci/Libfuzzer Upload Windows ASan" - category: "win|week4" - short_name: "libfuzzer" - } - builders { - name: "buildbucket/luci.chromium.ci/Windows deterministic" - category: "win|week4" - short_name: "det" - } - builders { - name: "buildbucket/luci.chromium.ci/Mojo Windows" - category: "win|week4" - short_name: "mojo" - } - builders { - name: "buildbucket/luci.chromium.ci/win-celab-builder-rel" - category: "win|week4" - short_name: "celab" - } - builders { - name: "buildbucket/luci.chromium.ci/win-asan" - category: "win|week4" - short_name: "asan" - } - builders { - name: "buildbucket/luci.chromium.ci/Win 10 Fast Ring" - category: "win|week4" - short_name: "fastring" - } - builders { - name: "buildbucket/luci.chromium.ci/win-annotator-rel" - category: "win|week4" - short_name: "anno" - } - builders { - name: "buildbucket/luci.chromium.ci/win-pixel-builder-rel" - category: "win|week4" - short_name: "pixel" - } - builders { - name: "buildbucket/luci.chromium.webrtc/WebRTC Chromium Win Builder" - category: "win|week4|webrtc" - } - builders { - name: "buildbucket/luci.chromium.webrtc.fyi/WebRTC Chromium FYI Win Builder" - category: "win|week4|webrtc|fyi" - short_name: "rel" - } - builders { - name: "buildbucket/luci.chromium.webrtc.fyi/WebRTC Chromium FYI Win Builder (dbg)" - category: "win|week4|webrtc|fyi" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.chromium.ci/win-swangle-x86" - category: "win|week4|swangle" - short_name: "x86" - } - builders { - name: "buildbucket/luci.chromium.ci/win-swangle-x64" - category: "win|week4|swangle" - short_name: "x64" - } - builders { - name: "buildbucket/luci.chromium.ci/win-swangle-tot-angle-x86" - category: "win|week4|swangle|angle" - short_name: "x86" - } - builders { - name: "buildbucket/luci.chromium.ci/win-swangle-tot-angle-x64" - category: "win|week4|swangle|angle" - short_name: "x64" - } - builders { - name: "buildbucket/luci.chromium.ci/win-swangle-tot-swiftshader-x86" - category: "win|week4|swangle|swift" - short_name: "x86" - } - builders { - name: "buildbucket/luci.chromium.ci/win-swangle-tot-swiftshader-x64" - category: "win|week4|swangle|swift" - short_name: "x64" - } - builders { - name: "buildbucket/luci.chromium.ci/Win x64 Builder" - category: "win|week5" - } - builders { - name: "buildbucket/luci.chromium.ci/GPU Win x64 Builder" - category: "win|week5" - short_name: "gpu" - } - builders { - name: "buildbucket/luci.chromium.ci/linux-chromeos-dbg" - category: "cros|week1" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.chromium.ci/linux-chromeos-rel" - category: "cros|week1" - short_name: "rel" - } - builders { - name: "buildbucket/luci.chromium.ci/linux-chromeos-code-coverage" - category: "cros|week1" - short_name: "code" - } - builders { - name: "buildbucket/luci.chromium.ci/Linux ChromiumOS Full" - category: "cros|week2" - short_name: "full" - } - builders { - name: "buildbucket/luci.chromium.ci/ChromiumOS ASAN Release" - category: "cros|week2" - short_name: "asan" - } - builders { - name: "buildbucket/luci.chromium.ci/Linux Chromium OS ASan LSan Builder" - category: "cros|week2" - short_name: "asan lsan" - } - builders { - name: "buildbucket/luci.chromium.ci/Linux ChromiumOS MSan Builder" - category: "cros|week2" - short_name: "msan" - } - builders { - name: "buildbucket/luci.chromium.ci/Mojo ChromiumOS" - category: "cros|week2" - short_name: "mojo" - } - builders { - name: "buildbucket/luci.chromium.ci/Libfuzzer Upload Chrome OS ASan" - category: "cros|week2" - short_name: "fuzz" - } - builders { - name: "buildbucket/luci.chromium.ci/chromeos-amd64-generic-rel" - category: "cros|week3|amd64" - short_name: "rel" - } - builders { - name: "buildbucket/luci.chromium.ci/chromeos-amd64-generic-dbg" - category: "cros|week3|amd64" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.chromium.ci/chromeos-amd64-generic-asan-rel" - category: "cros|week3|amd64" - short_name: "asan" - } - builders { - name: "buildbucket/luci.chromium.ci/chromeos-amd64-generic-cfi-thin-lto-rel" - category: "cros|week3|amd64" - short_name: "thinlto" - } - builders { - name: "buildbucket/luci.chromium.ci/chromeos-arm-generic-rel" - category: "cros|week3|arm" - short_name: "rel" - } - builders { - name: "buildbucket/luci.chromium.ci/chromeos-arm-generic-dbg" - category: "cros|week3|arm" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.chromium.ci/chromeos-kevin-rel" - category: "cros|week3|kevin" - short_name: "rel" - } - builders { - name: "buildbucket/luci.chromium.webrtc.fyi/WebRTC Chromium FYI ios-device" - category: "ios|week1a" - short_name: "dev" - } - builders { - name: "buildbucket/luci.chromium.webrtc.fyi/WebRTC Chromium FYI ios-simulator" - category: "ios|week1a" - short_name: "sim" - } - builders { - name: "buildbucket/luci.chromium.ci/ios-device" - category: "ios|week1b" - short_name: "dev" - } - builders { - name: "buildbucket/luci.chromium.ci/ios-simulator" - category: "ios|week1b|sim" - } - builders { - name: "buildbucket/luci.chromium.ci/ios-simulator-full-configs" - category: "ios|week1b|sim" - short_name: "fullconf" - } - builders { - name: "buildbucket/luci.chromium.ci/ios-simulator-noncq" - category: "ios|week1b|sim" - short_name: "noncq" - } - builders { - name: "buildbucket/luci.chromium.ci/ios13-beta-simulator" - category: "ios|week1b|ios13|beta" - short_name: "sim" - } - builders { - name: "buildbucket/luci.chromium.ci/ios13-sdk-simulator" - category: "ios|week1b|ios13|sdk" - short_name: "sim" - } - builders { - name: "buildbucket/luci.chromium.ci/ios-simulator-cronet" - category: "ios|week1c" - short_name: "cro" - } - builders { - name: "buildbucket/luci.chromium.ci/ios-simulator-cr-recipe" - category: "ios|week1c" - short_name: "crr" - } - builders { - name: "buildbucket/luci.chromium.ci/ios-webkit-tot" - category: "ios|week1c" - short_name: "webkit" - } - builders { - name: "buildbucket/luci.chromium.ci/ios13-sdk-device" - category: "ios|week1c|ios13" - short_name: "dev" - } - builders { - name: "buildbucket/luci.chromium.ci/ios-simulator-code-coverage" - category: "ios|week1d" - short_name: "code" - } - header { - oncalls { - name: "Chromium" - url: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff" - } - oncalls { - name: "Android" - url: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-android-sheriff" - } - oncalls { - name: "iOS" - url: "https://rota-ng.appspot.com/legacy/sheriff_ios.json" - } - oncalls { - name: "GPU" - url: "https://rota-ng.appspot.com/legacy/sheriff_gpu.json" - } - oncalls { - name: "Angle" - url: "https://rota-ng.appspot.com/legacy/sheriff_angle.json" - } - oncalls { - name: "Perf" - url: "https://rota-ng.appspot.com/legacy/sheriff_perf.json" - } - oncalls { - name: "Perfbot" - url: "https://rota-ng.appspot.com/legacy/sheriff_perfbot.json" - } - oncalls { - name: "Trooper" - url: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-ops-client-infra" - show_primary_secondary_labels: true - } - links { - name: "Builds" - links { - text: "continuous" - url: "https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html" - alt: "Continuous browser snapshots" - } - links { - text: "symbols" - url: "https://www.chromium.org/developers/how-tos/debugging-on-windows" - alt: "Windows Symbols" - } - links { - text: "status" - url: "https://chromium-status.appspot.com/" - alt: "Current tree status" - } - } - links { - name: "Dashboards" - links { - text: "perf" - url: "https://chromeperf.appspot.com/" - alt: "Chrome perf dashboard" - } - links { - text: "flake-portal" - url: "https://analysis.chromium.org/p/chromium/flake-portal" - alt: "New flake portal" - } - links { - text: "legacy-flakiness" - url: "https://test-results.appspot.com/dashboards/flakiness_dashboard.html" - alt: "Legacy flakiness dashboard" - } - } - links { - name: "Chromium" - links { - text: "source" - url: "https://chromium.googlesource.com/chromium/src" - alt: "Chromium source code repository" - } - links { - text: "reviews" - url: "https://chromium-review.googlesource.com" - alt: "Chromium code review tool" - } - links { - text: "bugs" - url: "https://crbug.com" - alt: "Chromium bug tracker" - } - links { - text: "coverage" - url: "https://analysis.chromium.org/p/chromium/coverage" - alt: "Chromium code coverage dashboard" - } - links { - text: "dev" - url: "https://dev.chromium.org/Home" - alt: "Chromium developer home page" - } - links { - text: "support" - url: "https://support.google.com/chrome/#topic=7438008" - alt: "Google Chrome help center" - } - } - links { - name: "Consoles" - links { - text: "android" - url: "/p/chromium/g/chromium.android" - alt: "Chromium Android console" - } - links { - text: "clang" - url: "/p/chromium/g/chromium.clang" - alt: "Chromium Clang console" - } - links { - text: "dawn" - url: "/p/chromium/g/chromium.dawn" - alt: "Chromium Dawn console" - } - links { - text: "fuzz" - url: "/p/chromium/g/chromium.fuzz" - alt: "Chromium Fuzz console" - } - links { - text: "fyi" - url: "/p/chromium/g/chromium.fyi" - alt: "Chromium FYI console" - } - links { - text: "gpu" - url: "/p/chromium/g/chromium.gpu" - alt: "Chromium GPU console" - } - links { - text: "perf" - url: "/p/chrome/g/chrome.perf/console" - alt: "Chromium Perf console" - } - links { - text: "perf.fyi" - url: "/p/chrome/g/chrome.perf.fyi/console" - alt: "Chromium Perf FYI console" - } - links { - text: "swangle" - url: "/p/chromium/g/chromium.swangle" - alt: "Chromium SWANGLE console" - } - links { - text: "webrtc" - url: "/p/chromium/g/chromium.webrtc" - alt: "Chromium WebRTC console" - } - links { - text: "chromiumos" - url: "/p/chromium/g/chromium.chromiumos" - alt: "ChromiumOS console" - } - } - links { - name: "Branch Consoles" - links { - text: "m86" - url: "/p/chromium-m86/g/main/console" - alt: "Beta branch console" - } - links { - text: "m85" - url: "/p/chromium/g/main-m85/console" - alt: "Stable branch console" - } - links { - text: "trunk" - url: "/p/chromium/g/main/console" - alt: "Trunk (ToT) console" - } - } - links { - name: "Tryservers" - links { - text: "android" - url: "/p/chromium/g/tryserver.chromium.android/builders" - alt: "Android" - } - links { - text: "angle" - url: "/p/chromium/g/tryserver.chromium.angle/builders" - alt: "Angle" - } - links { - text: "blink" - url: "/p/chromium/g/tryserver.blink/builders" - alt: "Blink" - } - links { - text: "chrome" - url: "/p/chrome/g/tryserver.chrome/builders" - alt: "Chrome" - } - links { - text: "chromiumos" - url: "/p/chromium/g/tryserver.chromium.chromiumos/builders" - alt: "ChromiumOS" - } - links { - text: "linux" - url: "/p/chromium/g/tryserver.chromium.linux/builders" - alt: "Linux" - } - links { - text: "mac" - url: "/p/chromium/g/tryserver.chromium.mac/builders" - alt: "Mac" - } - links { - text: "swangle" - url: "/p/chromium/g/tryserver.chromium.swangle/builders" - alt: "SWANGLE" - } - links { - text: "win" - url: "/p/chromium/g/tryserver.chromium.win/builders" - alt: "Win" - } - } - links { - name: "Navigate" - links { - text: "about" - url: "http://dev.chromium.org/developers/testing/chromium-build-infrastructure/tour-of-the-chromium-buildbot" - alt: "Tour of the console" - } - links { - text: "customize" - url: "https://chromium.googlesource.com/chromium/src/+/master/infra/config/luci-milo.cfg" - alt: "Customize this console" - } - } - console_groups { - title { - text: "Tree Closers" - url: "https://chromium-status.appspot.com/" - } - console_ids: "chromium/chromium" - console_ids: "chromium/chromium.win" - console_ids: "chromium/chromium.mac" - console_ids: "chromium/chromium.linux" - console_ids: "chromium/chromium.chromiumos" - console_ids: "chrome/chrome" - console_ids: "chromium/chromium.memory" - console_ids: "chromium/chromium.gpu" - } - console_groups { - console_ids: "chromium/chromium.android" - console_ids: "chrome/chrome.perf" - console_ids: "chromium/chromium.gpu.fyi" - console_ids: "chromium/chromium.swangle" - console_ids: "chromium/chromium.fuzz" - } - tree_status_host: "chromium-status.appspot.com" - } - include_experimental_builds: true -} -consoles { id: "chromium.gpu" name: "chromium.gpu" repo_url: "https://chromium.googlesource.com/chromium/src" @@ -13885,6 +12459,9 @@ name: "buildbucket/luci.chromium.try/linux-chromeos-rel" } builders { + name: "buildbucket/luci.chromium.try/linux-inverse-fieldtrials-fyi-rel" + } + builders { name: "buildbucket/luci.chromium.try/linux-libfuzzer-asan-rel" } builders { @@ -14604,6 +13181,9 @@ name: "buildbucket/luci.chromium.try/linux-gcc-rel" } builders { + name: "buildbucket/luci.chromium.try/linux-inverse-fieldtrials-fyi-rel" + } + builders { name: "buildbucket/luci.chromium.try/linux-lacros-fyi-rel" } builders {
diff --git a/infra/config/generated/luci-scheduler.cfg b/infra/config/generated/luci-scheduler.cfg index 0584895..1d6b86b 100644 --- a/infra/config/generated/luci-scheduler.cfg +++ b/infra/config/generated/luci-scheduler.cfg
@@ -9030,6 +9030,16 @@ } } job { + id: "ci-linux-inverse-fieldtrials-fyi-rel" + realm: "ci" + acl_sets: "ci" + buildbucket { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "linux-inverse-fieldtrials-fyi-rel" + } +} +job { id: "ci-linux-lacros-builder-fyi-rel" realm: "ci" acl_sets: "ci" @@ -11274,6 +11284,16 @@ } } job { + id: "linux-inverse-fieldtrials-fyi-rel" + realm: "ci" + acl_sets: "ci" + buildbucket { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "linux-inverse-fieldtrials-fyi-rel" + } +} +job { id: "linux-lacros-builder-fyi-rel" realm: "ci" acl_sets: "ci" @@ -12416,6 +12436,7 @@ triggers: "linux-chromium-tests-staging-builder" triggers: "linux-fieldtrial-rel" triggers: "linux-gcc-rel" + triggers: "linux-inverse-fieldtrials-fyi-rel" triggers: "linux-lacros-builder-fyi-rel" triggers: "linux-lacros-builder-rel" triggers: "ci-linux-official"
diff --git a/infra/config/subprojects/chromium/ci.star b/infra/config/subprojects/chromium/ci.star index f7d2279..270a095e 100644 --- a/infra/config/subprojects/chromium/ci.star +++ b/infra/config/subprojects/chromium/ci.star
@@ -2515,6 +2515,13 @@ ) ci.fyi_builder( + name = "linux-inverse-fieldtrials-fyi-rel", + console_view_entry = ci.console_view_entry( + category = "linux", + ), +) + +ci.fyi_builder( name = "linux-fieldtrial-rel", console_view_entry = ci.console_view_entry( category = "linux",
diff --git a/infra/config/subprojects/chromium/consoles/luci.chromium.try.star b/infra/config/subprojects/chromium/consoles/luci.chromium.try.star index 3a9f060..10dc2c8 100644 --- a/infra/config/subprojects/chromium/consoles/luci.chromium.try.star +++ b/infra/config/subprojects/chromium/consoles/luci.chromium.try.star
@@ -115,6 +115,7 @@ "try/linux-blink-heap-concurrent-marking-tsan-rel", "try/linux-blink-heap-verification-try", "try/linux-chromeos-rel", + "try/linux-inverse-fieldtrials-fyi-rel", "try/linux-libfuzzer-asan-rel", "try/linux-ozone-rel", "try/linux_android_dbg_ng",
diff --git a/infra/config/subprojects/chromium/try.star b/infra/config/subprojects/chromium/try.star index 007312d..b8eb2fd 100644 --- a/infra/config/subprojects/chromium/try.star +++ b/infra/config/subprojects/chromium/try.star
@@ -852,6 +852,10 @@ ) try_.chromium_linux_builder( + name = "linux-inverse-fieldtrials-fyi-rel", +) + +try_.chromium_linux_builder( name = "linux-lacros-fyi-rel", )
diff --git a/infra/config/subprojects/goma/consoles/chromium.goma.migration.star b/infra/config/subprojects/goma/consoles/chromium.goma.migration.star deleted file mode 100644 index 091df29..0000000 --- a/infra/config/subprojects/goma/consoles/chromium.goma.migration.star +++ /dev/null
@@ -1,1173 +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. - -# These are used for monitoring builders that have recently been migrated to -# Goma RBE (See crbug.com/950413). -luci.console_view( - name = "chromium.goma.migration", - header = "//chromium-header.textpb", - include_experimental_builds = True, - repo = "https://chromium.googlesource.com/chromium/src", - entries = [ - luci.console_view_entry( - builder = "ci/VR Linux", - category = "week1|linux", - short_name = "vr", - ), - luci.console_view_entry( - builder = "ci/Mojo Linux", - category = "week1|linux", - short_name = "mojo", - ), - luci.console_view_entry( - builder = "ci/Linux Builder (dbg)", - category = "week1|linux|dbg", - ), - luci.console_view_entry( - builder = "ci/Linux Builder (dbg)(32)", - category = "week1|linux|dbg", - short_name = "32bit", - ), - luci.console_view_entry( - builder = "ci/Linux CFI", - category = "week1|linux|cfi", - ), - luci.console_view_entry( - builder = "ci/Linux MSan Builder", - category = "week1|linux", - short_name = "msan", - ), - luci.console_view_entry( - builder = "ci/Afl Upload Linux ASan", - category = "week1|linux", - short_name = "afl-asan", - ), - luci.console_view_entry( - builder = "ci/WebKit Linux ASAN", - category = "week1|linux|webkit", - short_name = "asan", - ), - luci.console_view_entry( - builder = "ci/WebKit Linux Leak", - category = "week1|linux|webkit", - short_name = "leak", - ), - luci.console_view_entry( - builder = "ci/WebKit Linux MSAN", - category = "week1|linux|webkit", - short_name = "msan", - ), - luci.console_view_entry( - builder = "ci/Android FYI 32 Vk Release (Pixel 2)", - category = "week2a|android|32", - short_name = "p2", - ), - luci.console_view_entry( - builder = "ci/Android FYI 32 dEQP Vk Release (Pixel 2)", - category = "week2a|android|32deqp", - short_name = "p2", - ), - luci.console_view_entry( - builder = "ci/Android FYI 64 Vk Release (Pixel 2)", - category = "week2a|android|64", - short_name = "p2", - ), - luci.console_view_entry( - builder = "ci/Android FYI 64 dEQP Vk Release (Pixel 2)", - category = "week2a|android|64deqp", - short_name = "p2", - ), - luci.console_view_entry( - builder = "ci/Android FYI Release (NVIDIA Shield TV)", - category = "week2a|android|rel", - short_name = "shdtv", - ), - luci.console_view_entry( - builder = "ci/Android FYI Release (Nexus 5)", - category = "week2a|android|rel", - short_name = "n5", - ), - luci.console_view_entry( - builder = "ci/Android FYI Release (Nexus 5X)", - category = "week2a|android|rel", - short_name = "n5x", - ), - luci.console_view_entry( - builder = "ci/Android FYI Release (Nexus 6)", - category = "week2a|android|rel", - short_name = "n6", - ), - luci.console_view_entry( - builder = "ci/Android FYI Release (Nexus 6P)", - category = "week2a|android|rel", - short_name = "n6p", - ), - luci.console_view_entry( - builder = "ci/Android FYI Release (Nexus 9)", - category = "week2a|android|rel", - short_name = "n9", - ), - luci.console_view_entry( - builder = "ci/Android FYI Release (Pixel 2)", - category = "week2a|android|rel", - short_name = "p2", - ), - luci.console_view_entry( - builder = "ci/Android FYI dEQP Release (Nexus 5X)", - category = "week2a|android|deqp", - short_name = "n5x", - ), - luci.console_view_entry( - builder = "ci/Deterministic Android", - category = "week2a|android|det", - ), - luci.console_view_entry( - builder = "ci/Deterministic Android (dbg)", - category = "week2a|android|det", - short_name = "dbg", - ), - luci.console_view_entry( - builder = "webrtc.fyi/WebRTC Chromium FYI Android Builder", - category = "week2b|android|release", - short_name = "32", - ), - luci.console_view_entry( - builder = "webrtc.fyi/WebRTC Chromium FYI Android Builder (dbg)", - category = "week2b|android|debug|builder", - short_name = "32", - ), - luci.console_view_entry( - builder = "webrtc.fyi/WebRTC Chromium FYI Android Builder ARM64 (dbg)", - category = "week2b|android|debug|builder", - short_name = "64", - ), - luci.console_view_entry( - builder = "webrtc.fyi/WebRTC Chromium FYI Linux Builder", - category = "week2b|linux|release", - short_name = "bld", - ), - luci.console_view_entry( - builder = "webrtc.fyi/WebRTC Chromium FYI Linux Builder (dbg)", - category = "week2b|linux|debug", - short_name = "bld", - ), - luci.console_view_entry( - builder = "webrtc.fyi/WebRTC Chromium FYI Mac Builder", - category = "week2b|mac|release", - short_name = "bld", - ), - luci.console_view_entry( - builder = "webrtc.fyi/WebRTC Chromium FYI Mac Builder (dbg)", - category = "week2b|mac|debug", - short_name = "bld", - ), - luci.console_view_entry( - builder = "webrtc/WebRTC Chromium Android Builder", - category = "week2b|android", - short_name = "bld", - ), - luci.console_view_entry( - builder = "webrtc/WebRTC Chromium Linux Builder", - category = "week2b|linux", - short_name = "bld", - ), - luci.console_view_entry( - builder = "webrtc/WebRTC Chromium Mac Builder", - category = "week2b|mac", - short_name = "bld", - ), - luci.console_view_entry( - builder = "ci/Mac ASAN Release", - category = "week2c|mac|asan", - ), - luci.console_view_entry( - builder = "ci/Mac ASAN Release Media", - category = "week2c|mac|asan", - short_name = "media", - ), - luci.console_view_entry( - builder = "ci/Mac ASan 64 Builder", - category = "week2c|mac|asan", - short_name = "64", - ), - luci.console_view_entry( - builder = "ci/Libfuzzer Upload Mac ASan", - category = "week2c|mac|asan", - short_name = "fuzz", - ), - luci.console_view_entry( - builder = "ci/Android CFI", - category = "week2c|android", - short_name = "cfi", - ), - luci.console_view_entry( - builder = "ci/Site Isolation Android", - category = "week2c|android", - short_name = "isolate", - ), - luci.console_view_entry( - builder = "ci/Mojo Android", - category = "week2c|android", - short_name = "mojo", - ), - luci.console_view_entry( - builder = "ci/Android x64 Builder (dbg)", - category = "week2c|android|dbg", - short_name = "x64", - ), - luci.console_view_entry( - builder = "ci/Android x86 Builder (dbg)", - category = "week2c|android|dbg", - short_name = "x86", - ), - luci.console_view_entry( - builder = "ci/Android WebView L (dbg)", - category = "week2c|android|dbg|webview", - short_name = "l", - ), - luci.console_view_entry( - builder = "ci/Android WebView M (dbg)", - category = "week2c|android|dbg|webview", - short_name = "m", - ), - luci.console_view_entry( - builder = "ci/Android WebView N (dbg)", - category = "week2c|android|dbg|webview", - short_name = "n", - ), - luci.console_view_entry( - builder = "ci/Android WebView O (dbg)", - category = "week2c|android|dbg|webview", - short_name = "o", - ), - luci.console_view_entry( - builder = "ci/Android WebView P FYI (rel)", - category = "week2c|android|rel|webview", - short_name = "p", - ), - luci.console_view_entry( - builder = "ci/Dawn Linux x64 Builder", - category = "week2d|linux|dawn", - ), - luci.console_view_entry( - builder = "ci/Dawn Linux x64 DEPS Builder", - category = "week2d|linux|dawn", - short_name = "deps", - ), - luci.console_view_entry( - builder = "ci/GPU FYI Linux Builder", - category = "week2d|linux|gpu|fyi", - ), - luci.console_view_entry( - builder = "ci/GPU FYI Linux Builder (dbg)", - category = "week2d|linux|gpu|fyi", - short_name = "dbg", - ), - luci.console_view_entry( - builder = "ci/GPU FYI Linux Ozone Builder", - category = "week2d|linux|gpu|fyi", - short_name = "ozone", - ), - luci.console_view_entry( - builder = "ci/GPU FYI Linux dEQP Builder", - category = "week2d|linux|gpu|fyi", - short_name = "deqp", - ), - luci.console_view_entry( - builder = "ci/Linux FYI GPU TSAN Release", - category = "week2d|linux|gpu|fyi", - short_name = "tsan", - ), - luci.console_view_entry( - builder = "ci/GPU Linux Builder (dbg)", - category = "week2d|linux|gpu", - short_name = "dbg", - ), - luci.console_view_entry( - builder = "ci/Linux Viz", - category = "week2d|linux", - short_name = "viz", - ), - luci.console_view_entry( - builder = "ci/Linux remote_run Builder", - category = "week2d|linux", - short_name = "rem", - ), - luci.console_view_entry( - builder = "ci/Closure Compilation Linux", - category = "week2d|linux", - short_name = "clsr", - ), - luci.console_view_entry( - builder = "ci/Deterministic Linux", - category = "week2d|linux|det", - ), - luci.console_view_entry( - builder = "ci/Deterministic Linux (dbg)", - category = "week2d|linux|det", - short_name = "dbg", - ), - luci.console_view_entry( - builder = "ci/Dawn Mac x64 Builder", - category = "week2d|mac|dawn", - ), - luci.console_view_entry( - builder = "ci/Dawn Mac x64 DEPS Builder", - category = "week2d|mac|dawn", - short_name = "deps", - ), - luci.console_view_entry( - builder = "ci/GPU FYI Mac Builder", - category = "week2d|mac|gpu|fyi", - ), - luci.console_view_entry( - builder = "ci/GPU FYI Mac Builder (dbg)", - category = "week2d|mac|gpu|fyi", - short_name = "dbg", - ), - luci.console_view_entry( - builder = "ci/GPU FYI Mac dEQP Builder", - category = "week2d|mac|gpu|fyi", - short_name = "deqp", - ), - luci.console_view_entry( - builder = "ci/Mac FYI GPU ASAN Release", - category = "week2d|mac|gpu|fyi", - short_name = "asan", - ), - luci.console_view_entry( - builder = "ci/GPU Mac Builder (dbg)", - category = "week2d|mac|gpu", - short_name = "dbg", - ), - luci.console_view_entry( - builder = "ci/Mac deterministic", - category = "week2d|mac|det", - ), - luci.console_view_entry( - builder = "ci/Mac deterministic (dbg)", - category = "week2d|mac|det", - short_name = "dbg", - ), - luci.console_view_entry( - builder = "ci/Linux Builder", - category = "week2.5|linux", - ), - luci.console_view_entry( - builder = "ci/GPU Linux Builder", - category = "week2.5|linux", - short_name = "gpu", - ), - luci.console_view_entry( - builder = "ci/linux-ozone-rel", - category = "week3a|linux", - short_name = "ozone", - ), - luci.console_view_entry( - builder = "ci/linux-annotator-rel", - category = "week3a|linux", - short_name = "anno", - ), - luci.console_view_entry( - builder = "ci/linux-code-coverage", - category = "week3a|linux", - short_name = "code", - ), - luci.console_view_entry( - builder = "ci/linux-blink-animation-use-time-delta", - category = "week3a|linux|blink", - short_name = "anim", - ), - luci.console_view_entry( - builder = "ci/linux-blink-heap-concurrent-marking-tsan-rel", - category = "week3a|linux|blink", - short_name = "tsan", - ), - luci.console_view_entry( - builder = "ci/linux-blink-heap-verification", - category = "week3a|linux|blink", - short_name = "ver", - ), - luci.console_view_entry( - builder = "ci/linux-chromium-tests-staging-builder", - category = "week3a|linux", - short_name = "crtests", - ), - luci.console_view_entry( - builder = "ci/android-cronet-arm-dbg", - category = "week3b|android|cronet|arm", - short_name = "dbg", - ), - luci.console_view_entry( - builder = "ci/android-cronet-arm-rel", - category = "week3b|android|cronet|arm", - ), - luci.console_view_entry( - builder = "ci/android-cronet-asan-arm-rel", - category = "week3b|android|cronet|arm", - short_name = "asan", - ), - luci.console_view_entry( - builder = "ci/android-cronet-kitkat-arm-rel", - category = "week3b|android|cronet|arm", - short_name = "kkat", - ), - luci.console_view_entry( - builder = "ci/android-cronet-lollipop-arm-rel", - category = "week3b|android|cronet|arm", - short_name = "lpop", - ), - luci.console_view_entry( - builder = "ci/android-cronet-arm64-rel", - category = "week3b|android|cronet|arm64", - ), - luci.console_view_entry( - builder = "ci/android-cronet-arm64-dbg", - category = "week3b|android|cronet|arm64", - short_name = "dbg", - ), - luci.console_view_entry( - builder = "ci/android-cronet-marshmallow-arm64-rel", - category = "week3b|android|cronet|arm64", - short_name = "marsh", - ), - luci.console_view_entry( - builder = "ci/android-cronet-marshmallow-arm64-perf-rel", - category = "week3b|android|cronet|arm64", - short_name = "perf", - ), - luci.console_view_entry( - builder = "ci/android-cronet-x86-rel", - category = "week3b|android|cronet|x86", - ), - luci.console_view_entry( - builder = "ci/android-cronet-x86-dbg", - category = "week3b|android|cronet|x86", - short_name = "dbg", - ), - luci.console_view_entry( - builder = "ci/android-incremental-dbg", - category = "week3b|android", - short_name = "inc", - ), - luci.console_view_entry( - builder = "ci/android-mojo-webview-rel", - category = "week3b|android", - short_name = "mojo", - ), - luci.console_view_entry( - builder = "ci/android-pie-arm64-dbg", - category = "week3b|linux", - short_name = "pie", - ), - luci.console_view_entry( - builder = "ci/mac-code-coverage", - category = "week3c|mac", - short_name = "code", - ), - luci.console_view_entry( - builder = "ci/mac-hermetic-upgrade-rel", - category = "week3c|mac", - short_name = "herm", - ), - luci.console_view_entry( - builder = "ci/mac-mojo-rel", - category = "week3c|mac", - short_name = "mojo", - ), - luci.console_view_entry( - builder = "ci/mac-osxbeta-rel", - category = "week3c|mac", - short_name = "osx", - ), - luci.console_view_entry( - builder = "ci/Mac Builder", - category = "week3c|mac", - ), - luci.console_view_entry( - builder = "ci/Mac Builder (dbg)", - category = "week3c|mac", - short_name = "dbg", - ), - luci.console_view_entry( - builder = "ci/GPU Mac Builder", - category = "week3c|mac", - short_name = "gpu", - ), - luci.console_view_entry( - builder = "ci/Libfuzzer Upload Linux ASan", - category = "week4|linux", - short_name = "asan", - ), - luci.console_view_entry( - builder = "ci/Libfuzzer Upload Linux ASan Debug", - category = "week4|linux", - short_name = "dbg", - ), - luci.console_view_entry( - builder = "ci/Libfuzzer Upload Linux MSan", - category = "week4|linux", - short_name = "msan", - ), - luci.console_view_entry( - builder = "ci/Libfuzzer Upload Linux UBSan", - category = "week4|linux", - short_name = "ubsan", - ), - luci.console_view_entry( - builder = "ci/Libfuzzer Upload Linux V8-ARM64 ASan", - category = "week4|linux|v8arm", - short_name = "asan", - ), - luci.console_view_entry( - builder = "ci/Libfuzzer Upload Linux V8-ARM64 ASan Debug", - category = "week4|linux|v8arm", - short_name = "dbg", - ), - luci.console_view_entry( - builder = "ci/Libfuzzer Upload Linux32 ASan", - category = "week4|linux32", - short_name = "asan", - ), - luci.console_view_entry( - builder = "ci/Libfuzzer Upload Linux32 ASan Debug", - category = "week4|linux32", - short_name = "dbg", - ), - luci.console_view_entry( - builder = "ci/Libfuzzer Upload Linux32 V8-ARM ASan", - category = "week4|linux32|v8arm", - short_name = "asan", - ), - luci.console_view_entry( - builder = "ci/Libfuzzer Upload Linux32 V8-ARM ASan Debug", - category = "week4|linux32|v8arm", - short_name = "dbg", - ), - luci.console_view_entry( - builder = "ci/ASan Debug (32-bit x86 with V8-ARM)", - category = "week5|asan", - short_name = "dbg", - ), - luci.console_view_entry( - builder = "ci/ASan Release (32-bit x86 with V8-ARM)", - category = "week5|asan", - short_name = "rel", - ), - luci.console_view_entry( - builder = "ci/ASan Release Media (32-bit x86 with V8-ARM)", - category = "week5|asan", - short_name = "media", - ), - luci.console_view_entry( - builder = "ci/ASAN Debug", - category = "week6|asan", - short_name = "dbg", - ), - luci.console_view_entry( - builder = "ci/ASAN Release", - category = "week6|asan", - short_name = "rel", - ), - luci.console_view_entry( - builder = "ci/ASAN Release Media", - category = "week6|asan", - short_name = "media", - ), - luci.console_view_entry( - builder = "ci/MSAN Release (chained origins)", - category = "week7|msan", - short_name = "chain", - ), - luci.console_view_entry( - builder = "ci/MSAN Release (no origins)", - category = "week7|msan", - short_name = "none", - ), - luci.console_view_entry( - builder = "ci/TSAN Release", - category = "week8|tsan", - short_name = "rel", - ), - luci.console_view_entry( - builder = "ci/TSAN Debug", - category = "week8|tsan", - short_name = "dbg", - ), - luci.console_view_entry( - builder = "ci/UBSan Release", - category = "week9|ubsan", - ), - luci.console_view_entry( - builder = "ci/UBSan vptr Release", - category = "week9|ubsan|vptr", - short_name = "rel", - ), - luci.console_view_entry( - builder = "ci/UBSanVptr Linux", - category = "week9|ubsan|vptr", - short_name = "lnx", - ), - luci.console_view_entry( - builder = "ci/Cast Android (dbg)", - category = "week10|android", - ), - luci.console_view_entry( - builder = "ci/Cast Audio Linux", - category = "week10|linux", - short_name = "audio", - ), - luci.console_view_entry( - builder = "ci/Cast Linux", - category = "week10|linux", - ), - luci.console_view_entry( - builder = "ci/Fuchsia ARM64", - category = "week11|fuchsia|arm64", - ), - luci.console_view_entry( - builder = "ci/fuchsia-arm64-cast", - category = "week11|fuchsia|arm64", - short_name = "cast", - ), - luci.console_view_entry( - builder = "ci/Fuchsia x64", - category = "week11|fuchsia|x64", - ), - luci.console_view_entry( - builder = "ci/fuchsia-x64-cast", - category = "week11|fuchsia|x64", - short_name = "cast", - ), - luci.console_view_entry( - builder = "ci/fuchsia-fyi-arm64-rel", - category = "week11|fuchsia|fyi", - short_name = "arm64", - ), - luci.console_view_entry( - builder = "ci/fuchsia-fyi-x64-dbg", - category = "week11|fuchsia|fyi", - short_name = "x64 dbg", - ), - luci.console_view_entry( - builder = "ci/fuchsia-fyi-x64-rel", - category = "week11|fuchsia|fyi", - short_name = "x64 rel", - ), - luci.console_view_entry( - builder = "ci/android-marshmallow-arm64-rel", - category = "week13|android", - short_name = "marsh", - ), - luci.console_view_entry( - builder = "ci/Android Release (Nexus 5X)", - category = "week13|android", - short_name = "n5x", - ), - luci.console_view_entry( - builder = "ci/Linux ASan LSan Builder", - category = "week14a|linux", - short_name = "asanlsan", - ), - luci.console_view_entry( - builder = "ci/Linux TSan Builder", - category = "week14a|linux", - short_name = "tsan", - ), - luci.console_view_entry( - builder = "ci/Android ASAN (dbg)", - category = "week14b|android", - short_name = "asanlsan", - ), - luci.console_view_entry( - builder = "ci/Android arm Builder (dbg)", - category = "week14b|android", - short_name = "tsan", - ), - luci.console_view_entry( - builder = "ci/Android arm64 Builder (dbg)", - category = "week14b|android", - short_name = "tsan", - ), - luci.console_view_entry( - builder = "ci/fuchsia-x64-dbg", - category = "week15a|fuchsia", - short_name = "x64dbg", - ), - luci.console_view_entry( - builder = "ci/linux-archive-dbg", - category = "week15a|linux|archive", - short_name = "dbg", - ), - luci.console_view_entry( - builder = "ci/linux-archive-rel", - category = "week15a|linux|archive", - short_name = "rel", - ), - luci.console_view_entry( - builder = "ci/linux-bfcache-rel", - category = "week15a|linux", - short_name = "bfc", - ), - luci.console_view_entry( - builder = "ci/linux-fieldtrial-rel", - category = "week15a|linux", - short_name = "field", - ), - luci.console_view_entry( - builder = "ci/android-archive-rel", - category = "week15b|android|archive", - short_name = "rel", - ), - luci.console_view_entry( - builder = "ci/android-archive-dbg", - category = "week15b|android|archive", - short_name = "dbg", - ), - luci.console_view_entry( - builder = "ci/android-asan", - category = "week15b|android", - short_name = "asan", - ), - luci.console_view_entry( - builder = "ci/android-bfcache-rel", - category = "week15b|android", - short_name = "bfc", - ), - luci.console_view_entry( - builder = "ci/android-code-coverage", - category = "week15b|android", - short_name = "code", - ), - luci.console_view_entry( - builder = "ci/android-pie-arm64-rel", - category = "week15b|android|pie", - short_name = "arm64", - ), - luci.console_view_entry( - builder = "ci/android-pie-x86-rel", - category = "week15b|android|pie", - short_name = "x86", - ), - luci.console_view_entry( - builder = "ci/GPU FYI Perf Android 64 Builder", - category = "week15b|android|gpu", - short_name = "perf64", - ), - luci.console_view_entry( - builder = "ci/mac-archive-rel", - category = "week15b|mac|archive", - short_name = "rel", - ), - luci.console_view_entry( - builder = "ci/mac-archive-dbg", - category = "week15b|mac|archive", - short_name = "dbg", - ), - luci.console_view_entry( - builder = "ci/android-marshmallow-x86-rel-non-cq", - category = "week16b", - short_name = "marsh", - ), - luci.console_view_entry( - builder = "ci/Android FYI 64 Perf (Pixel 2)", - category = "week16b", - short_name = "pxl2", - ), - luci.console_view_entry( - builder = "ci/linux-swangle-tot-angle-x64", - category = "week17|swangle|angle", - short_name = "x64", - ), - luci.console_view_entry( - builder = "ci/linux-swangle-tot-angle-x86", - category = "week17|swangle|angle", - short_name = "x86", - ), - luci.console_view_entry( - builder = "ci/linux-swangle-tot-swiftshader-x64", - category = "week17|swangle|swift", - short_name = "x64", - ), - luci.console_view_entry( - builder = "ci/linux-swangle-tot-swiftshader-x86", - category = "week17|swangle|swift", - short_name = "x86", - ), - luci.console_view_entry( - builder = "ci/linux-swangle-x64", - category = "week17|swangle", - short_name = "x64", - ), - luci.console_view_entry( - builder = "ci/linux-swangle-x86", - category = "week17|swangle", - short_name = "x86", - ), - luci.console_view_entry( - builder = "ci/android-code-coverage-native", - category = "misc|android", - ), - luci.console_view_entry( - builder = "ci/Win ASan Release", - category = "win|week1|asan", - ), - luci.console_view_entry( - builder = "ci/Win ASan Release Media", - category = "win|week1|asan", - short_name = "media", - ), - luci.console_view_entry( - builder = "ci/win10-code-coverage", - category = "win|week1.1", - short_name = "code", - ), - luci.console_view_entry( - builder = "ci/Win x64 Builder (dbg)", - category = "win|week1.5", - short_name = "dbg", - ), - luci.console_view_entry( - builder = "ci/win-archive-dbg", - category = "win|week1.5|archive", - short_name = "dbg", - ), - luci.console_view_entry( - builder = "ci/win-archive-rel", - category = "win|week1.5|archive", - short_name = "rel", - ), - luci.console_view_entry( - builder = "ci/Dawn Win10 x64 Builder", - category = "win|week2|dawn", - ), - luci.console_view_entry( - builder = "ci/Dawn Win10 x64 DEPS Builder", - category = "win|week2|dawn", - short_name = "deps", - ), - luci.console_view_entry( - builder = "ci/GPU Win x64 Builder (dbg)", - category = "win|week2|gpu", - short_name = "dbg", - ), - luci.console_view_entry( - builder = "ci/GPU FYI XR Win x64 Builder", - category = "win|week2|gpu|fyi", - short_name = "xr", - ), - luci.console_view_entry( - builder = "ci/GPU FYI Win x64 dEQP Builder", - category = "win|week2|gpu|fyi", - short_name = "deqp", - ), - luci.console_view_entry( - builder = "ci/GPU FYI Win x64 DX12 Vulkan Builder", - category = "win|week2|gpu|fyi|dx12", - short_name = "rel", - ), - luci.console_view_entry( - builder = "ci/GPU FYI Win x64 DX12 Vulkan Builder (dbg)", - category = "win|week2|gpu|fyi|dx12", - short_name = "dbg", - ), - luci.console_view_entry( - builder = "ci/GPU FYI Win x64 Builder", - category = "win|week2|gpu|fyi", - short_name = "rel", - ), - luci.console_view_entry( - builder = "ci/GPU FYI Win x64 Builder (dbg)", - category = "win|week2|gpu|fyi", - short_name = "dbg", - ), - luci.console_view_entry( - builder = "ci/Win Builder", - category = "win|week3", - short_name = "rel", - ), - luci.console_view_entry( - builder = "ci/Win Builder (dbg)", - category = "win|week3", - short_name = "dbg", - ), - luci.console_view_entry( - builder = "ci/GPU FYI Win Builder", - category = "win|week3|gpu|fyi", - short_name = "rel", - ), - luci.console_view_entry( - builder = "ci/GPU FYI Win Builder (dbg)", - category = "win|week3|gpu|fyi", - short_name = "dbg", - ), - luci.console_view_entry( - builder = "ci/GPU FYI Win dEQP Builder", - category = "win|week3|gpu|fyi", - short_name = "deqp", - ), - luci.console_view_entry( - builder = "ci/Dawn Win10 x86 Builder", - category = "win|week3|dawn", - short_name = "rel", - ), - luci.console_view_entry( - builder = "ci/Dawn Win10 x86 DEPS Builder", - category = "win|week3|dawn", - short_name = "deps", - ), - luci.console_view_entry( - builder = "ci/win32-archive-rel", - category = "win|week4|win32", - short_name = "rel", - ), - luci.console_view_entry( - builder = "ci/win32-archive-dbg", - category = "win|week4|win32", - short_name = "dbg", - ), - luci.console_view_entry( - builder = "ci/win32-arm64-rel", - category = "win|week4|win32", - short_name = "arm", - ), - luci.console_view_entry( - builder = "ci/Libfuzzer Upload Windows ASan", - category = "win|week4", - short_name = "libfuzzer", - ), - luci.console_view_entry( - builder = "ci/Windows deterministic", - category = "win|week4", - short_name = "det", - ), - luci.console_view_entry( - builder = "ci/Mojo Windows", - category = "win|week4", - short_name = "mojo", - ), - luci.console_view_entry( - builder = "ci/win-celab-builder-rel", - category = "win|week4", - short_name = "celab", - ), - luci.console_view_entry( - builder = "ci/win-asan", - category = "win|week4", - short_name = "asan", - ), - luci.console_view_entry( - builder = "ci/Win 10 Fast Ring", - category = "win|week4", - short_name = "fastring", - ), - luci.console_view_entry( - builder = "ci/win-annotator-rel", - category = "win|week4", - short_name = "anno", - ), - luci.console_view_entry( - builder = "ci/win-pixel-builder-rel", - category = "win|week4", - short_name = "pixel", - ), - luci.console_view_entry( - builder = "webrtc/WebRTC Chromium Win Builder", - category = "win|week4|webrtc", - ), - luci.console_view_entry( - builder = "webrtc.fyi/WebRTC Chromium FYI Win Builder", - category = "win|week4|webrtc|fyi", - short_name = "rel", - ), - luci.console_view_entry( - builder = "webrtc.fyi/WebRTC Chromium FYI Win Builder (dbg)", - category = "win|week4|webrtc|fyi", - short_name = "dbg", - ), - luci.console_view_entry( - builder = "ci/win-swangle-x86", - category = "win|week4|swangle", - short_name = "x86", - ), - luci.console_view_entry( - builder = "ci/win-swangle-x64", - category = "win|week4|swangle", - short_name = "x64", - ), - luci.console_view_entry( - builder = "ci/win-swangle-tot-angle-x86", - category = "win|week4|swangle|angle", - short_name = "x86", - ), - luci.console_view_entry( - builder = "ci/win-swangle-tot-angle-x64", - category = "win|week4|swangle|angle", - short_name = "x64", - ), - luci.console_view_entry( - builder = "ci/win-swangle-tot-swiftshader-x86", - category = "win|week4|swangle|swift", - short_name = "x86", - ), - luci.console_view_entry( - builder = "ci/win-swangle-tot-swiftshader-x64", - category = "win|week4|swangle|swift", - short_name = "x64", - ), - luci.console_view_entry( - builder = "ci/Win x64 Builder", - category = "win|week5", - ), - luci.console_view_entry( - builder = "ci/GPU Win x64 Builder", - category = "win|week5", - short_name = "gpu", - ), - luci.console_view_entry( - builder = "ci/linux-chromeos-dbg", - category = "cros|week1", - short_name = "dbg", - ), - luci.console_view_entry( - builder = "ci/linux-chromeos-rel", - category = "cros|week1", - short_name = "rel", - ), - luci.console_view_entry( - builder = "ci/linux-chromeos-code-coverage", - category = "cros|week1", - short_name = "code", - ), - luci.console_view_entry( - builder = "ci/Linux ChromiumOS Full", - category = "cros|week2", - short_name = "full", - ), - luci.console_view_entry( - builder = "ci/ChromiumOS ASAN Release", - category = "cros|week2", - short_name = "asan", - ), - luci.console_view_entry( - builder = "ci/Linux Chromium OS ASan LSan Builder", - category = "cros|week2", - short_name = "asan lsan", - ), - luci.console_view_entry( - builder = "ci/Linux ChromiumOS MSan Builder", - category = "cros|week2", - short_name = "msan", - ), - luci.console_view_entry( - builder = "ci/Mojo ChromiumOS", - category = "cros|week2", - short_name = "mojo", - ), - luci.console_view_entry( - builder = "ci/Libfuzzer Upload Chrome OS ASan", - category = "cros|week2", - short_name = "fuzz", - ), - luci.console_view_entry( - builder = "ci/chromeos-amd64-generic-rel", - category = "cros|week3|amd64", - short_name = "rel", - ), - luci.console_view_entry( - builder = "ci/chromeos-amd64-generic-dbg", - category = "cros|week3|amd64", - short_name = "dbg", - ), - luci.console_view_entry( - builder = "ci/chromeos-amd64-generic-asan-rel", - category = "cros|week3|amd64", - short_name = "asan", - ), - luci.console_view_entry( - builder = "ci/chromeos-amd64-generic-cfi-thin-lto-rel", - category = "cros|week3|amd64", - short_name = "thinlto", - ), - luci.console_view_entry( - builder = "ci/chromeos-arm-generic-rel", - category = "cros|week3|arm", - short_name = "rel", - ), - luci.console_view_entry( - builder = "ci/chromeos-arm-generic-dbg", - category = "cros|week3|arm", - short_name = "dbg", - ), - luci.console_view_entry( - builder = "ci/chromeos-kevin-rel", - category = "cros|week3|kevin", - short_name = "rel", - ), - luci.console_view_entry( - builder = "webrtc.fyi/WebRTC Chromium FYI ios-device", - category = "ios|week1a", - short_name = "dev", - ), - luci.console_view_entry( - builder = "webrtc.fyi/WebRTC Chromium FYI ios-simulator", - category = "ios|week1a", - short_name = "sim", - ), - luci.console_view_entry( - builder = "ci/ios-device", - category = "ios|week1b", - short_name = "dev", - ), - luci.console_view_entry( - builder = "ci/ios-simulator", - category = "ios|week1b|sim", - ), - luci.console_view_entry( - builder = "ci/ios-simulator-full-configs", - category = "ios|week1b|sim", - short_name = "fullconf", - ), - luci.console_view_entry( - builder = "ci/ios-simulator-noncq", - category = "ios|week1b|sim", - short_name = "noncq", - ), - luci.console_view_entry( - builder = "ci/ios13-beta-simulator", - category = "ios|week1b|ios13|beta", - short_name = "sim", - ), - luci.console_view_entry( - builder = "ci/ios13-sdk-simulator", - category = "ios|week1b|ios13|sdk", - short_name = "sim", - ), - luci.console_view_entry( - builder = "ci/ios-simulator-cronet", - category = "ios|week1c", - short_name = "cro", - ), - luci.console_view_entry( - builder = "ci/ios-simulator-cr-recipe", - category = "ios|week1c", - short_name = "crr", - ), - luci.console_view_entry( - builder = "ci/ios-webkit-tot", - category = "ios|week1c", - short_name = "webkit", - ), - luci.console_view_entry( - builder = "ci/ios13-sdk-device", - category = "ios|week1c|ios13", - short_name = "dev", - ), - luci.console_view_entry( - builder = "ci/ios-simulator-code-coverage", - category = "ios|week1d", - short_name = "code", - ), - ], -)
diff --git a/infra/config/subprojects/goma/subproject.star b/infra/config/subprojects/goma/subproject.star index 0ff40f4..1a05416 100644 --- a/infra/config/subprojects/goma/subproject.star +++ b/infra/config/subprojects/goma/subproject.star
@@ -5,6 +5,5 @@ exec("./goma.star") exec("./consoles/chromium.goma.star") exec("./consoles/chromium.goma.fyi.star") -exec("./consoles/chromium.goma.migration.star") exec("./consoles/goma.latest.star") exec("./consoles/luci.chromium.goma.star")
diff --git a/ios/build/bots/scripts/shard_util.py b/ios/build/bots/scripts/shard_util.py index 37b9494a..961fef3 100644 --- a/ios/build/bots/scripts/shard_util.py +++ b/ios/build/bots/scripts/shard_util.py
@@ -14,14 +14,18 @@ # WARNING: THESE DUPLICATE CONSTANTS IN: # //build/scripts/slave/recipe_modules/ios/api.py +# Regex to parse all compiled EG tests, including disabled (prepended with +# DISABLED_ or FLAKY_). TEST_NAMES_DEBUG_APP_PATTERN = re.compile( 'imp +(?:0[xX][0-9a-fA-F]+ )?-\[(?P<testSuite>[A-Za-z_][A-Za-z0-9_]' - '*Test[Case]*) (?P<testMethod>test[A-Za-z0-9_]*)\]') + '*Test[Case]*) (?P<testMethod>(?:DISABLED_|FLAKY_)?test[A-Za-z0-9_]*)\]') TEST_CLASS_RELEASE_APP_PATTERN = re.compile( r'name +0[xX]\w+ ' '(?P<testSuite>[A-Za-z_][A-Za-z0-9_]*Test(?:Case|))\n') +# Regex to parse all compiled EG tests, including disabled (prepended with +# DISABLED_ or FLAKY_). TEST_NAME_RELEASE_APP_PATTERN = re.compile( - r'name +0[xX]\w+ (?P<testCase>test[A-Za-z0-9_]+)\n') + r'name +0[xX]\w+ (?P<testCase>(?:DISABLED_|FLAKY_)?test[A-Za-z0-9_]+)\n') # 'ChromeTestCase' and 'BaseEarlGreyTestCase' are parent classes # of all EarlGrey/EarlGrey2 test classes. They have no real tests. IGNORED_CLASSES = ['BaseEarlGreyTestCase', 'ChromeTestCase'] @@ -81,7 +85,7 @@ def fetch_test_names_for_release(stdout): """Parse otool output to get all testMethods in all TestCases in the - format of (TestCase, testMethod), in release app. + format of (TestCase, testMethod) including disabled tests, in release app. WARNING: This logic is similar to what's found in //build/scripts/slave/recipe_modules/ios/api.py @@ -90,7 +94,7 @@ stdout: (string) response of 'otool -ov' Returns: - (list) a list of (TestCase, testMethod) + (list) a list of (TestCase, testMethod), containing disabled tests. """ # For Release builds `otool -ov` command generates output that is # different from Debug builds. @@ -114,29 +118,30 @@ def fetch_test_names_for_debug(stdout): """Parse otool output to get all testMethods in all TestCases in the - format of (TestCase, testMethod), in debug app. + format of (TestCase, testMethod) including disabled tests, in debug app. Args: stdout: (string) response of 'otool -ov' Returns: - (list) a list of (TestCase, testMethod) + (list) a list of (TestCase, testMethod), containing disabled tests. """ test_names = TEST_NAMES_DEBUG_APP_PATTERN.findall(stdout) return filter(lambda (test_case, _): test_case not in IGNORED_CLASSES, test_names) -def fetch_test_names(app, host_app, release=False): +def fetch_test_names(app, host_app, release, enabled_tests_only=True): """Determine the list of (TestCase, testMethod) for the app. Args: app: (string) path to app host_app: (string) path to host app. None or "NO_PATH" for EG1. release: (bool) whether this is a release build. + enabled_tests_only: (bool) output only enabled tests. Returns: - (list) a list of (TestCase, testMethod) + (list) a list of (TestCase, testMethod). """ # Determine what path to use app_path = determine_app_path(app, host_app, release) @@ -147,9 +152,13 @@ LOGGER.info("Ignored test classes: {}".format(IGNORED_CLASSES)) if release: LOGGER.info("Release build detected. Fetching test names for release.") - return fetch_test_names_for_release(stdout) - - return fetch_test_names_for_debug(stdout) + all_test_names = ( + fetch_test_names_for_release(stdout) + if release else fetch_test_names_for_debug(stdout)) + enabled_test_names = ( + filter(lambda (_, test_method): test_method.startswith('test'), + all_test_names)) + return enabled_test_names if enabled_tests_only else all_test_names def balance_into_sublists(test_counts, total_shards):
diff --git a/ios/build/bots/scripts/shard_util_test.py b/ios/build/bots/scripts/shard_util_test.py index 1f182f9..597f13d 100644 --- a/ios/build/bots/scripts/shard_util_test.py +++ b/ios/build/bots/scripts/shard_util_test.py
@@ -23,7 +23,9 @@ 'name 0x1064b8438 PasswordsTestCase', 'imp 0x1075e6887 -[PasswordsTestCase testG]', 'name 0x1064b8438 ToolBarTestCase', - 'imp 0x1075e6887 -[ToolBarTestCase testH]', 'version 0' + 'imp 0x1075e6887 -[ToolBarTestCase testH]', + 'imp 0x1075e6887 -[ToolBarTestCase DISABLED_testI]', + 'imp 0x1075e6887 -[ToolBarTestCase FLAKY_testJ]', 'version 0' ]) # Debug app otool output format in Xcode 11.4 toolchain. @@ -43,7 +45,9 @@ ' name 0x1064b8438 PasswordsTestCase', ' imp 0x1075e6887 -[PasswordsTestCase testG]', ' name 0x1064b8438 ToolBarTestCase', - ' imp 0x1075e6887 -[ToolBarTestCase testH]', 'version 0' + ' imp 0x1075e6887 -[ToolBarTestCase testH]', + ' imp 0x1075e6887 -[ToolBarTestCase DISABLED_testI]', + ' imp 0x1075e6887 -[ToolBarTestCase FLAKY_testJ]', 'version 0' ]) RELEASE_APP_OTOOL_OUTPUT = '\n'.join([ @@ -58,8 +62,9 @@ 'name 0x1075e6887 testF', 'baseProtocols 0x0', 'name 0x1064b8438 ChromeTestCase', 'name 0x1064b8438 setUp', 'baseProtocols 0x0', 'name 0x1064b8438 ToolBarTestCase', - 'name 0x1075e6887 testG', 'name 0x1075e6887 testH', 'baseProtocols 0x0', - 'version 0' + 'name 0x1075e6887 testG', 'name 0x1075e6887 testH', + 'name 0x1075e6887 DISABLED_testI', 'name 0x1075e6887 FLAKY_testJ', + 'baseProtocols 0x0', 'version 0' ]) # Release app otool output format in Xcode 11.4 toolchain. @@ -76,7 +81,8 @@ ' name 0x1064b8438 ChromeTestCase', ' name 0x1064b8438 setUp', 'baseProtocols 0x0', ' name 0x1064b8438 ToolBarTestCase', ' name 0x1075e6887 testG', ' name 0x1075e6887 testH', - 'baseProtocols 0x0', 'version 0' + ' name 0x1075e6893 DISABLED_testI', + ' name 0x1075e723f FLAKY_testJ', 'baseProtocols 0x0', 'version 0' ]) @@ -117,92 +123,110 @@ def test_fetch_test_names_debug(self): """Ensures that the debug output is formatted correctly""" resp = shard_util.fetch_test_names_for_debug(DEBUG_APP_OTOOL_OUTPUT) - self.assertEqual(len(resp), 8) - expected_test_names = [('CacheTestCase', 'testA'), ('CacheTestCase', - 'testB'), - ('CacheTestCase', 'testc'), ('TabUITestCase', - 'testD'), - ('TabUITestCase', 'testE'), - ('KeyboardTestCase', 'testF'), - ('PasswordsTestCase', 'testG'), - ('ToolBarTestCase', 'testH')] + self.assertEqual(len(resp), 10) + expected_test_names = [ + ('CacheTestCase', 'testA'), + ('CacheTestCase', 'testB'), + ('CacheTestCase', 'testc'), + ('TabUITestCase', 'testD'), + ('TabUITestCase', 'testE'), + ('KeyboardTestCase', 'testF'), + ('PasswordsTestCase', 'testG'), + ('ToolBarTestCase', 'testH'), + ('ToolBarTestCase', 'DISABLED_testI'), + ('ToolBarTestCase', 'FLAKY_testJ'), + ] for test_name in expected_test_names: self.assertTrue(test_name in resp) test_cases = map(lambda (test_case, test_method): test_case, resp) # ({'CacheTestCase': 3, 'TabUITestCase': 2, 'PasswordsTestCase': 1, - # 'KeyboardTestCase': 1, 'ToolBarTestCase': 1}) + # 'KeyboardTestCase': 1, 'ToolBarTestCase': 3}) counts = collections.Counter(test_cases).most_common() name, _ = counts[0] - self.assertEqual(name, 'CacheTestCase') + self.assertEqual(name, 'ToolBarTestCase') def test_fetch_test_counts_release(self): """Ensures that the release output is formatted correctly""" resp = shard_util.fetch_test_names_for_release(RELEASE_APP_OTOOL_OUTPUT) - self.assertEqual(len(resp), 8) + self.assertEqual(len(resp), 10) - expected_test_names = [('CacheTestCase', 'testA'), ('CacheTestCase', - 'testB'), - ('CacheTestCase', 'testc'), ('KeyboardTest', - 'testD'), - ('KeyboardTest', 'testE'), ('KeyboardTest', 'testF'), - ('ToolBarTestCase', 'testG'), - ('ToolBarTestCase', 'testH')] + expected_test_names = [ + ('CacheTestCase', 'testA'), + ('CacheTestCase', 'testB'), + ('CacheTestCase', 'testc'), + ('KeyboardTest', 'testD'), + ('KeyboardTest', 'testE'), + ('KeyboardTest', 'testF'), + ('ToolBarTestCase', 'testG'), + ('ToolBarTestCase', 'testH'), + ('ToolBarTestCase', 'DISABLED_testI'), + ('ToolBarTestCase', 'FLAKY_testJ'), + ] for test_name in expected_test_names: self.assertTrue(test_name in resp) test_cases = map(lambda (test_case, test_method): test_case, resp) # ({'KeyboardTest': 3, 'CacheTestCase': 3, - # 'ToolBarTestCase': 2}) + # 'ToolBarTestCase': 4}) counts = collections.Counter(test_cases).most_common() name, _ = counts[0] - self.assertEqual(name, 'KeyboardTest') + self.assertEqual(name, 'ToolBarTestCase') def test_fetch_test_names_debug_114(self): """Test the debug output from otool in Xcode 11.4""" resp = shard_util.fetch_test_names_for_debug(DEBUG_APP_OTOOL_OUTPUT_114) - self.assertEqual(len(resp), 8) - expected_test_names = [('CacheTestCase', 'testA'), ('CacheTestCase', - 'testB'), - ('CacheTestCase', 'testc'), ('TabUITestCase', - 'testD'), - ('TabUITestCase', 'testE'), - ('KeyboardTestCase', 'testF'), - ('PasswordsTestCase', 'testG'), - ('ToolBarTestCase', 'testH')] + self.assertEqual(len(resp), 10) + expected_test_names = [ + ('CacheTestCase', 'testA'), + ('CacheTestCase', 'testB'), + ('CacheTestCase', 'testc'), + ('TabUITestCase', 'testD'), + ('TabUITestCase', 'testE'), + ('KeyboardTestCase', 'testF'), + ('PasswordsTestCase', 'testG'), + ('ToolBarTestCase', 'testH'), + ('ToolBarTestCase', 'DISABLED_testI'), + ('ToolBarTestCase', 'FLAKY_testJ'), + ] for test_name in expected_test_names: self.assertTrue(test_name in resp) test_cases = map(lambda (test_case, test_method): test_case, resp) # ({'CacheTestCase': 3, 'TabUITestCase': 2, 'PasswordsTestCase': 1, - # 'KeyboardTestCase': 1, 'ToolBarTestCase': 1}) + # 'KeyboardTestCase': 1, 'ToolBarTestCase': 3}) counts = collections.Counter(test_cases).most_common() name, _ = counts[0] - self.assertEqual(name, 'CacheTestCase') + self.assertEqual(name, 'ToolBarTestCase') def test_fetch_test_counts_release_114(self): """Test the release output from otool in Xcode 11.4""" resp = shard_util.fetch_test_names_for_release(RELEASE_APP_OTOOL_OUTPUT_114) - self.assertEqual(len(resp), 8) + self.assertEqual(len(resp), 10) - expected_test_names = [('CacheTestCase', 'testA'), ('CacheTestCase', - 'testB'), - ('CacheTestCase', 'testc'), ('KeyboardTest', - 'testD'), - ('KeyboardTest', 'testE'), ('KeyboardTest', 'testF'), - ('ToolBarTestCase', 'testG'), - ('ToolBarTestCase', 'testH')] + expected_test_names = [ + ('CacheTestCase', 'testA'), + ('CacheTestCase', 'testB'), + ('CacheTestCase', 'testc'), + ('KeyboardTest', 'testD'), + ('KeyboardTest', 'testE'), + ('KeyboardTest', 'testF'), + ('ToolBarTestCase', 'testG'), + ('ToolBarTestCase', 'testH'), + ('ToolBarTestCase', 'DISABLED_testI'), + ('ToolBarTestCase', 'FLAKY_testJ'), + ] for test_name in expected_test_names: self.assertTrue(test_name in resp) test_cases = map(lambda (test_case, test_method): test_case, resp) # ({'KeyboardTest': 3, 'CacheTestCase': 3, - # 'ToolBarTestCase': 2}) + # 'ToolBarTestCase': 4}) counts = collections.Counter(test_cases).most_common() name, _ = counts[0] - self.assertEqual(name, 'KeyboardTest') + self.assertEqual(name, 'ToolBarTestCase') def test_balance_into_sublists_debug(self): """Ensure the balancing algorithm works""" @@ -217,11 +241,15 @@ sublists_3 = shard_util.balance_into_sublists(test_counts, 3) self.assertEqual(len(sublists_3), 3) # CacheTestCase has 3, - # TabUITestCase has 2, ToolBarTestCase has 1 + # TabUITestCase has 2, ToolBarTestCase has 4 # PasswordsTestCase has 1, KeyboardTestCase has 1 - self.assertEqual(len(sublists_3[0]), 1) - self.assertEqual(len(sublists_3[1]), 2) - self.assertEqual(len(sublists_3[2]), 2) + # They will be balanced into: + # [[ToolBarTestCase], [CacheTestCase, PasswordsTestCase], + # [TabUITestCase, KeyboardTestCase]] + self.assertEqual( + sorted([len(sublists_3[0]), + len(sublists_3[1]), + len(sublists_3[2])]), [1, 2, 2]) def test_balance_into_sublists_release(self): """Ensure the balancing algorithm works""" @@ -233,7 +261,8 @@ self.assertEqual(len(sublists_3), 3) # KeyboardTest has 3 # CacheTestCase has 3 - # ToolbarTest Case has 2 + # ToolbarTest Case has 4 + # They will be balanced as one in each shard. self.assertEqual(len(sublists_3[0]), 1) self.assertEqual(len(sublists_3[1]), 1) self.assertEqual(len(sublists_3[2]), 1)
diff --git a/ios/build/bots/scripts/test_apps.py b/ios/build/bots/scripts/test_apps.py index 6b01824e..fa225c05 100644 --- a/ios/build/bots/scripts/test_apps.py +++ b/ios/build/bots/scripts/test_apps.py
@@ -12,6 +12,9 @@ import test_runner +OUTPUT_DISABLED_TESTS_TEST_ARG = '--write-compiled-tests-json-to-writable-path' + + #TODO(crbug.com/1046911): Remove usage of KIF filters. def get_kif_test_filter(tests, invert=False): """Returns the KIF test filter to filter the given test cases. @@ -111,6 +114,7 @@ self.env_vars[env_var[0]] = None if len(env_var) == 1 else env_var[1] self.included_tests = included_tests or [] self.excluded_tests = excluded_tests or [] + self.disabled_tests = [] self.module_name = os.path.splitext(os.path.basename(test_app))[0] self.release = release self.host_app_path = host_app_path @@ -238,16 +242,27 @@ # but they are not test-methods. # TODO(crbug.com/982435): Rename not test methods with test-suffix. none_tests = ['ChromeTestCase/testServer', 'FindInPageTestCase/testURL'] + # TODO(crbug.com/1123681): Move all_tests to class var. Set all_tests, + # disabled_tests values in initialization to avoid multiple calls to otool. all_tests = [] + # Only store the tests when there is the test arg. + store_disabled_tests = OUTPUT_DISABLED_TESTS_TEST_ARG in self.test_args + self.disabled_tests = [] for test_class, test_method in shard_util.fetch_test_names( - self.test_app_path, self.host_app_path, self.release): + self.test_app_path, + self.host_app_path, + self.release, + enabled_tests_only=False): test_name = '%s/%s' % (test_class, test_method) if (test_name not in none_tests and # inlcuded_tests contains the tests to execute, which may be a subset # of all tests b/c of the iOS test sharding logic in run.py. Filter by # self.included_tests if specified (test_class in self.included_tests if self.included_tests else True)): - all_tests.append(test_name) + if test_method.startswith('test'): + all_tests.append(test_name) + elif store_disabled_tests: + self.disabled_tests.append(test_name) return all_tests
diff --git a/ios/build/bots/scripts/xcodebuild_runner.py b/ios/build/bots/scripts/xcodebuild_runner.py index a827ce2..9983a3d 100644 --- a/ios/build/bots/scripts/xcodebuild_runner.py +++ b/ios/build/bots/scripts/xcodebuild_runner.py
@@ -403,6 +403,12 @@ if shard_attempts[-1]['failed']: self.logs['failed tests'].extend(shard_attempts[-1]['failed'].keys()) + # Gets disabled tests from test app object if any. + self.logs['disabled tests'] = [] + for launch_command in launch_commands: + self.logs['disabled tests'].extend( + launch_command.egtests_app.disabled_tests) + # Gets all failures/flakes and lists them in bot summary all_failures = set() for shard_attempts in attempts_results: @@ -459,6 +465,8 @@ for test in attempt_results['passed']: output.mark_passed(test) + output.mark_all_skipped(self.logs['disabled tests']) + self.test_results['tests'] = output.tests # Test is failed if there are failures for the last run.
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm index f99fc03..baad67e 100644 --- a/ios/chrome/app/main_controller.mm +++ b/ios/chrome/app/main_controller.mm
@@ -486,6 +486,7 @@ needRestoration = [CrashRestoreHelper moveAsideSessionInformationForBrowserState:chromeBrowserState]; } + [[PreviousSessionInfo sharedInstance] resetConnectedSceneSessionIDs]; // Initialize and set the main browser state. [self initializeBrowserState:chromeBrowserState];
diff --git a/ios/chrome/browser/discover_feed/BUILD.gn b/ios/chrome/browser/discover_feed/BUILD.gn index 11663b08..89fd0117 100644 --- a/ios/chrome/browser/discover_feed/BUILD.gn +++ b/ios/chrome/browser/discover_feed/BUILD.gn
@@ -18,6 +18,7 @@ "//components/signin/public/identity_manager", "//ios/chrome/browser/browser_state", "//ios/chrome/browser/signin", + "//ios/chrome/browser/ui/content_suggestions:metrics", "//ios/public/provider/chrome/browser", "//ios/public/provider/chrome/browser/discover_feed", ]
diff --git a/ios/chrome/browser/discover_feed/discover_feed_service.h b/ios/chrome/browser/discover_feed/discover_feed_service.h index 1a94d3c..5d66a1b 100644 --- a/ios/chrome/browser/discover_feed/discover_feed_service.h +++ b/ios/chrome/browser/discover_feed/discover_feed_service.h
@@ -9,6 +9,7 @@ #include "components/signin/public/identity_manager/identity_manager.h" class ChromeBrowserState; +@class DiscoverFeedMetricsRecorder; class DiscoverFeedProvider; // A browser-context keyed service that is used to keep the Discover Feed data @@ -20,6 +21,10 @@ DiscoverFeedService(ChromeBrowserState* browser_state); ~DiscoverFeedService() override; + // Returns the FeedMetricsRecorder to be used by the Feed, a single instance + // of DiscoverFeedMetricsRecorder needs to be used per BrowserState. + DiscoverFeedMetricsRecorder* GetDiscoverFeedMetricsRecorder(); + // KeyedService: void Shutdown() override; @@ -36,6 +41,9 @@ // Discover Feed provider to notify of changes. DiscoverFeedProvider* discover_feed_provider_; + // Metrics recorder for the DiscoverFeed. + DiscoverFeedMetricsRecorder* discover_feed_metrics_recorder_; + DISALLOW_COPY_AND_ASSIGN(DiscoverFeedService); };
diff --git a/ios/chrome/browser/discover_feed/discover_feed_service.mm b/ios/chrome/browser/discover_feed/discover_feed_service.mm index f731c50..035964a 100644 --- a/ios/chrome/browser/discover_feed/discover_feed_service.mm +++ b/ios/chrome/browser/discover_feed/discover_feed_service.mm
@@ -7,6 +7,7 @@ #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #import "ios/chrome/browser/signin/authentication_service_factory.h" #include "ios/chrome/browser/signin/identity_manager_factory.h" +#import "ios/chrome/browser/ui/content_suggestions/discover_feed_metrics_recorder.h" #import "ios/public/provider/chrome/browser/chrome_browser_provider.h" #import "ios/public/provider/chrome/browser/discover_feed/discover_feed_configuration.h" #import "ios/public/provider/chrome/browser/discover_feed/discover_feed_provider.h" @@ -23,14 +24,22 @@ identity_manager_->AddObserver(this); } + discover_feed_metrics_recorder_ = [[DiscoverFeedMetricsRecorder alloc] init]; + DiscoverFeedConfiguration* discover_config = [[DiscoverFeedConfiguration alloc] init]; discover_config.browserState = browser_state; + discover_config.metricsRecorder = discover_feed_metrics_recorder_; discover_feed_provider_->StartFeed(discover_config); } DiscoverFeedService::~DiscoverFeedService() {} +DiscoverFeedMetricsRecorder* +DiscoverFeedService::GetDiscoverFeedMetricsRecorder() { + return discover_feed_metrics_recorder_; +} + void DiscoverFeedService::Shutdown() { if (identity_manager_) { identity_manager_->RemoveObserver(this);
diff --git a/ios/chrome/browser/metrics/previous_session_info.h b/ios/chrome/browser/metrics/previous_session_info.h index 073e6ea..cadb03b 100644 --- a/ios/chrome/browser/metrics/previous_session_info.h +++ b/ios/chrome/browser/metrics/previous_session_info.h
@@ -17,6 +17,9 @@ // Key in the UserDefaults for a boolean describing whether or not the session // restoration is in progress. extern NSString* const kPreviousSessionInfoRestoringSession; +// Key in the UserDefaults for an array which contains the ids for the connected +// scene sessions on the previous run. +extern NSString* const kPreviousSessionInfoConnectedSceneSessionIDs; // The values of this enum are persisted (both to NSUserDefaults and logs) and // represent the state of the last session (which may have been running a @@ -143,6 +146,15 @@ // ignored. - (void)resetMemoryWarningFlag; +// Adds |sessionID| to the list of connected sessions. +- (void)addSceneSessionID:(NSString*)sessionID; + +// Removes |sessionID| from the list of connected sessions. +- (void)removeSceneSessionID:(NSString*)sessionID; + +// Empties the list of connected session. +- (void)resetConnectedSceneSessionIDs; + // Must be called when Chrome starts session restoration. The returned closure // runner will clear up the flag when destroyed. Can be used on different // threads.
diff --git a/ios/chrome/browser/metrics/previous_session_info.mm b/ios/chrome/browser/metrics/previous_session_info.mm index 76e5dcd7..18819a77 100644 --- a/ios/chrome/browser/metrics/previous_session_info.mm +++ b/ios/chrome/browser/metrics/previous_session_info.mm
@@ -94,6 +94,7 @@ // version of the application. NSString* const kPreviousSessionInfoMultiWindowEnabled = @"PreviousSessionInfoMultiWindowEnabled"; + } // namespace namespace previous_session_info_constants { @@ -102,6 +103,8 @@ NSString* const kOSStartTime = @"OSStartTime"; NSString* const kPreviousSessionInfoRestoringSession = @"PreviousSessionInfoRestoringSession"; +NSString* const kPreviousSessionInfoConnectedSceneSessionIDs = + @"PreviousSessionInfoConnectedSceneSessionIDs"; } // namespace previous_session_info_constants @interface PreviousSessionInfo () @@ -113,6 +116,10 @@ // Can be greater than one if multiple sessions are being restored in parallel. @property(atomic, assign) int numberOfSessionsBeingRestored; +// The list of the session IDs for all the connected scenes, used for crash +// restoration. +@property(nonatomic, strong) NSMutableSet<NSString*>* connectedSceneSessionsIDs; + // Redefined to be read-write. @property(nonatomic, assign) NSInteger availableDeviceStorage; @property(nonatomic, assign) float deviceBatteryLevel; @@ -185,6 +192,12 @@ gSharedInstance.isMultiWindowEnabledSession = [defaults boolForKey:kPreviousSessionInfoMultiWindowEnabled]; + gSharedInstance.connectedSceneSessionsIDs = [NSMutableSet + setWithArray:[defaults + stringArrayForKey: + previous_session_info_constants:: + kPreviousSessionInfoConnectedSceneSessionIDs]]; + NSTimeInterval lastSystemStartTime = [defaults doubleForKey:previous_session_info_constants::kOSStartTime]; @@ -403,6 +416,29 @@ [defaults synchronize]; } +- (void)synchronizeSceneSessionIDs { + NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; + [defaults setObject:[self.connectedSceneSessionsIDs allObjects] + forKey:previous_session_info_constants:: + kPreviousSessionInfoConnectedSceneSessionIDs]; + [defaults synchronize]; +} + +- (void)addSceneSessionID:(NSString*)sessionID { + [self.connectedSceneSessionsIDs addObject:sessionID]; + [self synchronizeSceneSessionIDs]; +} + +- (void)removeSceneSessionID:(NSString*)sessionID { + [self.connectedSceneSessionsIDs removeObject:sessionID]; + [self synchronizeSceneSessionIDs]; +} + +- (void)resetConnectedSceneSessionIDs { + self.connectedSceneSessionsIDs = [[NSMutableSet alloc] init]; + [self synchronizeSceneSessionIDs]; +} + - (base::ScopedClosureRunner)startSessionRestoration { if (self.numberOfSessionsBeingRestored == 0) { [NSUserDefaults.standardUserDefaults
diff --git a/ios/chrome/browser/metrics/previous_session_info_private.h b/ios/chrome/browser/metrics/previous_session_info_private.h index fb7f5a1..8ac12ba 100644 --- a/ios/chrome/browser/metrics/previous_session_info_private.h +++ b/ios/chrome/browser/metrics/previous_session_info_private.h
@@ -14,6 +14,7 @@ @property(nonatomic, assign) previous_session_info_constants::DeviceBatteryState deviceBatteryState; @property(nonatomic, assign) BOOL OSRestartedAfterPreviousSession; +@property(nonatomic, strong) NSMutableSet<NSString*>* connectedSceneSessionsIDs; + (void)resetSharedInstanceForTesting;
diff --git a/ios/chrome/browser/metrics/previous_session_info_unittest.mm b/ios/chrome/browser/metrics/previous_session_info_unittest.mm index 35758c0..e240041 100644 --- a/ios/chrome/browser/metrics/previous_session_info_unittest.mm +++ b/ios/chrome/browser/metrics/previous_session_info_unittest.mm
@@ -16,6 +16,8 @@ #endif using previous_session_info_constants::kPreviousSessionInfoRestoringSession; +using previous_session_info_constants:: + kPreviousSessionInfoConnectedSceneSessionIDs; namespace { @@ -31,6 +33,11 @@ // last session. NSString* const kLastRanLanguage = @"LastRanLanguage"; +// IDs to be used for testing scene sessions. +NSString* const kTestSession1ID = @"test_session_1"; +NSString* const kTestSession2ID = @"test_session_2"; +NSString* const kTestSession3ID = @"test_session_3"; + using PreviousSessionInfoTest = PlatformTest; TEST_F(PreviousSessionInfoTest, InitializationWithEmptyDefaults) { @@ -326,6 +333,52 @@ terminatedDuringSessionRestoration]); } +// Tests that AddSceneSessionID adds to User Defaults. +TEST_F(PreviousSessionInfoTest, AddSceneSessionID) { + [PreviousSessionInfo resetSharedInstanceForTesting]; + [[PreviousSessionInfo sharedInstance] addSceneSessionID:kTestSession1ID]; + [[PreviousSessionInfo sharedInstance] addSceneSessionID:kTestSession2ID]; + NSArray<NSString*>* sessionIDs = [NSUserDefaults.standardUserDefaults + stringArrayForKey:kPreviousSessionInfoConnectedSceneSessionIDs]; + EXPECT_TRUE([sessionIDs containsObject:kTestSession1ID]); + EXPECT_TRUE([sessionIDs containsObject:kTestSession2ID]); + EXPECT_EQ(2U, [sessionIDs count]); +} + +// Tests that RemoveSceneSessionID removes id from User Defaults. +TEST_F(PreviousSessionInfoTest, RemoveSceneSessionID) { + [PreviousSessionInfo resetSharedInstanceForTesting]; + [[PreviousSessionInfo sharedInstance] addSceneSessionID:kTestSession1ID]; + [[PreviousSessionInfo sharedInstance] addSceneSessionID:kTestSession2ID]; + [[PreviousSessionInfo sharedInstance] addSceneSessionID:kTestSession3ID]; + NSArray<NSString*>* sessionIDs = [NSUserDefaults.standardUserDefaults + stringArrayForKey:kPreviousSessionInfoConnectedSceneSessionIDs]; + ASSERT_EQ(3U, [sessionIDs count]); + [[PreviousSessionInfo sharedInstance] removeSceneSessionID:kTestSession3ID]; + [[PreviousSessionInfo sharedInstance] removeSceneSessionID:kTestSession1ID]; + sessionIDs = [NSUserDefaults.standardUserDefaults + stringArrayForKey:kPreviousSessionInfoConnectedSceneSessionIDs]; + EXPECT_FALSE([sessionIDs containsObject:kTestSession3ID]); + EXPECT_FALSE([sessionIDs containsObject:kTestSession1ID]); + EXPECT_EQ(1U, [sessionIDs count]); +} + +// Tests that resetConnectedSceneSessionIDs remove all session ids from User +// Defaults. +TEST_F(PreviousSessionInfoTest, resetConnectedSceneSessionIDs) { + [PreviousSessionInfo resetSharedInstanceForTesting]; + [[PreviousSessionInfo sharedInstance] addSceneSessionID:kTestSession1ID]; + [[PreviousSessionInfo sharedInstance] addSceneSessionID:kTestSession2ID]; + [[PreviousSessionInfo sharedInstance] addSceneSessionID:kTestSession3ID]; + NSArray<NSString*>* sessionIDs = [NSUserDefaults.standardUserDefaults + stringArrayForKey:kPreviousSessionInfoConnectedSceneSessionIDs]; + ASSERT_EQ(3U, [sessionIDs count]); + [[PreviousSessionInfo sharedInstance] resetConnectedSceneSessionIDs]; + sessionIDs = [NSUserDefaults.standardUserDefaults + stringArrayForKey:kPreviousSessionInfoConnectedSceneSessionIDs]; + EXPECT_EQ(0U, [sessionIDs count]); +} + // Tests that scoped object returned from startSessionRestoration correctly // resets User Defaults. TEST_F(PreviousSessionInfoTest, ParallelSessionRestorations) {
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm b/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm index 1631665c..4a4db90 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm
@@ -2210,6 +2210,11 @@ } const BookmarkNode* node = [self nodeAtIndexPath:indexPath]; + + // Disable the edit and move menu options if the node is not editable by user, + // or if editing bookmarks is not allowed. + BOOL canEditNode = + [self isEditBookmarksEnabled] && [self isNodeEditableByUser:node]; UIContextMenuActionProvider actionProvider; // TODO (crbug.com/1093302): Add more actions for Bookmark URL and Folder. @@ -2247,9 +2252,13 @@ [menuElements addObject:[actionFactory actionToCopyURL:node->url()]]; - [menuElements addObject:[actionFactory actionToEditWithBlock:^{ - [self editNode:node]; - }]]; + UIAction* editAction = [actionFactory actionToEditWithBlock:^{ + [self editNode:node]; + }]; + if (!canEditNode) { + editAction.attributes = UIMenuElementAttributesDisabled; + } + [menuElements addObject:editAction]; [menuElements addObject:[actionFactory actionToShareWithBlock:^{ @@ -2279,15 +2288,22 @@ NSMutableArray<UIMenuElement*>* menuElements = [[NSMutableArray alloc] init]; - [menuElements addObject:[actionFactory actionToEditWithBlock:^{ - [self editNode:node]; - }]]; + UIAction* editAction = [actionFactory actionToEditWithBlock:^{ + [self editNode:node]; + }]; + UIAction* moveAction = [actionFactory actionToMoveFolderWithBlock:^{ + std::set<const BookmarkNode*> nodes; + nodes.insert(node); + [self moveNodes:nodes]; + }]; - [menuElements addObject:[actionFactory actionToMoveFolderWithBlock:^{ - std::set<const BookmarkNode*> nodes; - nodes.insert(node); - [self moveNodes:nodes]; - }]]; + if (!canEditNode) { + editAction.attributes = UIMenuElementAttributesDisabled; + moveAction.attributes = UIMenuElementAttributesDisabled; + } + + [menuElements addObject:editAction]; + [menuElements addObject:moveAction]; return [UIMenu menuWithTitle:@"" children:menuElements]; };
diff --git a/ios/chrome/browser/ui/content_suggestions/BUILD.gn b/ios/chrome/browser/ui/content_suggestions/BUILD.gn index bf44aec..9a4e529e 100644 --- a/ios/chrome/browser/ui/content_suggestions/BUILD.gn +++ b/ios/chrome/browser/ui/content_suggestions/BUILD.gn
@@ -23,8 +23,6 @@ "content_suggestions_service_bridge_observer.h", "content_suggestions_service_bridge_observer.mm", "discover_feed_delegate.h", - "discover_feed_metrics_recorder.h", - "discover_feed_metrics_recorder.mm", "mediator_util.h", "mediator_util.mm", "ntp_home_mediator.h", @@ -35,6 +33,7 @@ ] deps = [ ":feature_flags", + ":metrics", "//base", "//components/favicon/core", "//components/feature_engagement/public", @@ -103,6 +102,7 @@ "//ui/base", "//ui/strings", ] + public_deps = [ ":metrics" ] configs += [ "//build/config/compiler:enable_arc" ] } @@ -151,6 +151,7 @@ ":content_suggestions_constant", ":content_suggestions_ui_util", ":feature_flags", + ":metrics", "resources:content_suggestions_no_image", "resources:content_suggestions_offline", "resources:ntp_search_icon", @@ -185,6 +186,15 @@ configs += [ "//build/config/compiler:enable_arc" ] } +source_set("metrics") { + sources = [ + "discover_feed_metrics_recorder.h", + "discover_feed_metrics_recorder.mm", + ] + deps = [ "//base" ] + configs += [ "//build/config/compiler:enable_arc" ] +} + source_set("content_suggestions_constant") { sources = [ "ntp_home_constant.h",
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm index cd2a0e5..16a54d6 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm
@@ -19,6 +19,7 @@ #import "components/search_engines/template_url.h" #import "components/search_engines/template_url_service.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" +#include "ios/chrome/browser/discover_feed/discover_feed_service.h" #include "ios/chrome/browser/discover_feed/discover_feed_service_factory.h" #include "ios/chrome/browser/drag_and_drop/drag_and_drop_flag.h" #import "ios/chrome/browser/drag_and_drop/url_drag_drop_handler.h" @@ -209,8 +210,11 @@ if (IsDiscoverFeedEnabled()) { // Creating the DiscoverFeedService will start the DiscoverFeed. - DiscoverFeedServiceFactory::GetForBrowserState( - self.browser->GetBrowserState()); + DiscoverFeedService* discoverFeedService = + DiscoverFeedServiceFactory::GetForBrowserState( + self.browser->GetBrowserState()); + self.discoverFeedMetricsRecorder = + discoverFeedService->GetDiscoverFeedMetricsRecorder(); } self.discoverFeedViewController = [self discoverFeed]; @@ -239,7 +243,6 @@ self.metricsRecorder = [[ContentSuggestionsMetricsRecorder alloc] init]; self.metricsRecorder.delegate = self.contentSuggestionsMediator; - self.discoverFeedMetricsRecorder = [[DiscoverFeedMetricsRecorder alloc] init]; // Offset to maintain Discover feed scroll position. CGFloat offset = 0; @@ -266,6 +269,8 @@ self.browser->GetCommandDispatcher(), SnackbarCommands); self.suggestionsViewController.dispatcher = dispatcher; self.suggestionsViewController.discoverFeedMenuHandler = self; + self.suggestionsViewController.discoverFeedMetricsRecorder = + self.discoverFeedMetricsRecorder; self.discoverFeedHeaderDelegate = self.suggestionsViewController.discoverFeedHeaderDelegate;
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.h b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.h index f0bc509a..a238ad0 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.h +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.h
@@ -21,6 +21,7 @@ @protocol ContentSuggestionsViewControllerAudience; @protocol DiscoverFeedHeaderChanging; @protocol DiscoverFeedMenuCommands; +@class DiscoverFeedMetricsRecorder; @protocol OverscrollActionsControllerDelegate; @protocol SnackbarCommands; @protocol SuggestedContent; @@ -69,6 +70,9 @@ // Provider of menu configurations for the contentSuggestions component. @property(nonatomic, weak) id<ContentSuggestionsMenuProvider> menuProvider API_AVAILABLE(ios(13.0)); +// Discover Feed metrics recorder. +@property(nonatomic, strong) + DiscoverFeedMetricsRecorder* discoverFeedMetricsRecorder; - (void)setDataSource:(id<ContentSuggestionsDataSource>)dataSource; - (void)setDispatcher:(id<SnackbarCommands>)dispatcher;
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm index 2c6e706..4808b73 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm
@@ -28,6 +28,7 @@ #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_metrics_recording.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller_audience.h" #import "ios/chrome/browser/ui/content_suggestions/discover_feed_menu_commands.h" +#import "ios/chrome/browser/ui/content_suggestions/discover_feed_metrics_recorder.h" #import "ios/chrome/browser/ui/content_suggestions/ntp_home_constant.h" #import "ios/chrome/browser/ui/content_suggestions/theme_change_delegate.h" #import "ios/chrome/browser/ui/ntp/new_tab_page_header_constants.h" @@ -90,6 +91,9 @@ // Whether this VC is observing the discoverFeedHeight using KVO or not. @property(nonatomic, assign) BOOL observingDiscoverFeedHeight; +// The CollectionViewController scroll position when an scrolling event starts. +@property(nonatomic, assign) int scrollStartPosition; + @end @implementation ContentSuggestionsViewController @@ -742,6 +746,7 @@ - (void)scrollViewWillBeginDragging:(UIScrollView*)scrollView { [self.overscrollActionsController scrollViewWillBeginDragging:scrollView]; + self.scrollStartPosition = scrollView.contentOffset.y; } - (void)scrollViewDidEndDragging:(UIScrollView*)scrollView @@ -749,6 +754,8 @@ [super scrollViewDidEndDragging:scrollView willDecelerate:decelerate]; [self.overscrollActionsController scrollViewDidEndDragging:scrollView willDecelerate:decelerate]; + [self.discoverFeedMetricsRecorder + recordFeedScrolled:scrollView.contentOffset.y - self.scrollStartPosition]; } - (void)scrollViewWillEndDragging:(UIScrollView*)scrollView
diff --git a/ios/chrome/browser/ui/content_suggestions/discover_feed_metrics_recorder.h b/ios/chrome/browser/ui/content_suggestions/discover_feed_metrics_recorder.h index d3529ab..7284634b 100644 --- a/ios/chrome/browser/ui/content_suggestions/discover_feed_metrics_recorder.h +++ b/ios/chrome/browser/ui/content_suggestions/discover_feed_metrics_recorder.h
@@ -10,6 +10,9 @@ // Records different metrics for the NTP's Discover feed. @interface DiscoverFeedMetricsRecorder : NSObject +// Record metrics for when the user has scrolled |scrollDistance| in the Feed. +- (void)recordFeedScrolled:(int)scrollDistance; + // Record metrics for when the user has reached the bottom of their current // feed. - (void)recordInfiniteFeedTriggered;
diff --git a/ios/chrome/browser/ui/content_suggestions/discover_feed_metrics_recorder.mm b/ios/chrome/browser/ui/content_suggestions/discover_feed_metrics_recorder.mm index 54fea54..4b4102dc 100644 --- a/ios/chrome/browser/ui/content_suggestions/discover_feed_metrics_recorder.mm +++ b/ios/chrome/browser/ui/content_suggestions/discover_feed_metrics_recorder.mm
@@ -4,6 +4,7 @@ #import "ios/chrome/browser/ui/content_suggestions/discover_feed_metrics_recorder.h" +#import "base/mac/foundation_util.h" #import "base/metrics/histogram_macros.h" #import "base/metrics/user_metrics.h" #import "base/metrics/user_metrics_action.h" @@ -78,6 +79,19 @@ kMaxValue = kAddedToReadLater, }; +// Values for the UMA ContentSuggestions.Feed.EngagementType +// histogram. These values are persisted to logs. Entries should not be +// renumbered and numeric values should never be reused. This must be kept +// in sync with FeedEngagementType in enums.xml. +enum class FeedEngagementType { + kFeedEngaged = 0, + kFeedEngagedSimple = 1, + kFeedInteracted = 2, + kDeprecatedFeedScrolled = 3, + kFeedScrolled = 4, + kMaxValue = kFeedScrolled, +}; + namespace { // Histogram name for the infinite feed trigger. const char kDiscoverFeedInfiniteFeedTriggered[] = @@ -116,12 +130,48 @@ // User action name for infinite feed triggering. const char kDiscoverFeedUserActionInfiniteFeedTriggered[] = "ContentSuggestions.Feed.InfiniteFeedTriggered"; + +// Histogram name for the feed engagement types. +const char kDiscoverFeedEngagementTypeHistogram[] = + "ContentSuggestions.Feed.EngagementType"; + +// Minimum scrolling amount to record a FeedEngagementType::kFeedEngaged due to +// scrolling. +const int kMinScrollThreshold = 160; + +// Time between two metrics recorded to consider it a new session. +const int kMinutesBetweenSessions = 5; } // namespace +@interface DiscoverFeedMetricsRecorder () + +// Tracking property to avoid duplicate recordings of +// FeedEngagementType::kFeedEngagedSimple. +@property(nonatomic, assign) BOOL engagedSimpleReported; +// Tracking property to avoid duplicate recordings of +// FeedEngagementType::kFeedEngaged. +@property(nonatomic, assign) BOOL engagedReported; +// Tracking property to avoid duplicate recordings of +// FeedEngagementType::kFeedScrolled. +@property(nonatomic, assign) BOOL scrolledReported; +// The time when the first metric is being recorded for this session. +@property(nonatomic, assign) base::Time sessionStartTime; + +@end + @implementation DiscoverFeedMetricsRecorder #pragma mark - Public +- (void)recordFeedScrolled:(int)scrollDistance { + [self recordEngagement:scrollDistance interacted:NO]; + + if (!self.scrolledReported) { + [self recordEngagementTypeHistogram:FeedEngagementType::kFeedScrolled]; + self.scrolledReported = YES; + } +} + - (void)recordInfiniteFeedTriggered { UMA_HISTOGRAM_ENUMERATION(kDiscoverFeedInfiniteFeedTriggered, FeedLoadStreamStatus::kLoadedFromNetwork); @@ -202,6 +252,61 @@ // Records histogram metrics for Discover feed user actions. - (void)recordDiscoverFeedUserActionHistogram:(FeedUserActionType)actionType { UMA_HISTOGRAM_ENUMERATION(kDiscoverFeedUserActionHistogram, actionType); + [self recordInteraction]; +} + +// Records Feed engagement. +- (void)recordEngagement:(int)scrollDistance interacted:(BOOL)interacted { + scrollDistance = abs(scrollDistance); + + // Determine if this interaction is part of a new 'session'. + base::Time now = base::Time::Now(); + base::TimeDelta visitTimeout = + base::TimeDelta::FromMinutes(kMinutesBetweenSessions); + if (now - self.sessionStartTime > visitTimeout) { + [self finalizeSession]; + } + // Reset the last active time for session measurement. + self.sessionStartTime = now; + + // Report the user as engaged-simple if they have scrolled any amount or + // interacted with the card, and we have not already reported it for this + // chrome run. + if (!self.engagedSimpleReported && (scrollDistance > 0 || interacted)) { + [self recordEngagementTypeHistogram:FeedEngagementType::kFeedEngagedSimple]; + self.engagedSimpleReported = YES; + } + + // Report the user as engaged if they have scrolled more than the threshold or + // interacted with the card, and we have not already reported it this chrome + // run. + if (!self.engagedReported && + (scrollDistance > kMinScrollThreshold || interacted)) { + [self recordEngagementTypeHistogram:FeedEngagementType::kFeedEngaged]; + self.engagedReported = YES; + } +} + +// Records any direct interaction with the Feed, this doesn't include scrolling. +- (void)recordInteraction { + [self recordEngagement:0 interacted:YES]; + [self recordEngagementTypeHistogram:FeedEngagementType::kFeedInteracted]; +} + +// Records Engagement histograms of |engagementType|. +- (void)recordEngagementTypeHistogram:(FeedEngagementType)engagementType { + UMA_HISTOGRAM_ENUMERATION(kDiscoverFeedEngagementTypeHistogram, + engagementType); +} + +// Resets the session tracking values, this occurs if there's been +// kMinutesBetweenSessions minutes between sessions. +- (void)finalizeSession { + if (!self.engagedSimpleReported) + return; + self.engagedReported = NO; + self.engagedSimpleReported = NO; + self.scrolledReported = NO; } @end
diff --git a/ios/chrome/browser/ui/main/BUILD.gn b/ios/chrome/browser/ui/main/BUILD.gn index 7a91f3f..f0d9af44 100644 --- a/ios/chrome/browser/ui/main/BUILD.gn +++ b/ios/chrome/browser/ui/main/BUILD.gn
@@ -90,6 +90,7 @@ "//ios/chrome/browser/crash_report/breadcrumbs:feature_flags", "//ios/chrome/browser/first_run", "//ios/chrome/browser/main", + "//ios/chrome/browser/metrics", "//ios/chrome/browser/ntp:features", "//ios/chrome/browser/ntp_snippets:ntp_snippets", "//ios/chrome/browser/screenshot",
diff --git a/ios/chrome/browser/ui/main/scene_controller.mm b/ios/chrome/browser/ui/main/scene_controller.mm index 299bf3fe..12e217c4 100644 --- a/ios/chrome/browser/ui/main/scene_controller.mm +++ b/ios/chrome/browser/ui/main/scene_controller.mm
@@ -38,6 +38,7 @@ #import "ios/chrome/browser/main/browser_list.h" #import "ios/chrome/browser/main/browser_list_factory.h" #import "ios/chrome/browser/main/browser_util.h" +#import "ios/chrome/browser/metrics/previous_session_info.h" #include "ios/chrome/browser/ntp/features.h" #import "ios/chrome/browser/ntp_snippets/content_suggestions_scheduler_notifications.h" #include "ios/chrome/browser/screenshot/screenshot_delegate.h" @@ -296,6 +297,12 @@ level > SceneActivationLevelBackground && !self.hasInitializedUI; if (initializingUIInColdStart) { [self initializeUI]; + if (@available(iOS 13, *)) { + // Add the scene to the list of connected scene, to restore in case of + // crashes. + [[PreviousSessionInfo sharedInstance] + addSceneSessionID:sceneState.scene.session.persistentIdentifier]; + } } if (level == SceneActivationLevelForegroundActive) { @@ -340,6 +347,10 @@ } if (self.hasInitializedUI && level == SceneActivationLevelUnattached) { + if (@available(iOS 13, *)) { + [[PreviousSessionInfo sharedInstance] + removeSceneSessionID:sceneState.scene.session.persistentIdentifier]; + } [self teardownUI]; } }
diff --git a/ios/chrome/browser/ui/settings/password/BUILD.gn b/ios/chrome/browser/ui/settings/password/BUILD.gn index d72169d6..0ac4f31 100644 --- a/ios/chrome/browser/ui/settings/password/BUILD.gn +++ b/ios/chrome/browser/ui/settings/password/BUILD.gn
@@ -5,38 +5,24 @@ source_set("password") { configs += [ "//build/config/compiler:enable_arc" ] sources = [ - "legacy_password_details_table_view_controller.h", - "legacy_password_details_table_view_controller.mm", - "legacy_password_details_table_view_controller_delegate.h", - "password_exporter.h", - "password_exporter.mm", "password_issue_with_form.h", "password_issue_with_form.mm", "password_issues_coordinator.h", "password_issues_coordinator.mm", "password_issues_mediator.h", "password_issues_mediator.mm", - "passwords_consumer.h", + "passwords_coordinator.h", + "passwords_coordinator.mm", "passwords_mediator.h", "passwords_mediator.mm", - "passwords_table_view_controller.h", - "passwords_table_view_controller.mm", ] deps = [ - ":password_constants", ":password_ui", "//base", "//components/autofill/core/common", - "//components/google/core/common", - "//components/keyed_service/core", - "//components/password_manager/core/browser", "//components/password_manager/core/common", - "//components/prefs", - "//components/strings", - "//components/url_formatter", "//ios/chrome/app/strings", "//ios/chrome/browser", - "//ios/chrome/browser", "//ios/chrome/browser/browser_state", "//ios/chrome/browser/main:public", "//ios/chrome/browser/passwords", @@ -45,6 +31,56 @@ "//ios/chrome/browser/ui:feature_flags", "//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/coordinators:chrome_coordinators", + "//ios/chrome/browser/ui/settings/password/password_details", + "//ios/chrome/common", + "//ios/chrome/common/ui/colors", + "//ios/chrome/common/ui/reauthentication", + "//ui/base", + "//url", + ] + frameworks = [ "MobileCoreServices.framework" ] +} + +source_set("password_ui") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ + "legacy_password_details_table_view_controller.h", + "legacy_password_details_table_view_controller.mm", + "legacy_password_details_table_view_controller_delegate.h", + "password_exporter.h", + "password_exporter.mm", + "password_issue.h", + "password_issue_content_item.h", + "password_issue_content_item.mm", + "password_issues_consumer.h", + "password_issues_presenter.h", + "password_issues_table_view_controller.h", + "password_issues_table_view_controller.mm", + "passwords_consumer.h", + "passwords_settings_commands.h", + "passwords_table_view_controller.h", + "passwords_table_view_controller.mm", + "passwords_table_view_controller_delegate.h", + "passwords_table_view_controller_presentation_delegate.h", + ] + deps = [ + ":password_constants", + "//base", + "//components/autofill/core/common", + "//components/google/core/common", + "//components/password_manager/core/browser", + "//components/password_manager/core/common", + "//components/prefs", + "//components/strings", + "//components/url_formatter", + "//ios/chrome/app/strings", + "//ios/chrome/browser", + "//ios/chrome/browser/browser_state", + "//ios/chrome/browser/main:public", + "//ios/chrome/browser/passwords", + "//ios/chrome/browser/signin", + "//ios/chrome/browser/ui:feature_flags", + "//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/elements", "//ios/chrome/browser/ui/settings:settings_root", "//ios/chrome/browser/ui/settings/cells", @@ -53,6 +89,7 @@ "//ios/chrome/browser/ui/settings/password/password_details", "//ios/chrome/browser/ui/settings/utils", "//ios/chrome/browser/ui/table_view", + "//ios/chrome/browser/ui/table_view/cells", "//ios/chrome/browser/ui/table_view/cells:cells_constants", "//ios/chrome/browser/ui/util", "//ios/chrome/common", @@ -63,40 +100,7 @@ "//ios/chrome/common/ui/util", "//ios/third_party/material_components_ios", "//ui/base", - "//ui/base", "//ui/base/clipboard:clipboard_types", - "//url", - ] - frameworks = [ "MobileCoreServices.framework" ] -} - -source_set("password_ui") { - configs += [ "//build/config/compiler:enable_arc" ] - sources = [ - "password_issue.h", - "password_issue_content_item.h", - "password_issue_content_item.mm", - "password_issues_consumer.h", - "password_issues_presenter.h", - "password_issues_table_view_controller.h", - "password_issues_table_view_controller.mm", - ] - deps = [ - "//base", - "//components/autofill/core/common", - "//components/password_manager/core/browser", - "//components/password_manager/core/common", - "//components/prefs", - "//components/strings", - "//components/url_formatter", - "//ios/chrome/app/strings:ios_strings_grit", - "//ios/chrome/browser", - "//ios/chrome/browser/ui/settings:settings_root", - "//ios/chrome/browser/ui/settings/autofill", - "//ios/chrome/browser/ui/table_view/cells", - "//ios/chrome/browser/ui/util", - "//ios/chrome/common/ui/util", - "//ui/base", ] } @@ -116,7 +120,7 @@ "legacy_password_details_table_view_controller+testing.h", "password_exporter_for_testing.h", ] - deps = [ ":password" ] + deps = [ ":password_ui" ] } source_set("unit_tests") {
diff --git a/ios/chrome/browser/ui/settings/password/passwords_consumer.h b/ios/chrome/browser/ui/settings/password/passwords_consumer.h index 4435559..2f5f689 100644 --- a/ios/chrome/browser/ui/settings/password/passwords_consumer.h +++ b/ios/chrome/browser/ui/settings/password/passwords_consumer.h
@@ -7,6 +7,13 @@ #import <Foundation/Foundation.h> +#include <memory> +#include <vector> + +namespace autofill { +struct PasswordForm; +} + // Enum with all possible UI states of password check. typedef NS_ENUM(NSInteger, PasswordCheckUIState) { // When no compromised passwords were detected. @@ -27,7 +34,8 @@ @protocol PasswordsConsumer <NSObject> // Displays current password check UI state on screen. -- (void)setPasswordCheckUIState:(PasswordCheckUIState)state; +- (void)setPasswordCheckUIState:(PasswordCheckUIState)state + compromisedPasswordsCount:(NSInteger)count; // Displays password and blocked forms. - (void)setPasswordsForms:
diff --git a/ios/chrome/browser/ui/settings/password/passwords_coordinator.h b/ios/chrome/browser/ui/settings/password/passwords_coordinator.h new file mode 100644 index 0000000..e0b1071 --- /dev/null +++ b/ios/chrome/browser/ui/settings/password/passwords_coordinator.h
@@ -0,0 +1,43 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORDS_COORDINATOR_H_ +#define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORDS_COORDINATOR_H_ + +#import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h" + +class Browser; +@class PasswordsCoordinator; + +// Delegate for PasswordsCoordinator. +@protocol PasswordsCoordinatorDelegate + +// Called when the view controller is removed from navigation controller. +- (void)passwordsCoordinatorDidRemove:(PasswordsCoordinator*)coordinator; + +@end + +// This coordinator presents a list of saved passwords and some passwords +// related features. +@interface PasswordsCoordinator : ChromeCoordinator + +- (instancetype)initWithBaseNavigationController: + (UINavigationController*)navigationController + browser:(Browser*)browser + NS_DESIGNATED_INITIALIZER; + +- (instancetype)initWithBaseViewController:(UIViewController*)viewController + browser:(Browser*)browser NS_UNAVAILABLE; + +// Starts password check. For example, used by PasswordBreachDialog to +// automatically start the check. +- (void)checkSavedPasswords; + +@property(nonatomic, weak) id<PasswordsCoordinatorDelegate> delegate; + +@property(nonatomic, strong, readonly) UIViewController* viewController; + +@end + +#endif // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORDS_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/settings/password/passwords_coordinator.mm b/ios/chrome/browser/ui/settings/password/passwords_coordinator.mm new file mode 100644 index 0000000..a04abc1 --- /dev/null +++ b/ios/chrome/browser/ui/settings/password/passwords_coordinator.mm
@@ -0,0 +1,229 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/settings/password/passwords_coordinator.h" + +#include "base/metrics/histogram_functions.h" +#include "components/keyed_service/core/service_access_type.h" +#include "components/password_manager/core/browser/password_manager_metrics_util.h" +#include "components/password_manager/core/browser/password_store.h" +#include "components/password_manager/core/common/password_manager_features.h" +#import "ios/chrome/browser/main/browser.h" +#include "ios/chrome/browser/passwords/ios_chrome_password_check_manager.h" +#include "ios/chrome/browser/passwords/ios_chrome_password_check_manager_factory.h" +#include "ios/chrome/browser/passwords/ios_chrome_password_store_factory.h" +#include "ios/chrome/browser/signin/authentication_service_factory.h" +#include "ios/chrome/browser/sync/sync_setup_service_factory.h" +#import "ios/chrome/browser/ui/commands/application_commands.h" +#import "ios/chrome/browser/ui/commands/command_dispatcher.h" +#import "ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller.h" +#import "ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller_delegate.h" +#import "ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator.h" +#import "ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator_delegate.h" +#import "ios/chrome/browser/ui/settings/password/password_issues_coordinator.h" +#import "ios/chrome/browser/ui/settings/password/passwords_consumer.h" +#import "ios/chrome/browser/ui/settings/password/passwords_mediator.h" +#import "ios/chrome/browser/ui/settings/password/passwords_settings_commands.h" +#import "ios/chrome/browser/ui/settings/password/passwords_table_view_controller.h" +#import "ios/chrome/browser/ui/settings/password/passwords_table_view_controller_presentation_delegate.h" +#include "ios/chrome/browser/ui/ui_feature_flags.h" +#import "ios/chrome/common/ui/reauthentication/reauthentication_module.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@interface PasswordsCoordinator () < + LegacyPasswordDetailsTableViewControllerDelegate, + PasswordDetailsCoordinatorDelegate, + PasswordIssuesCoordinatorDelegate, + PasswordsSettingsCommands, + PasswordsTableViewControllerPresentationDelegate> + +// Main view controller for this coordinator. +@property(nonatomic, strong) + PasswordsTableViewController* passwordsViewController; + +// Main mediator for this coordinator. +@property(nonatomic, strong) PasswordsMediator* mediator; + +// Reauthentication module used by passwords export and password details. +@property(nonatomic, strong) ReauthenticationModule* reauthModule; + +// The dispatcher used by |viewController|. +@property(nonatomic, weak) + id<ApplicationCommands, BrowserCommands, BrowsingDataCommands> + dispatcher; + +// Coordinator for password details. +@property(nonatomic, strong) + PasswordIssuesCoordinator* passwordIssuesCoordinator; + +// Coordinator for password details. +@property(nonatomic, strong) + PasswordDetailsCoordinator* passwordDetailsCoordinator; + +@end + +@implementation PasswordsCoordinator + +@synthesize baseNavigationController = _baseNavigationController; + +- (instancetype)initWithBaseNavigationController: + (UINavigationController*)navigationController + browser:(Browser*)browser { + self = [super initWithBaseViewController:navigationController + browser:browser]; + if (self) { + _baseNavigationController = navigationController; + _dispatcher = static_cast< + id<BrowserCommands, ApplicationCommands, BrowsingDataCommands>>( + browser->GetCommandDispatcher()); + } + return self; +} + +- (void)checkSavedPasswords { + [self.mediator startPasswordCheck]; + base::UmaHistogramEnumeration( + "PasswordManager.BulkCheck.UserAction", + password_manager::metrics_util::PasswordCheckInteraction:: + kAutomaticPasswordCheck); +} + +- (UIViewController*)viewController { + return self.passwordsViewController; +} + +#pragma mark - ChromeCoordinator + +- (void)start { + self.mediator = [[PasswordsMediator alloc] + initWithPasswordStore:IOSChromePasswordStoreFactory::GetForBrowserState( + self.browser->GetBrowserState(), + ServiceAccessType::EXPLICIT_ACCESS) + passwordCheckManager:[self passwordCheckManager] + authService:AuthenticationServiceFactory::GetForBrowserState( + self.browser->GetBrowserState()) + syncService:SyncSetupServiceFactory::GetForBrowserState( + self.browser->GetBrowserState())]; + self.reauthModule = [[ReauthenticationModule alloc] + initWithSuccessfulReauthTimeAccessor:self.mediator]; + + self.passwordsViewController = + [[PasswordsTableViewController alloc] initWithBrowser:self.browser]; + + self.passwordsViewController.handler = self; + self.passwordsViewController.delegate = self.mediator; + self.passwordsViewController.dispatcher = self.dispatcher; + self.passwordsViewController.presentationDelegate = self; + self.passwordsViewController.reauthenticationModule = self.reauthModule; + + self.mediator.consumer = self.passwordsViewController; + + [self.baseNavigationController pushViewController:self.passwordsViewController + animated:YES]; +} + +- (void)stop { + self.passwordsViewController = nil; + + [self.passwordIssuesCoordinator stop]; + self.passwordIssuesCoordinator.delegate = nil; + self.passwordIssuesCoordinator = nil; + + [self.passwordDetailsCoordinator stop]; + self.passwordDetailsCoordinator.delegate = nil; + self.passwordDetailsCoordinator = nil; +} + +#pragma mark - PasswordsSettingsCommands + +- (void)showCompromisedPasswords { + DCHECK(!self.passwordIssuesCoordinator); + self.passwordIssuesCoordinator = [[PasswordIssuesCoordinator alloc] + initWithBaseNavigationController:self.baseNavigationController + browser:self.browser + passwordCheckManager:[self passwordCheckManager].get()]; + self.passwordIssuesCoordinator.delegate = self; + self.passwordIssuesCoordinator.reauthModule = self.reauthModule; + [self.passwordIssuesCoordinator start]; +} + +- (void)showDetailedViewForForm:(const autofill::PasswordForm&)form { + if (base::FeatureList::IsEnabled( + password_manager::features::kPasswordCheck)) { + DCHECK(!self.passwordDetailsCoordinator); + self.passwordDetailsCoordinator = [[PasswordDetailsCoordinator alloc] + initWithBaseNavigationController:self.baseNavigationController + browser:self.browser + password:form + reauthModule:self.reauthModule + passwordCheckManager:[self passwordCheckManager].get()]; + self.passwordDetailsCoordinator.delegate = self; + [self.passwordDetailsCoordinator start]; + } else { + LegacyPasswordDetailsTableViewController* controller = + [[LegacyPasswordDetailsTableViewController alloc] + initWithPasswordForm:form + delegate:self + reauthenticationModule:self.reauthModule]; + controller.dispatcher = self.dispatcher; + [self.baseNavigationController pushViewController:controller animated:YES]; + } +} + +#pragma mark - PasswordsTableViewControllerPresentationDelegate + +- (void)passwordsTableViewControllerDismissed { + [self.delegate passwordsCoordinatorDidRemove:self]; +} + +#pragma mark - PasswordIssuesCoordinatorDelegate + +- (void)passwordIssuesCoordinatorDidRemove: + (PasswordIssuesCoordinator*)coordinator { + DCHECK_EQ(self.passwordIssuesCoordinator, coordinator); + [self.passwordIssuesCoordinator stop]; + self.passwordIssuesCoordinator.delegate = nil; + self.passwordIssuesCoordinator = nil; +} + +- (BOOL)willHandlePasswordDeletion:(const autofill::PasswordForm&)password { + [self.passwordsViewController deletePasswordForm:password]; + return YES; +} + +#pragma mark PasswordDetailsCoordinatorDelegate + +- (void)passwordDetailsCoordinatorDidRemove: + (PasswordDetailsCoordinator*)coordinator { + DCHECK_EQ(self.passwordDetailsCoordinator, coordinator); + [self.passwordDetailsCoordinator stop]; + self.passwordDetailsCoordinator.delegate = nil; + self.passwordDetailsCoordinator = nil; +} + +- (void)passwordDetailsCoordinator:(PasswordDetailsCoordinator*)coordinator + deletePassword:(const autofill::PasswordForm&)password { + DCHECK_EQ(self.passwordDetailsCoordinator, coordinator); + [self.passwordsViewController deletePasswordForm:password]; +} + +#pragma mark LegacyPasswordDetailsTableViewControllerDelegate + +- (void)passwordDetailsTableViewController: + (LegacyPasswordDetailsTableViewController*)controller + deletePassword:(const autofill::PasswordForm&)form { + [self.passwordsViewController deletePasswordForm:form]; +} + +#pragma mark Private + +- (scoped_refptr<IOSChromePasswordCheckManager>)passwordCheckManager { + return IOSChromePasswordCheckManagerFactory::GetForBrowserState( + self.browser->GetBrowserState()); +} + +@end
diff --git a/ios/chrome/browser/ui/settings/password/passwords_mediator.h b/ios/chrome/browser/ui/settings/password/passwords_mediator.h index de7b8ad..de70e96 100644 --- a/ios/chrome/browser/ui/settings/password/passwords_mediator.h +++ b/ios/chrome/browser/ui/settings/password/passwords_mediator.h
@@ -8,6 +8,8 @@ #import <Foundation/Foundation.h> #include "base/memory/scoped_refptr.h" +#import "ios/chrome/browser/ui/settings/password/passwords_table_view_controller_delegate.h" +#import "ios/chrome/common/ui/reauthentication/reauthentication_module.h" class AuthenticationService; class IOSChromePasswordCheckManager; @@ -19,7 +21,8 @@ } // This mediator fetches and organises the passwords for its consumer. -@interface PasswordsMediator : NSObject +@interface PasswordsMediator : NSObject <PasswordsTableViewControllerDelegate, + SuccessfulReauthTimeAccessor> - (instancetype) initWithPasswordStore: @@ -34,15 +37,6 @@ @property(nonatomic, weak) id<PasswordsConsumer> consumer; -// Returns detailed information about error if applicable. -- (NSAttributedString*)passwordCheckErrorInfo; - -// Returns string containing the timestamp of the last password check. If the -// check finished less than 1 minute ago string will look "Last check just -// now.", otherwise "Last check X minutes/hours... ago.". If check never run -// string will be "Check never run.". -- (NSString*)formatElapsedTimeSinceLastCheck; - @end #endif // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORDS_MEDIATOR_H_
diff --git a/ios/chrome/browser/ui/settings/password/passwords_mediator.mm b/ios/chrome/browser/ui/settings/password/passwords_mediator.mm index efb8c662..9021bfce 100644 --- a/ios/chrome/browser/ui/settings/password/passwords_mediator.mm +++ b/ios/chrome/browser/ui/settings/password/passwords_mediator.mm
@@ -16,9 +16,7 @@ #import "ios/chrome/browser/signin/authentication_service.h" #include "ios/chrome/browser/sync/sync_setup_service.h" #import "ios/chrome/browser/ui/settings/password/passwords_consumer.h" -#import "ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h" #include "ios/chrome/browser/ui/ui_feature_flags.h" -#import "ios/chrome/browser/ui/util/uikit_ui_util.h" #import "ios/chrome/common/string_util.h" #import "ios/chrome/common/ui/colors/semantic_color_names.h" #include "ios/chrome/grit/ios_chromium_strings.h" @@ -68,6 +66,12 @@ PasswordCheckState _currentState; } +// Object storing the time of the previous successful re-authentication. +// This is meant to be used by the |ReauthenticationModule| for keeping +// re-authentications valid for a certain time interval within the scope +// of the Passwords Screen. +@property(nonatomic, strong, readonly) NSDate* successfulReauthTime; + @end @implementation PasswordsMediator @@ -116,10 +120,44 @@ password_manager::features::kPasswordCheck)) { _currentState = _passwordCheckManager->GetPasswordCheckState(); [self.consumer setPasswordCheckUIState: - [self computePasswordCheckUIStateWith:_currentState]]; + [self computePasswordCheckUIStateWith:_currentState] + compromisedPasswordsCount:_passwordCheckManager + ->GetCompromisedCredentials() + .size()]; } } +#pragma mark - PasswordsTableViewControllerDelegate + +- (void)startPasswordCheck { + _passwordCheckManager->StartPasswordCheck(); +} + +- (NSString*)formatElapsedTimeSinceLastCheck { + base::Time lastCompletedCheck = + _passwordCheckManager->GetLastPasswordCheckTime(); + + // lastCompletedCheck is 0.0 in case the check never completely ran before. + if (lastCompletedCheck == base::Time()) + return l10n_util::GetNSString(IDS_IOS_CHECK_NEVER_RUN); + + base::TimeDelta elapsedTime = base::Time::Now() - lastCompletedCheck; + + NSString* timestamp; + // If check finished in less than |kJustCheckedTimeThresholdInMinutes| show + // "just now" instead of timestamp. + if (elapsedTime < kJustCheckedTimeThresholdInMinutes) + timestamp = l10n_util::GetNSString(IDS_IOS_CHECK_FINISHED_JUST_NOW); + else + timestamp = base::SysUTF8ToNSString( + base::UTF16ToUTF8(ui::TimeFormat::SimpleWithMonthAndYear( + ui::TimeFormat::FORMAT_ELAPSED, ui::TimeFormat::LENGTH_LONG, + elapsedTime, true))); + + return l10n_util::GetNSStringF(IDS_IOS_LAST_COMPLETED_CHECK, + base::SysNSStringToUTF16(timestamp)); +} + - (NSAttributedString*)passwordCheckErrorInfo { if (!_passwordCheckManager->GetCompromisedCredentials().empty()) return nil; @@ -165,7 +203,10 @@ DCHECK(self.consumer); [self.consumer - setPasswordCheckUIState:[self computePasswordCheckUIStateWith:state]]; + setPasswordCheckUIState:[self computePasswordCheckUIStateWith:state] + compromisedPasswordsCount:_passwordCheckManager + ->GetCompromisedCredentials() + .size()]; } - (void)compromisedCredentialsDidChange: @@ -176,8 +217,10 @@ return; DCHECK(self.consumer); + [self.consumer setPasswordCheckUIState: - [self computePasswordCheckUIStateWith:_currentState]]; + [self computePasswordCheckUIStateWith:_currentState] + compromisedPasswordsCount:credentials.size()]; } #pragma mark - Private Methods @@ -265,29 +308,14 @@ [self.consumer setPasswordsForms:std::move(results)]; } -- (NSString*)formatElapsedTimeSinceLastCheck { - base::Time lastCompletedCheck = - _passwordCheckManager->GetLastPasswordCheckTime(); +#pragma mark SuccessfulReauthTimeAccessor - // lastCompletedCheck is 0.0 in case the check never completely ran before. - if (lastCompletedCheck == base::Time()) - return l10n_util::GetNSString(IDS_IOS_CHECK_NEVER_RUN); +- (void)updateSuccessfulReauthTime { + _successfulReauthTime = [[NSDate alloc] init]; +} - base::TimeDelta elapsedTime = base::Time::Now() - lastCompletedCheck; - - NSString* timestamp; - // If check finished in less than |kJustCheckedTimeThresholdInMinutes| show - // "just now" instead of timestamp. - if (elapsedTime < kJustCheckedTimeThresholdInMinutes) - timestamp = l10n_util::GetNSString(IDS_IOS_CHECK_FINISHED_JUST_NOW); - else - timestamp = base::SysUTF8ToNSString( - base::UTF16ToUTF8(ui::TimeFormat::SimpleWithMonthAndYear( - ui::TimeFormat::FORMAT_ELAPSED, ui::TimeFormat::LENGTH_LONG, - elapsedTime, true))); - - return l10n_util::GetNSStringF(IDS_IOS_LAST_COMPLETED_CHECK, - base::SysNSStringToUTF16(timestamp)); +- (NSDate*)lastSuccessfulReauthTime { + return [self successfulReauthTime]; } @end
diff --git a/ios/chrome/browser/ui/settings/password/passwords_mediator_unittest.mm b/ios/chrome/browser/ui/settings/password/passwords_mediator_unittest.mm index 25c978b3..d01a9426 100644 --- a/ios/chrome/browser/ui/settings/password/passwords_mediator_unittest.mm +++ b/ios/chrome/browser/ui/settings/password/passwords_mediator_unittest.mm
@@ -72,7 +72,8 @@ @implementation FakePasswordsConsumer -- (void)setPasswordCheckUIState:(PasswordCheckUIState)state { +- (void)setPasswordCheckUIState:(PasswordCheckUIState)state + compromisedPasswordsCount:(NSInteger)count { } - (void)setPasswordsForms:
diff --git a/ios/chrome/browser/ui/settings/password/passwords_settings_commands.h b/ios/chrome/browser/ui/settings/password/passwords_settings_commands.h new file mode 100644 index 0000000..02caa73 --- /dev/null +++ b/ios/chrome/browser/ui/settings/password/passwords_settings_commands.h
@@ -0,0 +1,21 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORDS_SETTINGS_COMMANDS_H_ +#define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORDS_SETTINGS_COMMANDS_H_ + +#import <Foundation/Foundation.h> + +// Commands relative to the passwords in the Settings. +@protocol PasswordsSettingsCommands <NSObject> + +// Shows the screen with password issues. +- (void)showCompromisedPasswords; + +// Shows passwords details. +- (void)showDetailedViewForForm:(const autofill::PasswordForm&)form; + +@end + +#endif // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORDS_SETTINGS_COMMANDS_H_
diff --git a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.h b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.h index e5edaac..7a98ab71 100644 --- a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.h +++ b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.h
@@ -5,34 +5,45 @@ #ifndef IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORDS_TABLE_VIEW_CONTROLLER_H_ #define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORDS_TABLE_VIEW_CONTROLLER_H_ -#import "ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller_delegate.h" +#import "ios/chrome/browser/ui/settings/password/passwords_consumer.h" #import "ios/chrome/browser/ui/settings/settings_controller_protocol.h" #import "ios/chrome/browser/ui/settings/settings_navigation_controller.h" #import "ios/chrome/browser/ui/settings/settings_root_table_view_controller.h" +#import "ios/chrome/common/ui/reauthentication/reauthentication_module.h" class Browser; -@protocol ReauthenticationProtocol; @class PasswordExporter; +@protocol PasswordsSettingsCommands; +@protocol PasswordsTableViewControllerDelegate; +@protocol PasswordsTableViewControllerPresentationDelegate; @interface PasswordsTableViewController - : SettingsRootTableViewController <SettingsControllerProtocol> + : SettingsRootTableViewController <PasswordsConsumer, + SettingsControllerProtocol> // The designated initializer. |browser| must not be nil. - (instancetype)initWithBrowser:(Browser*)browser NS_DESIGNATED_INITIALIZER; - (instancetype)initWithStyle:(UITableViewStyle)style NS_UNAVAILABLE; -// Starts password check. -- (void)startPasswordCheck; +// Deletes passed password form and updates list accordingly. +- (void)deletePasswordForm:(const autofill::PasswordForm&)form; + +@property(nonatomic, weak) id<PasswordsSettingsCommands> handler; + +// Delegate. +@property(nonatomic, weak) id<PasswordsTableViewControllerDelegate> delegate; + +@property(nonatomic, weak) id<PasswordsTableViewControllerPresentationDelegate> + presentationDelegate; + +// Reauthentication module. +@property(nonatomic, strong) id<ReauthenticationProtocol> + reauthenticationModule; @end -@interface PasswordsTableViewController (Testing) < - LegacyPasswordDetailsTableViewControllerDelegate> - -// Initializes the password exporter with a (fake) |reauthenticationModule|. -- (void)setReauthenticationModuleForExporter: - (id<ReauthenticationProtocol>)reauthenticationModule; +@interface PasswordsTableViewController (Testing) // Returns the password exporter to allow setting fake testing objects on it. - (PasswordExporter*)getPasswordExporter;
diff --git a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm index df5ce1638..11f1dd4 100644 --- a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm
@@ -6,17 +6,11 @@ #import <UIKit/UIKit.h> -#include "base/check_op.h" #include "base/ios/ios_util.h" #include "base/mac/foundation_util.h" #include "base/metrics/histogram_functions.h" -#include "base/metrics/histogram_macros.h" #include "base/metrics/user_metrics.h" -#include "base/metrics/user_metrics_action.h" -#include "base/notreached.h" -#include "base/numerics/safe_conversions.h" #include "base/strings/sys_string_conversions.h" -#include "base/strings/utf_string_conversions.h" #include "components/autofill/core/common/password_form.h" #include "components/google/core/common/google_util.h" #include "components/keyed_service/core/service_access_type.h" @@ -28,41 +22,28 @@ #include "components/password_manager/core/browser/ui/password_check_referrer.h" #include "components/password_manager/core/common/password_manager_features.h" #include "components/password_manager/core/common/password_manager_pref_names.h" -#include "components/prefs/pref_member.h" #include "components/prefs/pref_service.h" #include "components/strings/grit/components_strings.h" -#include "components/url_formatter/url_formatter.h" #include "ios/chrome/browser/application_context.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #import "ios/chrome/browser/main/browser.h" -#include "ios/chrome/browser/passwords/ios_chrome_password_check_manager.h" -#include "ios/chrome/browser/passwords/ios_chrome_password_check_manager_factory.h" #include "ios/chrome/browser/passwords/ios_chrome_password_store_factory.h" -#import "ios/chrome/browser/passwords/save_passwords_consumer.h" -#import "ios/chrome/browser/signin/authentication_service.h" -#include "ios/chrome/browser/signin/authentication_service_factory.h" #import "ios/chrome/browser/signin/chrome_identity_service_observer_bridge.h" -#include "ios/chrome/browser/sync/sync_setup_service_factory.h" #include "ios/chrome/browser/system_flags.h" #import "ios/chrome/browser/ui/elements/home_waiting_view.h" -#import "ios/chrome/browser/ui/settings/cells/settings_cells_constants.h" #import "ios/chrome/browser/ui/settings/cells/settings_check_cell.h" #import "ios/chrome/browser/ui/settings/cells/settings_check_item.h" #import "ios/chrome/browser/ui/settings/cells/settings_switch_cell.h" #import "ios/chrome/browser/ui/settings/cells/settings_switch_item.h" #import "ios/chrome/browser/ui/settings/elements/enterprise_info_popover_view_controller.h" -#import "ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller.h" -#import "ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller_delegate.h" -#import "ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator.h" -#import "ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator_delegate.h" #import "ios/chrome/browser/ui/settings/password/password_exporter.h" -#import "ios/chrome/browser/ui/settings/password/password_issues_coordinator.h" #import "ios/chrome/browser/ui/settings/password/passwords_consumer.h" -#import "ios/chrome/browser/ui/settings/password/passwords_mediator.h" +#import "ios/chrome/browser/ui/settings/password/passwords_settings_commands.h" #import "ios/chrome/browser/ui/settings/password/passwords_table_view_constants.h" +#import "ios/chrome/browser/ui/settings/password/passwords_table_view_controller_delegate.h" +#import "ios/chrome/browser/ui/settings/password/passwords_table_view_controller_presentation_delegate.h" #import "ios/chrome/browser/ui/settings/utils/pref_backed_boolean.h" #import "ios/chrome/browser/ui/settings/utils/settings_utils.h" -#import "ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h" #import "ios/chrome/browser/ui/table_view/cells/table_view_detail_text_item.h" #import "ios/chrome/browser/ui/table_view/cells/table_view_info_button_cell.h" #import "ios/chrome/browser/ui/table_view/cells/table_view_info_button_item.h" @@ -71,7 +52,6 @@ #import "ios/chrome/browser/ui/table_view/cells/table_view_text_item.h" #import "ios/chrome/browser/ui/table_view/table_view_navigation_controller_constants.h" #include "ios/chrome/browser/ui/ui_feature_flags.h" -#include "ios/chrome/browser/ui/util/ui_util.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" #import "ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.h" #import "ios/chrome/common/ui/colors/semantic_color_names.h" @@ -185,18 +165,12 @@ @interface PasswordsTableViewController () < BooleanObserver, ChromeIdentityServiceObserver, - LegacyPasswordDetailsTableViewControllerDelegate, - PasswordDetailsCoordinatorDelegate, PasswordExporterDelegate, PasswordExportActivityViewControllerDelegate, PasswordsConsumer, - PasswordIssuesCoordinatorDelegate, PopoverLabelViewControllerDelegate, - UISearchControllerDelegate, UISearchBarDelegate, - SuccessfulReauthTimeAccessor> { - // Mediator is owned here because there is no coordinator. - PasswordsMediator* _mediator; + UISearchControllerDelegate> { // The observable boolean that binds to the password manager setting state. // Saved passwords are only on if the password manager is enabled. PrefBackedBoolean* _passwordManagerEnabled; @@ -212,8 +186,6 @@ TableViewTextItem* _checkForProblemsItem; // The item related to the button for exporting passwords. TableViewTextItem* _exportPasswordsItem; - // The service responsible for password check feature. - scoped_refptr<IOSChromePasswordCheckManager> _passwordCheck; // The interface for getting and manipulating a user's saved passwords. scoped_refptr<password_manager::PasswordStore> _passwordStore; // The list of the user's saved passwords. @@ -230,14 +202,6 @@ ChromeBrowserState* _browserState; // Authentication Service Observer. std::unique_ptr<ChromeIdentityServiceObserverBridge> _identityServiceObserver; - // Object storing the time of the previous successful re-authentication. - // This is meant to be used by the |ReauthenticationModule| for keeping - // re-authentications valid for a certain time interval within the scope - // of the Save Passwords Settings. - NSDate* _successfulReauthTime; - // Module containing the reauthentication mechanism for viewing and copying - // passwords. - ReauthenticationModule* _reauthenticationModule; // Boolean containing whether the export operation is ready. This implies that // the exporter is idle and there is at least one saved passwords to export. BOOL _exportReady; @@ -247,8 +211,6 @@ // Alert informing the user that passwords are being prepared for // export. UIAlertController* _preparingPasswordsAlert; - // Coordinator for passwords issues screen. - PasswordIssuesCoordinator* _passwordIssuesCoordinator; } // Object handling passwords export operations. @@ -271,9 +233,8 @@ // Current state of the Password Check. @property(nonatomic, assign) PasswordCheckUIState passwordCheckState; -// Coordinator for password details. -@property(nonatomic, strong) - PasswordDetailsCoordinator* passwordDetailsCoordinator; +// Number of compromised passwords. +@property(assign) NSInteger compromisedPasswordsCount; @end @@ -290,11 +251,6 @@ if (self) { _browser = browser; _browserState = browser->GetBrowserState(); - _reauthenticationModule = [[ReauthenticationModule alloc] - initWithSuccessfulReauthTimeAccessor:self]; - _passwordExporter = [[PasswordExporter alloc] - initWithReauthenticationModule:_reauthenticationModule - delegate:self]; self.exampleHeaders = [[NSMutableDictionary alloc] init]; self.title = l10n_util::GetNSString(IDS_IOS_PASSWORDS); self.shouldHideDoneButton = YES; @@ -302,16 +258,6 @@ _passwordStore = IOSChromePasswordStoreFactory::GetForBrowserState( _browserState, ServiceAccessType::EXPLICIT_ACCESS); DCHECK(_passwordStore); - _passwordCheck = - IOSChromePasswordCheckManagerFactory::GetForBrowserState(_browserState); - _mediator = [[PasswordsMediator alloc] - initWithPasswordStore:_passwordStore - passwordCheckManager:_passwordCheck - authService:AuthenticationServiceFactory::GetForBrowserState( - _browserState) - syncService:SyncSetupServiceFactory::GetForBrowserState( - _browserState)]; - _mediator.consumer = self; _passwordManagerEnabled = [[PrefBackedBoolean alloc] initWithPrefService:_browserState->GetPrefs() prefName:password_manager::prefs::kCredentialsEnableService]; @@ -322,12 +268,12 @@ return self; } -- (void)startPasswordCheck { - if (_passwordCheck->GetPasswordCheckState() != PasswordCheckState::kRunning) { - _passwordCheck->StartPasswordCheck(); - UmaHistogramEnumeration("PasswordManager.BulkCheck.UserAction", - PasswordCheckInteraction::kAutomaticPasswordCheck); - } +- (void)setReauthenticationModule: + (ReauthenticationModule*)reauthenticationModule { + _reauthenticationModule = reauthenticationModule; + _passwordExporter = [[PasswordExporter alloc] + initWithReauthenticationModule:_reauthenticationModule + delegate:self]; } #pragma mark - UIViewController @@ -408,6 +354,13 @@ forBarMetrics:UIBarMetricsDefault]; } +- (void)didMoveToParentViewController:(UIViewController*)parent { + [super didMoveToParentViewController:parent]; + if (!parent) { + [self.presentationDelegate passwordsTableViewControllerDismissed]; + } +} + - (void)setEditing:(BOOL)editing animated:(BOOL)animated { [super setEditing:editing animated:animated]; if (editing) { @@ -551,14 +504,6 @@ if (self.navigationItem.searchController.active == YES) { self.navigationItem.searchController.active = NO; } - - [_passwordIssuesCoordinator stop]; - _passwordIssuesCoordinator.delegate = nil; - _passwordIssuesCoordinator = nil; - - [self.passwordDetailsCoordinator stop]; - self.passwordDetailsCoordinator.delegate = nil; - self.passwordDetailsCoordinator = nil; } #pragma mark - Items @@ -621,7 +566,7 @@ TableViewLinkHeaderFooterItem* footerItem = [[TableViewLinkHeaderFooterItem alloc] initWithType:ItemTypeLastCheckTimestampFooter]; - footerItem.text = [_mediator formatElapsedTimeSinceLastCheck]; + footerItem.text = [self.delegate formatElapsedTimeSinceLastCheck]; return footerItem; } @@ -724,7 +669,7 @@ // Called when user tapped on the information button of the password check // item. Shows popover with detailed description of an error. - (void)didTapPasswordCheckInfoButton:(UIButton*)buttonView { - NSAttributedString* info = [_mediator passwordCheckErrorInfo]; + NSAttributedString* info = [self.delegate passwordCheckErrorInfo]; // If no info returned by mediator handle this tap as tap on a cell. if (!info) { [self showPasswordIssuesPage]; @@ -745,7 +690,9 @@ #pragma mark - PasswordsConsumer -- (void)setPasswordCheckUIState:(PasswordCheckUIState)state { +- (void)setPasswordCheckUIState:(PasswordCheckUIState)state + compromisedPasswordsCount:(NSInteger)count { + self.compromisedPasswordsCount = count; // Update password check status and check button with new state. [self updatePasswordCheckButtonWithState:state]; [self updatePasswordCheckStatusLabelWithState:state]; @@ -923,21 +870,6 @@ [self searchForTerm:searchText]; } -#pragma mark - PasswordIssuesCoordinatorDelegate - -- (void)passwordIssuesCoordinatorDidRemove: - (PasswordIssuesCoordinator*)coordinator { - DCHECK_EQ(_passwordIssuesCoordinator, coordinator); - [_passwordIssuesCoordinator stop]; - _passwordIssuesCoordinator.delegate = nil; - _passwordIssuesCoordinator = nil; -} - -- (BOOL)willHandlePasswordDeletion:(const autofill::PasswordForm&)password { - [self deletePasswordForm:password]; - return YES; -} - #pragma mark - Private methods // Shows loading spinner background view. @@ -1188,7 +1120,7 @@ _passwordProblemsItem.detailText = base::SysUTF16ToNSString(l10n_util::GetPluralStringFUTF16( IDS_IOS_CHECK_PASSWORDS_COMPROMISED_COUNT, - _passwordCheck->GetCompromisedCredentials().size())); + self.compromisedPasswordsCount)); UIImage* unSafeIconImage = [[UIImage imageNamed:@"settings_unsafe_state"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; _passwordProblemsItem.trailingImage = unSafeIconImage; @@ -1199,7 +1131,7 @@ break; } case PasswordCheckStateSafe: { - DCHECK(_passwordCheck->GetCompromisedCredentials().empty()); + DCHECK(!self.compromisedPasswordsCount); UIImage* safeIconImage = [[UIImage imageNamed:@"settings_safe_state"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; _passwordProblemsItem.detailText = @@ -1302,29 +1234,6 @@ } } -- (void)openDetailedViewForForm:(const autofill::PasswordForm&)form { - if (base::FeatureList::IsEnabled( - password_manager::features::kPasswordCheck)) { - DCHECK(!self.passwordDetailsCoordinator); - self.passwordDetailsCoordinator = [[PasswordDetailsCoordinator alloc] - initWithBaseNavigationController:self.navigationController - browser:_browser - password:form - reauthModule:_reauthenticationModule - passwordCheckManager:_passwordCheck.get()]; - self.passwordDetailsCoordinator.delegate = self; - [self.passwordDetailsCoordinator start]; - } else { - LegacyPasswordDetailsTableViewController* controller = - [[LegacyPasswordDetailsTableViewController alloc] - initWithPasswordForm:form - delegate:self - reauthenticationModule:_reauthenticationModule]; - controller.dispatcher = self.dispatcher; - [self.navigationController pushViewController:controller animated:YES]; - } -} - - (void)deleteItemAtIndexPaths:(NSArray<NSIndexPath*>*)indexPaths { // Ensure indexPaths are sorted to maintain delete logic, and keep track of // number of items deleted to adjust index for accessing elements in the @@ -1416,17 +1325,10 @@ } - (void)showPasswordIssuesPage { - if (_passwordCheck->GetCompromisedCredentials().empty() || - _passwordCheck->GetPasswordCheckState() == PasswordCheckState::kRunning) + if (!self.compromisedPasswordsCount || + self.passwordCheckState == PasswordCheckStateRunning) return; - DCHECK(!_passwordIssuesCoordinator); - _passwordIssuesCoordinator = [[PasswordIssuesCoordinator alloc] - initWithBaseNavigationController:self.navigationController - browser:_browser - passwordCheckManager:_passwordCheck.get()]; - _passwordIssuesCoordinator.delegate = self; - _passwordIssuesCoordinator.reauthModule = _reauthenticationModule; - [_passwordIssuesCoordinator start]; + [self.handler showCompromisedPasswords]; password_manager::LogPasswordCheckReferrer( password_manager::PasswordCheckReferrer::kPasswordSettings); } @@ -1459,7 +1361,7 @@ SavedFormContentItem* saveFormItem = base::mac::ObjCCastStrict<SavedFormContentItem>( [model itemAtIndexPath:indexPath]); - [self openDetailedViewForForm:*saveFormItem.form]; + [self.handler showDetailedViewForForm:*saveFormItem.form]; break; } case ItemTypeBlocked: { @@ -1468,7 +1370,7 @@ BlockedFormContentItem* blockedItem = base::mac::ObjCCastStrict<BlockedFormContentItem>( [model itemAtIndexPath:indexPath]); - [self openDetailedViewForForm:*blockedItem.form]; + [self.handler showDetailedViewForForm:*blockedItem.form]; break; } case ItemTypeExportPasswordsButton: @@ -1480,7 +1382,7 @@ break; case ItemTypeCheckForProblemsButton: if (self.passwordCheckState != PasswordCheckStateRunning) { - _passwordCheck->StartPasswordCheck(); + [self.delegate startPasswordCheck]; UmaHistogramEnumeration("PasswordManager.BulkCheck.UserAction", PasswordCheckInteraction::kManualPasswordCheck); } @@ -1582,40 +1484,6 @@ return cell; } -#pragma mark PasswordDetailsCoordinatorDelegate - -- (void)passwordDetailsCoordinatorDidRemove: - (PasswordDetailsCoordinator*)coordinator { - DCHECK_EQ(self.passwordDetailsCoordinator, coordinator); - [self.passwordDetailsCoordinator stop]; - self.passwordDetailsCoordinator.delegate = nil; - self.passwordDetailsCoordinator = nil; -} - -- (void)passwordDetailsCoordinator:(PasswordDetailsCoordinator*)coordinator - deletePassword:(const autofill::PasswordForm&)password { - DCHECK_EQ(self.passwordDetailsCoordinator, coordinator); - [self deletePasswordForm:password]; -} - -#pragma mark LegacyPasswordDetailsTableViewControllerDelegate - -- (void)passwordDetailsTableViewController: - (LegacyPasswordDetailsTableViewController*)controller - deletePassword:(const autofill::PasswordForm&)form { - [self deletePasswordForm:form]; -} - -#pragma mark SuccessfulReauthTimeAccessor - -- (void)updateSuccessfulReauthTime { - _successfulReauthTime = [[NSDate alloc] init]; -} - -- (NSDate*)lastSuccessfulReauthTime { - return _successfulReauthTime; -} - #pragma mark PasswordExporterDelegate - (void)showSetPasscodeDialog { @@ -1798,13 +1666,6 @@ #pragma mark - Testing -- (void)setReauthenticationModuleForExporter: - (id<ReauthenticationProtocol>)reauthenticationModule { - _passwordExporter = [[PasswordExporter alloc] - initWithReauthenticationModule:reauthenticationModule - delegate:self]; -} - - (PasswordExporter*)getPasswordExporter { return _passwordExporter; }
diff --git a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller_delegate.h b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller_delegate.h new file mode 100644 index 0000000..efa2005 --- /dev/null +++ b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller_delegate.h
@@ -0,0 +1,27 @@ +// 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. + +#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORDS_TABLE_VIEW_CONTROLLER_DELEGATE_H_ +#define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORDS_TABLE_VIEW_CONTROLLER_DELEGATE_H_ + +#import <Foundation/Foundation.h> + +// Delegate for |PasswordsTableViewController|. +@protocol PasswordsTableViewControllerDelegate + +// Starts password check. +- (void)startPasswordCheck; + +// Returns string containing the timestamp of the last password check. If the +// check finished less than 1 minute ago string will look "Last check just +// now.", otherwise "Last check X minutes/hours... ago.". If check never run +// string will be "Check never run.". +- (NSString*)formatElapsedTimeSinceLastCheck; + +// Returns detailed information about Password Check error if applicable. +- (NSAttributedString*)passwordCheckErrorInfo; + +@end + +#endif // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORDS_TABLE_VIEW_CONTROLLER_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller_presentation_delegate.h b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller_presentation_delegate.h new file mode 100644 index 0000000..49bdcdf --- /dev/null +++ b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller_presentation_delegate.h
@@ -0,0 +1,18 @@ +// 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. + +#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORDS_TABLE_VIEW_CONTROLLER_PRESENTATION_DELEGATE_H_ +#define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORDS_TABLE_VIEW_CONTROLLER_PRESENTATION_DELEGATE_H_ + +#import <Foundation/Foundation.h> + +// Presentation delegate for |PasswordsTableViewController|. +@protocol PasswordsTableViewControllerPresentationDelegate + +// Called when |PasswordsTableViewController| is dismissed. +- (void)passwordsTableViewControllerDismissed; + +@end + +#endif // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORDS_TABLE_VIEW_CONTROLLER_PRESENTATION_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller_unittest.mm index 2c3479d..c703455 100644 --- a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller_unittest.mm
@@ -21,13 +21,14 @@ #include "ios/chrome/browser/main/test_browser.h" #include "ios/chrome/browser/passwords/ios_chrome_bulk_leak_check_service_factory.h" #include "ios/chrome/browser/passwords/ios_chrome_password_check_manager.h" +#include "ios/chrome/browser/passwords/ios_chrome_password_check_manager_factory.h" #include "ios/chrome/browser/passwords/ios_chrome_password_store_factory.h" #include "ios/chrome/browser/passwords/password_check_observer_bridge.h" #include "ios/chrome/browser/passwords/save_passwords_consumer.h" #import "ios/chrome/browser/ui/settings/cells/settings_check_item.h" #import "ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller.h" -#import "ios/chrome/browser/ui/settings/password/password_issues_coordinator.h" #import "ios/chrome/browser/ui/settings/password/passwords_consumer.h" +#import "ios/chrome/browser/ui/settings/password/passwords_mediator.h" #import "ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h" #import "ios/chrome/browser/ui/table_view/cells/table_view_detail_text_item.h" #include "ios/chrome/browser/ui/table_view/chrome_table_view_controller_test.h" @@ -57,7 +58,6 @@ // this file working. @interface PasswordsTableViewController (Test) < UISearchBarDelegate, - PasswordIssuesCoordinatorDelegate, PasswordsConsumer> - (void)updateExportPasswordsButton; @end @@ -111,9 +111,21 @@ CreateController(); + mediator_ = [[PasswordsMediator alloc] + initWithPasswordStore:IOSChromePasswordStoreFactory::GetForBrowserState( + browser_->GetBrowserState(), + ServiceAccessType::EXPLICIT_ACCESS) + passwordCheckManager:IOSChromePasswordCheckManagerFactory:: + GetForBrowserState( + browser_->GetBrowserState()) + authService:nil + syncService:nil]; + // Inject some fake passwords to pass the loading state. PasswordsTableViewController* passwords_controller = static_cast<PasswordsTableViewController*>(controller()); + passwords_controller.delegate = mediator_; + mediator_.consumer = passwords_controller; [passwords_controller setPasswordsForms:{}]; } @@ -154,7 +166,9 @@ void ChangePasswordCheckState(PasswordCheckUIState state) { PasswordsTableViewController* passwords_controller = static_cast<PasswordsTableViewController*>(controller()); - [passwords_controller setPasswordCheckUIState:state]; + NSInteger count = GetTestStore().compromised_credentials().size(); + [passwords_controller setPasswordCheckUIState:state + compromisedPasswordsCount:count]; } // Adds a form to PasswordsTableViewController. @@ -284,6 +298,7 @@ web::WebTaskEnvironment task_environment_; std::unique_ptr<TestBrowser> browser_; base::test::ScopedFeatureList scoped_feature_list_; + PasswordsMediator* mediator_; }; // Tests default case has no saved sites and no blocked sites. @@ -502,35 +517,6 @@ UIAccessibilityTraitNotEnabled); } -TEST_P(PasswordsTableViewControllerTest, PropagateDeletionToStore) { - PasswordsTableViewController* passwords_controller = - static_cast<PasswordsTableViewController*>(controller()); - autofill::PasswordForm form; - form.url = GURL("http://www.example.com/accounts/LoginAuth"); - form.action = GURL("http://www.example.com/accounts/Login"); - form.username_element = base::ASCIIToUTF16("Email"); - form.username_value = base::ASCIIToUTF16("test@egmail.com"); - form.password_element = base::ASCIIToUTF16("Passwd"); - form.password_value = base::ASCIIToUTF16("test"); - form.submit_element = base::ASCIIToUTF16("signIn"); - form.signon_realm = "http://www.example.com/"; - form.scheme = autofill::PasswordForm::Scheme::kHtml; - form.blocked_by_user = false; - - AddPasswordForm(std::make_unique<autofill::PasswordForm>(form)); - - if (GetParam().password_check_enabled) { - autofill::PasswordForm formFromStore = - GetTestStore().stored_passwords().at("http://www.example.com/")[0]; - [passwords_controller passwordDetailsTableViewController:nil - deletePassword:formFromStore]; - RunUntilIdle(); - } else { - [passwords_controller passwordDetailsTableViewController:nil - deletePassword:form]; - } -} - // Tests filtering of items. TEST_P(PasswordsTableViewControllerTest, FilterItems) { AddSavedForm1(); @@ -760,7 +746,7 @@ auto password = GetTestStore().stored_passwords().at("http://www.example.com/").at(0); - EXPECT_TRUE([passwords_controller willHandlePasswordDeletion:password]); + [passwords_controller deletePasswordForm:password]; EXPECT_EQ(1, NumberOfItemsInSection(GetSectionIndex(SavedPasswords))); }
diff --git a/ios/chrome/browser/ui/settings/settings_navigation_controller.mm b/ios/chrome/browser/ui/settings/settings_navigation_controller.mm index b55a1fe..7ba7c23 100644 --- a/ios/chrome/browser/ui/settings/settings_navigation_controller.mm +++ b/ios/chrome/browser/ui/settings/settings_navigation_controller.mm
@@ -18,7 +18,7 @@ #import "ios/chrome/browser/ui/settings/google_services/google_services_settings_coordinator.h" #import "ios/chrome/browser/ui/settings/google_services/google_services_settings_view_controller.h" #import "ios/chrome/browser/ui/settings/import_data_table_view_controller.h" -#import "ios/chrome/browser/ui/settings/password/passwords_table_view_controller.h" +#import "ios/chrome/browser/ui/settings/password/passwords_coordinator.h" #import "ios/chrome/browser/ui/settings/settings_table_view_controller.h" #import "ios/chrome/browser/ui/settings/sync/sync_encryption_passphrase_table_view_controller.h" #import "ios/chrome/browser/ui/settings/utils/settings_utils.h" @@ -39,6 +39,7 @@ @interface SettingsNavigationController () < GoogleServicesSettingsCoordinatorDelegate, + PasswordsCoordinatorDelegate, UIAdaptivePresentationControllerDelegate, UINavigationControllerDelegate> @@ -46,6 +47,9 @@ @property(nonatomic, strong) GoogleServicesSettingsCoordinator* googleServicesSettingsCoordinator; +// Saved passwords settings coordinator. +@property(nonatomic, strong) PasswordsCoordinator* savedPasswordsCoordinator; + // Current UIViewController being presented by this Navigation Controller. // If nil it means the Navigation Controller is not presenting anything, or the // VC being presented doesn't conform to @@ -143,22 +147,17 @@ delegate startPasswordCheckAutomatically:(BOOL)startCheck { DCHECK(browser); - PasswordsTableViewController* controller = - [[PasswordsTableViewController alloc] initWithBrowser:browser]; - controller.dispatcher = [delegate handlerForSettings]; - if (startCheck) { - [controller startPasswordCheck]; - } SettingsNavigationController* nc = [[SettingsNavigationController alloc] - initWithRootViewController:controller + initWithRootViewController:nil browser:browser delegate:delegate]; - [controller navigationItem].rightBarButtonItem = [nc doneButton]; + [nc showSavedPasswordsAndStartPasswordCheck:startCheck]; // Make sure the cancel button is always present, as the Save Passwords screen // isn't just shown from Settings. - [controller navigationItem].leftBarButtonItem = [nc cancelButton]; + [nc.savedPasswordsCoordinator.viewController navigationItem] + .leftBarButtonItem = [nc cancelButton]; return nc; } @@ -315,9 +314,10 @@ } } - // GoogleServicesSettingsCoordinator must be stopped before dismissing the - // sync settings view. + // GoogleServicesSettingsCoordinator and PasswordsCoordinator must be stopped + // before dismissing the sync settings view. [self stopGoogleServicesSettingsCoordinator]; + [self stopPasswordsCoordinator]; // Reset the delegate to prevent any queued transitions from attempting to // close the settings. @@ -384,6 +384,26 @@ self.googleServicesSettingsCoordinator = nil; } +// Shows the saved passwords and starts the password check is +// |startPasswordCheck| is true. +- (void)showSavedPasswordsAndStartPasswordCheck:(BOOL)startPasswordCheck { + self.savedPasswordsCoordinator = [[PasswordsCoordinator alloc] + initWithBaseNavigationController:self + browser:self.browser]; + self.savedPasswordsCoordinator.delegate = self; + [self.savedPasswordsCoordinator start]; + if (startPasswordCheck) { + [self.savedPasswordsCoordinator checkSavedPasswords]; + } +} + +// Stops the underlying passwords coordinator if it exists. +- (void)stopPasswordsCoordinator { + [self.savedPasswordsCoordinator stop]; + self.savedPasswordsCoordinator.delegate = nil; + self.savedPasswordsCoordinator = nil; +} + #pragma mark - GoogleServicesSettingsCoordinatorDelegate - (void)googleServicesSettingsCoordinatorDidRemove: @@ -392,6 +412,13 @@ [self stopGoogleServicesSettingsCoordinator]; } +#pragma mark - PasswordsCoordinatorDelegate + +- (void)passwordsCoordinatorDidRemove:(PasswordsCoordinator*)coordinator { + DCHECK_EQ(self.savedPasswordsCoordinator, coordinator); + [self stopPasswordsCoordinator]; +} + #pragma mark - UIAdaptivePresentationControllerDelegate - (BOOL)presentationControllerShouldDismiss: @@ -526,19 +553,12 @@ // TODO(crbug.com/779791) : Do not pass |baseViewController| through dispatcher. - (void)showSavedPasswordsSettingsFromViewController: (UIViewController*)baseViewController { - PasswordsTableViewController* controller = - [[PasswordsTableViewController alloc] initWithBrowser:self.browser]; - controller.dispatcher = [self.settingsNavigationDelegate handlerForSettings]; - [self pushViewController:controller animated:YES]; + [self showSavedPasswordsAndStartPasswordCheck:NO]; } - (void)showSavedPasswordsSettingsAndStartPasswordCheckFromViewController: (UIViewController*)baseViewController { - PasswordsTableViewController* controller = - [[PasswordsTableViewController alloc] initWithBrowser:self.browser]; - controller.dispatcher = [self.settingsNavigationDelegate handlerForSettings]; - [controller startPasswordCheck]; - [self pushViewController:controller animated:YES]; + [self showSavedPasswordsAndStartPasswordCheck:YES]; } // TODO(crbug.com/779791) : Do not pass |baseViewController| through dispatcher.
diff --git a/ios/chrome/browser/ui/settings/settings_table_view_controller.mm b/ios/chrome/browser/ui/settings/settings_table_view_controller.mm index cfa1d1f..2fdd549 100644 --- a/ios/chrome/browser/ui/settings/settings_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/settings_table_view_controller.mm
@@ -63,7 +63,7 @@ #import "ios/chrome/browser/ui/settings/google_services/google_services_settings_coordinator.h" #import "ios/chrome/browser/ui/settings/language/language_settings_mediator.h" #import "ios/chrome/browser/ui/settings/language/language_settings_table_view_controller.h" -#import "ios/chrome/browser/ui/settings/password/passwords_table_view_controller.h" +#import "ios/chrome/browser/ui/settings/password/passwords_coordinator.h" #import "ios/chrome/browser/ui/settings/privacy/privacy_coordinator.h" #import "ios/chrome/browser/ui/settings/safety_check/safety_check_coordinator.h" #import "ios/chrome/browser/ui/settings/search_engine_table_view_controller.h" @@ -178,6 +178,7 @@ GoogleServicesSettingsCoordinatorDelegate, IdentityManagerObserverBridgeDelegate, PasswordCheckObserver, + PasswordsCoordinatorDelegate, PopoverLabelViewControllerDelegate, PrefObserverDelegate, PrivacyCoordinatorDelegate, @@ -225,6 +226,9 @@ // Safety Check coordinator. SafetyCheckCoordinator* _safetyCheckCoordinator; + // Passwords coordinator. + PasswordsCoordinator* _passwordsCoordinator; + // Cached resized profile image. UIImage* _resizedImage; __weak UIImage* _oldImage; @@ -955,8 +959,7 @@ case ItemTypePasswords: base::RecordAction( base::UserMetricsAction("Options_ShowPasswordManager")); - controller = - [[PasswordsTableViewController alloc] initWithBrowser:_browser]; + [self showPasswords]; break; case ItemTypeAutofillCreditCard: base::RecordAction(base::UserMetricsAction("AutofillCreditCardsViewed")); @@ -1112,6 +1115,15 @@ [_googleServicesSettingsCoordinator start]; } +- (void)showPasswords { + DCHECK(!_passwordsCoordinator); + _passwordsCoordinator = [[PasswordsCoordinator alloc] + initWithBaseNavigationController:self.navigationController + browser:_browser]; + _passwordsCoordinator.delegate = self; + [_passwordsCoordinator start]; +} + // Shows Safety Check Screen. - (void)showSafetyCheck { DCHECK(!_safetyCheckCoordinator); @@ -1337,6 +1349,10 @@ [_safetyCheckCoordinator stop]; _safetyCheckCoordinator = nil; + [_passwordsCoordinator stop]; + _passwordsCoordinator.delegate = nil; + _passwordsCoordinator = nil; + [_privacyCoordinator stop]; _privacyCoordinator = nil; @@ -1539,6 +1555,15 @@ _safetyCheckCoordinator = nil; } +#pragma mark - SafetyCheckCoordinatorDelegate + +- (void)passwordsCoordinatorDidRemove:(PasswordsCoordinator*)coordinator { + DCHECK_EQ(_passwordsCoordinator, coordinator); + [_passwordsCoordinator stop]; + _passwordsCoordinator.delegate = nil; + _passwordsCoordinator = nil; +} + #pragma mark - PrivacyCoordinatorDelegate - (void)privacyCoordinatorViewControllerWasRemoved:
diff --git a/ios/chrome/test/app/BUILD.gn b/ios/chrome/test/app/BUILD.gn index d823234..9538c02 100644 --- a/ios/chrome/test/app/BUILD.gn +++ b/ios/chrome/test/app/BUILD.gn
@@ -79,6 +79,7 @@ "//ios/chrome/browser/ui/settings", "//ios/chrome/browser/ui/settings:settings_root", "//ios/chrome/browser/ui/settings/password", + "//ios/chrome/browser/ui/settings/password:password_ui", "//ios/chrome/browser/ui/settings/password:test_support", "//ios/chrome/browser/ui/tab_grid", "//ios/chrome/browser/ui/tabs",
diff --git a/ios/chrome/test/app/password_test_util.mm b/ios/chrome/test/app/password_test_util.mm index 370884e..56b6cfe9 100644 --- a/ios/chrome/test/app/password_test_util.mm +++ b/ios/chrome/test/app/password_test_util.mm
@@ -76,8 +76,8 @@ PasswordsTableViewController* passwords_table_view_controller = base::mac::ObjCCastStrict<PasswordsTableViewController>( settings_navigation_controller.topViewController); - [passwords_table_view_controller - setReauthenticationModuleForExporter:mock_reauthentication_module]; + passwords_table_view_controller.reauthenticationModule = + mock_reauthentication_module; return mock_reauthentication_module; }
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.mm b/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.mm index f25c107..f3cc6d6 100644 --- a/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.mm +++ b/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.mm
@@ -702,7 +702,8 @@ variations::VariationsIdsProvider* provider = variations::VariationsIdsProvider::GetInstance(); std::vector<variations::VariationID> ids = provider->GetVariationsVector( - variations::GOOGLE_WEB_PROPERTIES_ANY_CONTEXT); + {variations::GOOGLE_WEB_PROPERTIES_ANY_CONTEXT, + variations::GOOGLE_WEB_PROPERTIES_FIRST_PARTY}); return std::find(ids.begin(), ids.end(), variationID) != ids.end(); } @@ -710,7 +711,8 @@ variations::VariationsIdsProvider* provider = variations::VariationsIdsProvider::GetInstance(); std::vector<variations::VariationID> ids = provider->GetVariationsVector( - variations::GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT); + {variations::GOOGLE_WEB_PROPERTIES_TRIGGER_ANY_CONTEXT, + variations::GOOGLE_WEB_PROPERTIES_TRIGGER_FIRST_PARTY}); return std::find(ids.begin(), ids.end(), variationID) != ids.end(); }
diff --git a/ios/public/provider/chrome/browser/discover_feed/discover_feed_configuration.h b/ios/public/provider/chrome/browser/discover_feed/discover_feed_configuration.h index be398150..a929c62f 100644 --- a/ios/public/provider/chrome/browser/discover_feed/discover_feed_configuration.h +++ b/ios/public/provider/chrome/browser/discover_feed/discover_feed_configuration.h
@@ -8,6 +8,7 @@ #import <Foundation/Foundation.h> class ChromeBrowserState; +@class DiscoverFeedMetricsRecorder; // Configuration object used by the DiscoverFeedProvider. @interface DiscoverFeedConfiguration : NSObject @@ -15,6 +16,9 @@ // BrowserState used by DiscoverFeedProvider; @property(nonatomic, assign) ChromeBrowserState* browserState; +// DiscoverFeed metrics recorder used by DiscoverFeedProvider; +@property(nonatomic, strong) DiscoverFeedMetricsRecorder* metricsRecorder; + @end #endif // IOS_PUBLIC_PROVIDER_CHROME_BROWSER_DISCOVER_FEED_DISCOVER_FEED_CONFIGURATION_H_
diff --git a/ios/web/navigation/wk_navigation_util_unittest.mm b/ios/web/navigation/wk_navigation_util_unittest.mm index 12a33fe..16c714d6 100644 --- a/ios/web/navigation/wk_navigation_util_unittest.mm +++ b/ios/web/navigation/wk_navigation_util_unittest.mm
@@ -197,8 +197,6 @@ // Extract session JSON from restoration URL. base::JSONReader::ValueWithError value_with_error = ExtractSessionDict(restore_session_url); - ASSERT_EQ(base::ValueDeserializer::kErrorCodeNoError, - value_with_error.error_code); ASSERT_TRUE(value_with_error.value.has_value()); // Verify that all titles and URLs are present. @@ -233,8 +231,6 @@ // Extract session JSON from restoration URL. base::JSONReader::ValueWithError value_with_error = ExtractSessionDict(restore_session_url); - ASSERT_EQ(base::ValueDeserializer::kErrorCodeNoError, - value_with_error.error_code); ASSERT_TRUE(value_with_error.value.has_value()); // Verify that first kMaxSessionSize titles and URLs are present. @@ -279,8 +275,6 @@ // Extract session JSON from restoration URL. base::JSONReader::ValueWithError value_with_error = ExtractSessionDict(restore_session_url); - ASSERT_EQ(base::ValueDeserializer::kErrorCodeNoError, - value_with_error.error_code); ASSERT_TRUE(value_with_error.value.has_value()); // Verify that last kMaxSessionSize titles and URLs are present. @@ -326,8 +320,6 @@ // Extract session JSON from restoration URL. base::JSONReader::ValueWithError value_with_error = ExtractSessionDict(restore_session_url); - ASSERT_EQ(base::ValueDeserializer::kErrorCodeNoError, - value_with_error.error_code); ASSERT_TRUE(value_with_error.value.has_value()); // Verify that last kMaxSessionSize titles and URLs are present.
diff --git a/ios/web/webui/mojo_facade.mm b/ios/web/webui/mojo_facade.mm index c11b9c1..9014994 100644 --- a/ios/web/webui/mojo_facade.mm +++ b/ios/web/webui/mojo_facade.mm
@@ -81,8 +81,6 @@ base::JSON_PARSE_RFC); CHECK(value_with_error.value); CHECK(value_with_error.value->is_dict()); - CHECK_EQ(base::ValueDeserializer::kErrorCodeNoError, - value_with_error.error_code); const std::string* name = value_with_error.value->FindStringKey("name"); CHECK(name);
diff --git a/media/capture/video/mac/video_capture_device_avfoundation_mac.mm b/media/capture/video/mac/video_capture_device_avfoundation_mac.mm index 7073f0c..460c56e 100644 --- a/media/capture/video/mac/video_capture_device_avfoundation_mac.mm +++ b/media/capture/video/mac/video_capture_device_avfoundation_mac.mm
@@ -11,7 +11,6 @@ #include <stdint.h> #include "base/location.h" -#include "base/logging.h" #include "base/mac/foundation_util.h" #include "base/mac/mac_util.h" #include "base/metrics/histogram_macros.h" @@ -31,6 +30,22 @@ constexpr int kTimeToWaitBeforeStoppingStillImageCaptureInSeconds = 60; +base::TimeDelta GetCMSampleBufferTimestamp(CMSampleBufferRef sampleBuffer) { + const CMTime cm_timestamp = + CMSampleBufferGetPresentationTimeStamp(sampleBuffer); + const base::TimeDelta timestamp = + CMTIME_IS_VALID(cm_timestamp) + ? base::TimeDelta::FromSecondsD(CMTimeGetSeconds(cm_timestamp)) + : media::kNoTimestamp; + return timestamp; +} + +std::string MacFourCCToString(OSType fourcc) { + char arr[] = {fourcc >> 24, (fourcc >> 16) & 255, (fourcc >> 8) & 255, + fourcc & 255, 0}; + return arr; +} + } // anonymous namespace @implementation VideoCaptureDeviceAVFoundation @@ -120,6 +135,7 @@ return NO; } [_captureVideoDataOutput setAlwaysDiscardsLateVideoFrames:true]; + [_captureVideoDataOutput setSampleBufferDelegate:self queue:dispatch_get_global_queue( @@ -157,6 +173,9 @@ best_fourcc = kCMPixelFormat_422YpCbCr8; } + VLOG(2) << __func__ << ": configuring '" << MacFourCCToString(best_fourcc) + << "' " << width << "x" << height << "@" << frameRate; + // The capture output has to be configured, despite Mac documentation // detailing that setting the sessionPreset would be enough. The reason for // this mismatch is probably because most of the AVFoundation docs are written @@ -409,22 +428,69 @@ } } -// |captureOutput| is called by the capture device to deliver a new frame. -// AVFoundation calls from a number of threads, depending on, at least, if -// Chrome is on foreground or background. -- (void)captureOutput:(AVCaptureOutput*)captureOutput - didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer - fromConnection:(AVCaptureConnection*)connection { +- (void)processRamSample:(CMSampleBufferRef)sampleBuffer + baseAddress:(const void*)baseAddress + frameSize:(size_t)frameSize + pixelFormatType:(OSType)pixelFormat { + VLOG(3) << __func__ << ": format: " << MacFourCCToString(pixelFormat); const CMFormatDescriptionRef formatDescription = CMSampleBufferGetFormatDescription(sampleBuffer); - const FourCharCode fourcc = - CMFormatDescriptionGetMediaSubType(formatDescription); const CMVideoDimensions dimensions = CMVideoFormatDescriptionGetDimensions(formatDescription); const media::VideoCaptureFormat captureFormat( gfx::Size(dimensions.width, dimensions.height), _frameRate, - media::FourCCToChromiumPixelFormat(fourcc)); - gfx::ColorSpace colorSpace; + media::FourCCToChromiumPixelFormat(pixelFormat)); + base::TimeDelta timestamp = GetCMSampleBufferTimestamp(sampleBuffer); + base::AutoLock lock(_lock); + if (_frameReceiver && baseAddress) { + gfx::ColorSpace colorSpace; + // TODO(julien.isorce): move GetImageBufferColorSpace(CVImageBufferRef) + // from media::VTVideoDecodeAccelerator to media/base/mac and call it + // here to get the color space. See https://crbug.com/959962. + // colorSpace = media::GetImageBufferColorSpace(videoFrame); + _frameReceiver->ReceiveFrame(reinterpret_cast<const uint8_t*>(baseAddress), + frameSize, captureFormat, colorSpace, 0, 0, + timestamp); + } +} + +- (void)processRawSample:(CMSampleBufferRef)sampleBuffer { + VLOG(3) << __func__; + // Trust |_frameReceiver| to do decompression. + char* baseAddress = 0; + size_t frameSize = 0; + media::ExtractBaseAddressAndLength(&baseAddress, &frameSize, sampleBuffer); + [self processRamSample:sampleBuffer + baseAddress:baseAddress + frameSize:frameSize + pixelFormatType:CMFormatDescriptionGetMediaSubType( + CMSampleBufferGetFormatDescription(sampleBuffer))]; +} + +- (void)processSample:(CMSampleBufferRef)sampleBuffer + withImageBuffer:(CVImageBufferRef)videoFrame { + if (CVPixelBufferLockBaseAddress(videoFrame, kCVPixelBufferLock_ReadOnly) != + kCVReturnSuccess) { + return [self processRawSample:sampleBuffer]; + } + void* baseAddress = + static_cast<char*>(CVPixelBufferGetBaseAddress(videoFrame)); + size_t frameSize = CVPixelBufferGetHeight(videoFrame) * + CVPixelBufferGetBytesPerRow(videoFrame); + [self processRamSample:sampleBuffer + baseAddress:baseAddress + frameSize:frameSize + pixelFormatType:CVPixelBufferGetPixelFormatType(videoFrame)]; + CVPixelBufferUnlockBaseAddress(videoFrame, kCVPixelBufferLock_ReadOnly); +} + +// |captureOutput| is called by the capture device to deliver a new frame. +// Since the callback is configured to happen on a global dispatch queue, calls +// may enter here concurrently and on any thread. +- (void)captureOutput:(AVCaptureOutput*)captureOutput + didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer + fromConnection:(AVCaptureConnection*)connection { + VLOG(3) << __func__; // We have certain format expectation for capture output: // For MJPEG, |sampleBuffer| is expected to always be a CVBlockBuffer. @@ -433,51 +499,12 @@ // plugins/virtual cameras. In order to find out whether it is CVBlockBuffer // or CVImageBuffer we call CMSampleBufferGetImageBuffer() and check if the // return value is nil. - char* baseAddress = 0; - size_t frameSize = 0; - CVImageBufferRef videoFrame = nil; - if (fourcc != kCMVideoCodecType_JPEG_OpenDML) { - videoFrame = CMSampleBufferGetImageBuffer(sampleBuffer); - // Lock the frame and calculate frame size. - if (videoFrame && - CVPixelBufferLockBaseAddress(videoFrame, kCVPixelBufferLock_ReadOnly) == - kCVReturnSuccess) { - baseAddress = static_cast<char*>(CVPixelBufferGetBaseAddress(videoFrame)); - frameSize = CVPixelBufferGetHeight(videoFrame) * - CVPixelBufferGetBytesPerRow(videoFrame); - - // TODO(julien.isorce): move GetImageBufferColorSpace(CVImageBufferRef) - // from media::VTVideoDecodeAccelerator to media/base/mac and call it - // here to get the color space. See https://crbug.com/959962. - // colorSpace = media::GetImageBufferColorSpace(videoFrame); - } else { - videoFrame = nil; - } + CVImageBufferRef videoFrame = CMSampleBufferGetImageBuffer(sampleBuffer); + if (videoFrame) { + [self processSample:sampleBuffer withImageBuffer:videoFrame]; + } else { + [self processRawSample:sampleBuffer]; } - if (!videoFrame) { - media::ExtractBaseAddressAndLength(&baseAddress, &frameSize, sampleBuffer); - } - - { - base::AutoLock lock(_lock); - const CMTime cm_timestamp = - CMSampleBufferGetPresentationTimeStamp(sampleBuffer); - const base::TimeDelta timestamp = - CMTIME_IS_VALID(cm_timestamp) - ? base::TimeDelta::FromMicroseconds( - cm_timestamp.value * base::TimeTicks::kMicrosecondsPerSecond / - cm_timestamp.timescale) - : media::kNoTimestamp; - - if (_frameReceiver && baseAddress) { - _frameReceiver->ReceiveFrame(reinterpret_cast<uint8_t*>(baseAddress), - frameSize, captureFormat, colorSpace, 0, 0, - timestamp); - } - } - - if (videoFrame) - CVPixelBufferUnlockBaseAddress(videoFrame, kCVPixelBufferLock_ReadOnly); } - (void)onVideoError:(NSNotification*)errorNotification {
diff --git a/mojo/public/cpp/bindings/README.md b/mojo/public/cpp/bindings/README.md index 0a9b3073..a15cf13 100644 --- a/mojo/public/cpp/bindings/README.md +++ b/mojo/public/cpp/bindings/README.md
@@ -1159,7 +1159,7 @@ interface which itself already has a primary interface. If you want to test an associated interface endpoint without first -associating it, you can use `AssociatedRemote::BindNewEndpointAndPassDedicatedReceiverForTesting`. +associating it, you can use `AssociatedRemote::BindNewEndpointAndPassDedicatedReceiver`. This will create working associated interface endpoints which are not actually associated with anything else.
diff --git a/mojo/public/cpp/bindings/associated_receiver.h b/mojo/public/cpp/bindings/associated_receiver.h index f2857dc..f03b37d 100644 --- a/mojo/public/cpp/bindings/associated_receiver.h +++ b/mojo/public/cpp/bindings/associated_receiver.h
@@ -145,8 +145,8 @@ // // For testing, where the returned request is bound to e.g. a mock and there // are no other interfaces involved. - PendingAssociatedRemote<Interface> - BindNewEndpointAndPassDedicatedRemoteForTesting() WARN_UNUSED_RESULT { + PendingAssociatedRemote<Interface> BindNewEndpointAndPassDedicatedRemote() + WARN_UNUSED_RESULT { DCHECK(!is_bound()) << "AssociatedReceiver is already bound"; MessagePipe pipe;
diff --git a/mojo/public/cpp/bindings/associated_remote.h b/mojo/public/cpp/bindings/associated_remote.h index 32b010c..d8e09bc9 100644 --- a/mojo/public/cpp/bindings/associated_remote.h +++ b/mojo/public/cpp/bindings/associated_remote.h
@@ -180,8 +180,8 @@ // // For testing, where the returned request is bound to e.g. a mock and there // are no other interfaces involved. - PendingAssociatedReceiver<Interface> - BindNewEndpointAndPassDedicatedReceiverForTesting() WARN_UNUSED_RESULT { + PendingAssociatedReceiver<Interface> BindNewEndpointAndPassDedicatedReceiver() + WARN_UNUSED_RESULT { MessagePipe pipe; scoped_refptr<internal::MultiplexRouter> router0 = new internal::MultiplexRouter(
diff --git a/net/http/transport_security_state_static.json b/net/http/transport_security_state_static.json index 1e36aded..6d1592f 100644 --- a/net/http/transport_security_state_static.json +++ b/net/http/transport_security_state_static.json
@@ -7601,7 +7601,6 @@ { "name": "riaucybersolution.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "rk6.cz", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "royzez.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "rtd.uk.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "runtondev.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "safcstore.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "sakaserver.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -17235,7 +17234,6 @@ { "name": "exehack.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "frolova.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "firebounty.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "fistu.la", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "foo.hamburg", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "frolov.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "fushee.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -24423,7 +24421,6 @@ { "name": "openrainbow.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "openspace.xxx", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "opiates.ca", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "opiates.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "opin.me", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "opioids.co.uk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "opioids.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -32084,7 +32081,6 @@ { "name": "telos-analytics.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "test.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "the-body-shop.hu", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, - { "name": "thestoryshack.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "timco.cloud", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "tsurezurematome.ga", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, { "name": "type1joe.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true }, @@ -39201,7 +39197,6 @@ { "name": "api.biz.tr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "appeldorn.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "appliancerepairlosangeles.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "aqualysis.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "archmediamarketing.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "area4pro.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "artificial.army", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -42626,7 +42621,6 @@ { "name": "linext.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "linkat4.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lk-hardware.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "localblitz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lsws.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lukas-gorr.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "luminaires-online.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -45495,7 +45489,6 @@ { "name": "silke-hunde.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "silvacor-ziegel.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "simplecoding.click", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "sitebuilderreport.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "sitehome.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "sitesource101.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "sitevandaag.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -45949,7 +45942,6 @@ { "name": "gdprhallofshame.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "gepps.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "getprivacy.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "getprivacy.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "gfe.li", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "gfe.link", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "gfelite.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -46173,7 +46165,6 @@ { "name": "mpa-pro.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "mtasa.hu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "musicompare.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "muzhijy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "my-stuff-online.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "mygigabitnation.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "myjudo.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -47465,7 +47456,6 @@ { "name": "full-stack.ninja", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "fyretrine.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "g0881.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "garbomuffin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "getweloop.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "gippert-klein.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "gogroopie.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -48515,7 +48505,6 @@ { "name": "zlaty-tyden.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "zlatytyden.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "zq789.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "1288fc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "12photos.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "20zq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "319k3.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -50094,7 +50083,6 @@ { "name": "antiekboerderijgraafland.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "apo-deutschland.biz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "aquelarreweb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "arnevankauter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "arose.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "atelierfantazie.sk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "austinlockout.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -50618,7 +50606,6 @@ { "name": "udancy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "uhssl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "uniontestprep.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "uptakedigital.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "upwardtraining.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "upyourfinances.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "uraimo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -51740,7 +51727,6 @@ { "name": "rochakhand-knitcraft.com.np", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "rocketsandtutus.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "roninitconsulting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "rosnertexte.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "roundtablekzn.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "royal806.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "royal810.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -53055,7 +53041,6 @@ { "name": "elielaloum.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "eligibilis.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "epicdowney.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "esc.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "estetistarimini.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "estudio21pattern.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "eurodentaire.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -55613,7 +55598,6 @@ { "name": "interguard.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "interlijn.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "invoicehippo.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "inwao.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "irgwebsites.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "irish.radio", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "irishradioplayer.radio", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -58584,7 +58568,6 @@ { "name": "openstandia.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "opportunityliu.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "optimaner.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "ordoh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ore.cool", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "osolutionscorp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ostachstore.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -58604,7 +58587,6 @@ { "name": "panamatrippin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "paniodpolskiego.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "paragontasarim.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "partyshop.ge", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "parys.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "patrykwegrzynek.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "pause-canap.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -59213,7 +59195,6 @@ { "name": "miamaibaum.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "mifibra.cl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "mindsetatx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "mistaken.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "mjpak.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "moecraft.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "mora.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -59770,7 +59751,6 @@ { "name": "dadadani.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "danads.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "dapianw.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "dare.deals", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "darf.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "dead-letter.email", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "deepspace4.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -61105,7 +61085,6 @@ { "name": "sipyuru.lk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "sklepvoip.tel", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "skremovals.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "smits.frl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "somethingsomething.work", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "sophiahatstudio.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "speakersbusiness.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -63139,7 +63118,6 @@ { "name": "acupunturamadrid.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "acupunturavalencia.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "adamsasphaltpaving.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "administratie-smits.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ae86sb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "aero.parts", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ag88.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -68449,7 +68427,6 @@ { "name": "italiataxi.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "itaporanga.se.gov.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "itmx.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "izs8.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "japanese-cuisine.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "jecurranpc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "jobit.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -68500,7 +68477,6 @@ { "name": "k88801.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "k88870.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "k88891.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "k89188.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "k89388.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "k89999.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "k8dc01.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -68540,7 +68516,6 @@ { "name": "lc8guidance.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lc8md03.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lc8md30.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "lc98.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lc9852.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lc9910.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lecheng.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -79070,39 +79045,6 @@ { "name": "00168365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "00228555.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "00228999.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "00228aa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "00228b.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "00228bb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "00228c.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "00228cc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "00228d.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "00228dd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "00228e.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "00228ee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "00228f.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "00228g.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "00228gg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "00228h.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "00228hh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "00228jj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "00228k.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "00228kk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "00228m.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "00228mm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "00228nn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "00228p.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "00228pp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "00228q.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "00228r.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "00228rr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "00228s.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "00228ss.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "00228t.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "00228tt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "00228u.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "00228v.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "00228vip1.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "00228vip3.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "00365t.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "01365t.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "02365t.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -79121,7 +79063,6 @@ { "name": "1111365t.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "111365t.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "11168365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "1119968.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "11365t.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "123365t.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "12365t.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -79237,80 +79178,15 @@ { "name": "89365t.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "96002e.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "99365t.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968131.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968166.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "9968282.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968363.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "9968389.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968393.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "9968404.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968505.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968508.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "9968535.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968595.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968600.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968656.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968707.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968717.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968838.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968959.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968969.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "9968aa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "9968aaa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968ab.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968abc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968app.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968bbb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968caipiao.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968cc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968ccc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968com.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968dd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968ddd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968ee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968eee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "9968ff.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968fff.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968gg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968ggg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968go.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968hh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968hhh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968ii.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968iii.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968jj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968jjj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968ll.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968lll.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968mm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968mmm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968nn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968nnn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968ok.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968oo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968ooo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968pp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968ppp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968qq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968qqq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968rr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968rrr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968ss.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968sss.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968ttt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968uu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968uuu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "9968vv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968vvv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968ww.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968www.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "9968xl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968xx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968xxx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968yy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968yyy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968zz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968zzz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "999321365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "999365t.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "99qp.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -79563,7 +79439,6 @@ { "name": "geohoney.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "getbookked.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "getsmarterinsurance.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "go9968.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "goc4wraps.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "grand-city38.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "grimm.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -79677,7 +79552,6 @@ { "name": "penconsultants.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "philipdeussen.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "philipdeussen.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "pj1100.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "planhub.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "platform39.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "playinfinityvr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -79824,7 +79698,6 @@ { "name": "x00738.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "x00776.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "x00786.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "x668.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "x9016.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "xinnermedia.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "y68aa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -80151,7 +80024,6 @@ { "name": "interstateremovalists.sydney", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "inu.codes", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "investigatore.torino.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "itvaatlik.ee", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ixit.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "jaisiam.co.th", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "jamesusandra.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -81017,7 +80889,6 @@ { "name": "bet444423.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "bet444427.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "bet444428.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "bet444429.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "bet444430.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "biasmath.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "biggles.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -81289,7 +81160,6 @@ { "name": "lc040.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lc18.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lc1800.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "lc1818.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lc2121g.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lc245.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lc2500.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -82725,8 +82595,6 @@ { "name": "2habc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "5icsb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "9118.hk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "9968.love", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "9jabase.com.ng", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "a-tes-cotes.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "abdelaliezzyn.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -83025,7 +82893,6 @@ { "name": "mdclass.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "me7878.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "medasset.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "meganruggiero.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "metanumbers.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "metzgermark.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "mi1k.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -83159,7 +83026,6 @@ { "name": "signup.ly", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "siteweb-seo.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "siwek.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "skilloutlook.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "skynetstores.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "slymak.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "snowrippers.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -83477,7 +83343,6 @@ { "name": "bamboehof.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "bao-in.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "bao-in.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "bapha.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "basel-gynaecology.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "basel-gynaekologie.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "basilsys.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -85411,7 +85276,6 @@ { "name": "p82365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "panamarealestatebrokers.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "parkercs.tech", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "parketdoska.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "patentchallenges.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "paulineetaugustin.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "pcrabme.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -87077,14 +86941,6 @@ { "name": "svrx.one", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "swiftcom.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "sys21.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "t59970.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "t59971.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "t59972.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "t59973.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "t59983.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "t59984.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "t59985.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "t59986.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "talesbazaar.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "tattooli.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "tax-brain.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -87400,7 +87256,6 @@ { "name": "ekogroszekpieklo.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "empowersimcoe.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ergowish.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "espirituracer.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "estudioaguiar.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "eva42.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "extremebros.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -90568,7 +90423,6 @@ { "name": "caletka.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "campona.hu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "cancer-rose.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "cantical.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "cardiosportsilvinadelgado.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "cardloan-center.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "careercapital.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -93481,7 +93335,6 @@ { "name": "zaferaniehearing.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "zamor.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "zeglujemy.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "zhoujianghan.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "zivver.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "0x12.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "0x22.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -94913,7 +94766,6 @@ { "name": "libhttp.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "libpdf.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "libscpi.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "lig.ink", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "linocomm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "linocomm.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "linocomm.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -98992,7 +98844,6 @@ { "name": "imoxin.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "imperiyashop.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "impossiblechoisir.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "impra.com.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "imprezer.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "impudence.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "in-books.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -105177,7 +105028,6 @@ { "name": "50.gy", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "528sss.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "557bbb.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "722sss.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "795sss.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "991ccc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "aaflalo.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -108323,7 +108173,6 @@ { "name": "optitaxes.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "orcz.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "orsal.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "osorio.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "our-store.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ouroboros.world", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "p3.marketing", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -108594,7 +108443,6 @@ { "name": "yvonne-stingel.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "yy30019.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "z30019.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "zaigar.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "znfinnews.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "zorox.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "zporno.porn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -108677,7 +108525,6 @@ { "name": "carolinelanthier.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "casaruralcincoleyendas.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "casasincreibles.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "catpic.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "cccanna.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "celebrate-creativity.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "celebritypictures.blog", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -108759,7 +108606,6 @@ { "name": "etbtoursegypt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "eteachbd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "europeanbizhealthcare.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "exbasi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "extrasauber.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "extrasauber.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "extrasauber.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -109123,7 +108969,6 @@ { "name": "wolrdwidessl.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "wordwidessl.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "worldwidessl.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "wpboys.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "wxw.moe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "xanzhu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "xgys.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -110384,7 +110229,6 @@ { "name": "katerinastudio.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "kathrin-maren-enders.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "kgky.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "kidan.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "kimino-school.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "kinetikos.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "kiseki.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -110673,7 +110517,6 @@ { "name": "zotan.network", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "zotan.pw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "17avolemsaberlaveritat.cat", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "2q.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "2vp-an.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "360kuvia.fi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "360prokuvat.fi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -110829,7 +110672,6 @@ { "name": "emxvn.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "encontro.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "entropyofdelicatewonders.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "epitafija.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "erpollo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "erysonhandel.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "eslove.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -110945,7 +110787,6 @@ { "name": "kra2laiz.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "kratom-k.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "kryptoforce.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "kuraga.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "la-vraie-histoire.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "laby.link", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lacatta.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -110958,7 +110799,6 @@ { "name": "liveteachers.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "logopaedie-sandkrug.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "looop.rocks", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "loukkos.ma", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lovegpl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lovemoon.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lowcarbspark.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -111056,7 +110896,6 @@ { "name": "poezja.art", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "positivefocus.ie", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "postex.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "pqd.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "principalstest.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "problempaws.ie", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "processout.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -111240,7 +111079,6 @@ { "name": "3sixtydutyfree.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "604windswell.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "70mpg.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "8800.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "8885asknick.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "99laptops.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "aboutyou.si", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -111395,7 +111233,6 @@ { "name": "draft.cards", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "drivehub.win", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "drrenointerior.sg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "dymovskiy.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ecocleanpower.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "eggbay.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "eldiedesign.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -111512,7 +111349,6 @@ { "name": "intiveo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "investors.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ireta.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "iritual.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "irmo.hr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ironbarnyc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "isharryworking.today", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -111969,7 +111805,6 @@ { "name": "freebasics.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "funtimeusabiloxi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "gabe.download", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "gabrielgroup.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "gamecss.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ganardinerotrabajandoporinternet.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ganglioslinfaticos.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -112474,7 +112309,6 @@ { "name": "bivi.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "blackforlife.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "bloggingsaif.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "bmzm.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "bopyx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "boringnews.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "bracebridgechiro.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -113929,7 +113763,6 @@ { "name": "ngpest.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "nigelvm.email", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "nils.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "nocoffeetech.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "noel.wf", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "noel.yt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "notisecit.hu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -114144,7 +113977,6 @@ { "name": "whyfeedthegreed.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "wisemoney.com.vc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "wpshop.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "wulel.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "xn--grnstrm-r1ae.nu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "yaencasa.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "yc1820.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -114639,7 +114471,6 @@ { "name": "thewest.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "thumbnail.site", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "tianbo1988.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "tietsikka.fi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "tigernero.duckdns.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "tipslab.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "tlctrades.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -116010,7 +115841,6 @@ { "name": "mannhaarkunst.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "marcannmentalhealth.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "marco-s.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "margmusic.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "markisa.ninja", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "mathavuzteknolojileri.com.tr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "maxopolyworldnews.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -116233,7 +116063,6 @@ { "name": "wildanfauzy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "wondercorner.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "woodward-vets.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "wpnesia.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "wvhin.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "xemcanho.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "xiahdeh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -116310,7 +116139,6 @@ { "name": "aircomet.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "airfield.gq", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "airtel.com.ng", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "aitci.com.ph", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ajitp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "akepayu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "akinavn.vn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -116897,7 +116725,6 @@ { "name": "laboiteasous.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "labworks.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lacnesidlo.sk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "lad-china.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "ladige.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lamergameryt.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "lanekoll.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -117860,7 +117687,6 @@ { "name": "tianyis.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "tiga-design.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "timmerbedrijfpauel.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "toanz.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "tobostop.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "tog.pw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "togoweed.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -118041,7 +117867,6 @@ { "name": "eggy.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "eichendorffschule.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "elbrus360.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "elftoy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "elixirbih.ba", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "elypia.art", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "elypia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -118299,7 +118124,6 @@ { "name": "smartzona.bg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "smokycigars.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "socialplanet.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, - { "name": "softyak.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "somosgesath.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "soydxn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "sparklewindowcleaners.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, @@ -118402,6 +118226,482 @@ { "name": "zorgenvoorandrea.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "zwofroue.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, { "name": "zyciedirect.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "12grid.co.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "18onlypixel.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "18onlypixels.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "2dk.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "381485.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "4927a.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "4bengineering.cf", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "817209.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "abazola.cl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "actdigital.agency", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "adiraku.co.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "agaclinicaltrials.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "agent-imobiliar.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "agespisa.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ahenkerp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "airportal.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "albertonplumber.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "alexandrastrauss.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "allenturley.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "americanitpartners.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "amgreatness.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "andreaalloway.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "anhcuti.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "antoniojr.adv.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "anywhereworks.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "apsrustandtint.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "arcari.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "arthousecarousel.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "aruo.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "asdainfomanager.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "askmetutoring.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "asko.ee", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "atc-fr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "atlascloud.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "avatype.ir", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "awsl.tech", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "b0x0.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "b2b-leads.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "balicyclingtours.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bamaland.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "banffcanmorespeedskating.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "barkingmadpetproducts.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "berthaundcarlbenzpreis.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "best-tickets.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bianyanan.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bioghalm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bitbincomputers.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "blazebd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "blivdj.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bluebirdjc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bobvincent.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "boingboing.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "bootspropertycentral.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "boris64.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "browfai.casa", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "busqueautonomo.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cafeferrovia.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "calaix.click", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "candlemakingexplained.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "capybaraowner.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "carl.land", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "carlcsaposs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "caspianrentcar.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ccsaposs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cecil.coop", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cgmbacklot.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cgps.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "chaise-de-gamer.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "chargifi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "charlescwcooke.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cidgomes.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cielo-thefilm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cityacademyslc.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cocreaciones.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "conceptcompany.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "conscientia.com.mx", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "conservadoraembh.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "covid19dataportal.si", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cptechsupport.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "cr-it.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "craigsaper.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "criandosites.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "csaposs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "curaprox.co.th", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "czteryporyroku.edu.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dakotacil.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "danielittlewood.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "darcyinspired.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "denizsartdiary.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "designconformitylibrary.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "desiskinscience.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dieselfiltersonline.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "digi-tec.ir", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dijitalzade.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "direct.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "directeca.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "diysonline.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "djanemagbrasil.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dlgraphic.ir", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "doganoglu.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "doggo-staging.herokuapp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dovecraft.com.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "drgregroberts.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dsorter.com.ng", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dugwood.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "dysautonomia-postsyndrome.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "edgeless.pp.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "egm-sakura.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "elkhalillaw.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "emeetattd.ddns.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "eniwa-eye.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "enmieux.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ersbodabilvard.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "erzaehlwerkstatt-heilbronn.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "espcafe.uno", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "etoile-rc.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "evbn.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "excelbroadcast.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "f88vip114.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "f88vip115.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "f88vip116.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "f88vip117.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "f88vip118.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "f88vip13.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "f88vip14.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "f88vip16.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "f88vip17.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "f88vip18.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "f88vip29.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "f88vip30.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "f88vip31.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "f88vip32.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "f88vip33.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "f88vip34.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fairtrade.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fattoriabio.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fidesic.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "files.to", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "finsify.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "firmfunding.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fitchdesigncompany.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "fitnessplanet.best", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "flybis.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "forumofld.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "francoislaude.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "franfoto.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "frbg.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "frenchbluecottage.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "frosty.style", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "futa.wiki", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "galacticaos.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gatemotorsmidrand.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gatemotorssandton.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gazvangaz.hu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "genzi.win", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "germain.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "germaintechnologies.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gogem.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gogemini.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "goldnull.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "goosementor.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "gravelshooters.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "groupdcc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "grupoune.com.mx", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hacerjabon.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "handy.lc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hardnode.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "heinrich5991.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hermofit.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hoanghaiauto.vn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hostinkos.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "hoymedivorcio.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "i2capmark.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ichtushosting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "idigovs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ihgcontrolbook.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ineedweb.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "infopreneur.blog", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "instrumentalverein-tueddern.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "internetpoem.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "inwerx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "iqtek.solutions", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "iriscddg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ivetdata.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jaredkunz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jave.asia", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jetlaggroup.co.il", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jiaxitian.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "johyn.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jollytotschildminder.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "joshuakin.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "julian.tech", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "jwbworks.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kapilarya.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kdcinfo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "keskikorpimotorsport.fi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ketopower.club", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "khakiblossom.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kibrit.com.tr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kmassociations.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "knowyour.place", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "konturconference.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "koolisw.cf", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kozansa.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "krenstetter.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "kylese.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lacoccinelle.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lafsc.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lapeinturequichangetout.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ledgy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lepetitkids.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "leshe.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "leshetu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "leskoalasenvoyage.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lesportesdelascension.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lestrokeofgenius.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "libremedia.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lidodecor.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lifeconnections.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "linux.im", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lmdev.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "logobravo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "love4taylor.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "luxuryhome.co.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "luxuryitaly.co.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "lyme-regis-accommodation.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "m1hax.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "madonnadellafibra.gq", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "magodasredes.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mandalatantra.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "marielinepitre.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "masterpieceitaly.co.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "matras.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "matrixbricks.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "maxmaharashtra.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mayflowerfairytales.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mcsdatum.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mdcallianceparty.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mdnailspa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "medicardlimited.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "meetanshi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "megalogi.ma", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "meinevorlagen.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mengma.pub", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mepassport.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "meupatrocinio.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "microl.ink", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "midnightcity.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "midyatotantik.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "miku.bar", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "milon-apps.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mindthe5.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mindthe5.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mineskopia.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "minka.net.bo", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "misakaloli.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mizrahi-tefahot.co.il", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mkbd.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mobincube.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mobincube.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "monarch.security", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "morganhome.co.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mostertadmin.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mpk-chayka.org.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mta-sts.email", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mudanzasjuniorh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mundoamatista.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mylover.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mynic.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "myparadigm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "mzrme.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nanaimo.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nandonoire.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "napych.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nationalfleetparts.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ndibba.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "neweggsoft.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "newsunited.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nextsfd.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nibiru.com.uy", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ninjacomputing.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nirvana-esport.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nordaccount.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "nozaka-k.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "olivereats.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "only.lc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "openchronicles.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "opticamasvision.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "originalgyms.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "owncloud.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "paclease.com.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "paganismguide.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "paintlabcustom.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "paperopedia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "pb-eatz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "peckandweis.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "petersonchiropractic.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "philis-oenologie.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "pmnd.rs", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "pogomate.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "posoco.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "postofficenear.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "poterscy.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "powerspeaking.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "praizeej.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "prepa-benjam.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "presly.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "primark.guru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "primekinoshita.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "princess-vip-escort.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "privatmeet.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "procalc.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "proconnectengenharia.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "project-merlin.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "promo.lc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "propertech.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "proshnotori.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "proto.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "psdfindia.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "pswatcher.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "punkrockpsychology.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "rabbitsstore.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "raceevents.live", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "raistrick.art", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "rawbeautysource.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "rdienclosures.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "re-presented.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "rebull.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "recetasboricuas.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "recursos.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "reddcrypt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "registerforhappywellth.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ricochet.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "rje-hub.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "rndtool.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "robben.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "rsb.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sahccareers.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sainokuni-eng.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "salasbanquetes.cl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sallycooke.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "samsreseller.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sangobion.com.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "schooldatasquad.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "schreinerei-schwenk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "searx.nu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "securix.hk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sexdolls.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sftkey.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "shemsharples.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "shinetsuamerica.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "shinetsusilicones.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "shoplyft.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "signicat.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "simplifixed.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sisters.cloud", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sl0.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "slopi.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "socialeyesthailand.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "solidariedadecultura.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "soloparaguas.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "solvin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sosgate.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "soundrelief.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "southmarengo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sova.st", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "specialtyjets.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "spind.energy", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "spnsv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sportschoolgeelhoed.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sprawdz-nip.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ssasociety.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ssl.pink", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ssl.red", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "sslcentral.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "stamit.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "strongprorealty.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "suenotek.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "swissdomaintrustee.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "symoteb.ir", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tagalliances.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "teccozed.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "technoyl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "techquintal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "techstartup.tech", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tekmoloji.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tellet.tel", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tests-und-tipps.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tfsrcymru.org.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "thealchemistatelier.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "theantarcticx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "thecigarlibrary.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "theeuropeanlibrary.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "thehomeofthefuture.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "thehorsesadvocate.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "themevilles.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "thevirtuousdog.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "thewebguru.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tianjiaxi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ticketswap.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ticketswap.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ticketswap.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ticketswap.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ticketswap.co.nz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ticketswap.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ticketswap.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ticketswap.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ticketswap.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ticketswap.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ticketswap.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ticketswap.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ticketswap.fi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ticketswap.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ticketswap.hu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ticketswap.ie", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ticketswap.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ticketswap.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ticketswap.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ticketswap.no", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ticketswap.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ticketswap.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ticketswap.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ticketswap.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ticketswap.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tiptoptransmissions.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "toepferei-langerwehe.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tomik.space", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "toptechs.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "totalsell.marketing", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tradition-immobilier.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "trigate.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "troqueladoras.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "truckscout24.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "trydoggo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tureceta.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "turobot.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "twizzle.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "tyroola.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "uni-cleaner.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "uni-watch.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "upc-point.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vacacionestours.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "valueourmind.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "valueourminds.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vanvanlines.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vashmatrass.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vineethavarma.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "vlice.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wadebet.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wake.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wartabangsa.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "waukeshairon.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wealthyspeakerschool.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wearesuma.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wemakeit.live", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "whatiexpose.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wigglestudio.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "willflies.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wisconsinhomemaker.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wizardofvegas.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wizdomonwheels.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wmspropertyportal.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wobako.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wolfeco.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "wrfalimentos.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "xn--80ah4f.xn--p1ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "xn--soloatrapasueos-brb.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "yakovmanshin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ymeadows.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "yooand.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "yourcfo.co.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "z3ven.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "zachhay.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "ziprecruiter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "zmc.com.sa", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, + { "name": "zrobysama.com.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true }, // END OF 1-YEAR BULK HSTS ENTRIES // Only eTLD+1 domains can be submitted automatically to hstspreload.org,
diff --git a/net/quic/quic_chromium_client_session.cc b/net/quic/quic_chromium_client_session.cc index 6756dbe..f0871c2 100644 --- a/net/quic/quic_chromium_client_session.cc +++ b/net/quic/quic_chromium_client_session.cc
@@ -1654,6 +1654,15 @@ UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.ZeroRttState", state); UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.ZeroRttReason", early_data_reason, ssl_early_data_reason_max_value + 1); + if (IsGoogleHost(session_key_.host())) { + UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.ZeroRttReasonGoogle", + early_data_reason, + ssl_early_data_reason_max_value + 1); + } else { + UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.ZeroRttReasonNonGoogle", + early_data_reason, + ssl_early_data_reason_max_value + 1); + } } void QuicChromiumClientSession::OnCryptoHandshakeMessageSent(
diff --git a/net/quic/quic_flags_list.h b/net/quic/quic_flags_list.h index d74e286..0ad3ea2 100644 --- a/net/quic/quic_flags_list.h +++ b/net/quic/quic_flags_list.h
@@ -284,14 +284,6 @@ // If true, disable QUIC version h3-29. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_disable_version_draft_29, false) -// If true, improve Bbr2Sender::AdjustNetworkParameters by 1) do not inject a -// bandwidth sample to the bandwidth filter, and 2) re-calculate pacing rate -// after cwnd updated.. -QUIC_FLAG( - bool, - FLAGS_quic_reloadable_flag_quic_bbr2_improve_adjust_network_parameters, - true) - // If true, try to coalesce packet of higher space with retransmissions to // mitigate RTT inflations. QUIC_FLAG(bool, @@ -304,28 +296,11 @@ FLAGS_quic_reloadable_flag_quic_record_received_min_ack_delay, false) -// If true, QuicSession will no longer need streams_waiting_for_acks_. -QUIC_FLAG(bool, - FLAGS_quic_reloadable_flag_quic_remove_streams_waiting_for_acks, - true) - -// When true, ParsedQuicVersionToString will print IETF drafts with format -// draft29 instead of ff00001d. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_fix_print_draft_version, true) - // If true, disable blackhole detection on server side. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_disable_server_blackhole_detection, false) -// Remove ACK_DECIMATION_WITH_REORDERING mode and fast_ack_after_quiescence -// option in QUIC received packet manager. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_remove_unused_ack_options, true) - -// If true, QUIC subclasses will no longer directly access stream_map for its -// content. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_do_not_use_stream_map, true) - // If true, // server accepts GOAWAY (draft-28 behavior), // client receiving GOAWAY with stream ID that is not client-initiated @@ -346,11 +321,6 @@ // exists) after two PTOs. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_revert_mtu_after_two_ptos, true) -// Simplify the ACK code in quic_received_packet_manager. -QUIC_FLAG(bool, - FLAGS_quic_reloadable_flag_quic_simplify_received_packet_manager_ack, - true) - // If true, when TLPR copt is used, enable half RTT as first PTO timeout. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_use_half_rtt_as_first_pto, true) @@ -360,9 +330,6 @@ FLAGS_quic_reloadable_flag_quic_enable_overshooting_detection, true) -// If true, enable QUIC version h3-T051. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_version_t051, true) - // If true, fix a case where data is marked lost in HANDSHAKE level but // HANDSHAKE key gets decrypted later. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_fix_neuter_handshake_data, true) @@ -462,3 +429,28 @@ QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_add_stream_info_to_idle_close_detail, true) + +// If true, use IETF QUIC application error codes in STOP_SENDING frames. +QUIC_FLAG(bool, + FLAGS_quic_reloadable_flag_quic_stop_sending_uses_ietf_error_code, + false) + +// If true, QuicSpdySession's destructor won't need to do cleanup. +QUIC_FLAG(bool, + FLAGS_quic_reloadable_flag_quic_clean_up_spdy_session_destructor, + true) + +// If true, discard INITIAL packet if the key has been dropped. +QUIC_FLAG( + bool, + FLAGS_quic_reloadable_flag_quic_discard_initial_packet_with_key_dropped, + true) + +// If true, disable QUIC version h3-T051. +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_disable_version_t051, false) + +// If true, make sure there is pending timer credit when trying to PTO +// retransmit any packets. +QUIC_FLAG(bool, + FLAGS_quic_reloadable_flag_quic_fix_pto_pending_timer_count, + true)
diff --git a/net/quiche/common/platform/impl/DEPS b/net/quiche/common/platform/impl/DEPS new file mode 100644 index 0000000..46f9ab7 --- /dev/null +++ b/net/quiche/common/platform/impl/DEPS
@@ -0,0 +1,6 @@ +include_rules = [ + # This is a temporary rule to simplify migrating QUICHE to using Abseil + # directly. + # TODO(b/166325009): remove this rule. + "+third_party/abseil-cpp/absl/container/node_hash_map.h", +]
diff --git a/net/quiche/common/platform/impl/quiche_unordered_containers_impl.h b/net/quiche/common/platform/impl/quiche_unordered_containers_impl.h index fe48f20c..d08485f 100644 --- a/net/quiche/common/platform/impl/quiche_unordered_containers_impl.h +++ b/net/quiche/common/platform/impl/quiche_unordered_containers_impl.h
@@ -7,20 +7,16 @@ #include <unordered_map> +#include "third_party/abseil-cpp/absl/container/node_hash_map.h" + namespace quiche { // The default hasher used by hash tables. template <typename Key> -using QuicheDefaultHasherImpl = std::hash<Key>; +using QuicheDefaultHasherImpl = absl::Hash<Key>; -template <typename Key, - typename Value, - typename Hash, - typename Eq = - typename std::unordered_map<Key, Value, Hash>::key_equal, - typename Alloc = - typename std::unordered_map<Key, Value, Hash>::allocator_type> -using QuicheUnorderedMapImpl = std::unordered_map<Key, Value, Hash, Eq, Alloc>; +template <typename Key, typename Value, typename Hash, typename Eq> +using QuicheUnorderedMapImpl = absl::node_hash_map<Key, Value, Hash, Eq>; } // namespace quiche
diff --git a/pdf/pdf_view_web_plugin.cc b/pdf/pdf_view_web_plugin.cc index 5cffa0e0..24c34ff 100644 --- a/pdf/pdf_view_web_plugin.cc +++ b/pdf/pdf_view_web_plugin.cc
@@ -8,6 +8,7 @@ #include <memory> #include <string> +#include <utility> #include <vector> #include "base/check_op.h" @@ -18,12 +19,15 @@ #include "cc/paint/paint_canvas.h" #include "pdf/pdf_engine.h" #include "pdf/pdf_init.h" +#include "pdf/pdfium/pdfium_engine.h" #include "pdf/ppapi_migration/url_loader.h" +#include "ppapi/c/pp_errors.h" #include "third_party/blink/public/common/input/web_coalesced_input_event.h" #include "third_party/blink/public/common/metrics/document_update_reason.h" #include "third_party/blink/public/mojom/input/focus_type.mojom-shared.h" #include "third_party/blink/public/platform/web_input_event_result.h" #include "third_party/blink/public/platform/web_rect.h" +#include "third_party/blink/public/platform/web_string.h" #include "third_party/blink/public/platform/web_url_error.h" #include "third_party/blink/public/platform/web_url_response.h" #include "third_party/blink/public/web/web_associated_url_loader.h" @@ -85,16 +89,28 @@ } // namespace -PdfViewWebPlugin::PdfViewWebPlugin(const blink::WebPluginParams& params) {} +PdfViewWebPlugin::PdfViewWebPlugin(const blink::WebPluginParams& params) + : initial_params_(params) {} PdfViewWebPlugin::~PdfViewWebPlugin() = default; +// Modeled on `OutOfProcessInstance::Init()`. bool PdfViewWebPlugin::Initialize(blink::WebPluginContainer* container) { DCHECK_EQ(container->Plugin(), this); container_ = container; + std::string stream_url; + for (size_t i = 0; i < initial_params_.attribute_names.size(); ++i) { + if (initial_params_.attribute_names[i] == "stream-url") + stream_url = initial_params_.attribute_values[i].Utf8(); + } + + // Contents of `initial_params_` no longer needed. + initial_params_ = {}; + PerProcessInitializer::GetInstance().Acquire(); InitializeEngine(/*enable_javascript=*/false); + LoadUrl(stream_url, /*is_print_preview=*/false); return true; } @@ -225,9 +241,13 @@ } void PdfViewWebPlugin::DocumentLoadComplete( - const PDFEngine::DocumentFeatures& document_features) {} + const PDFEngine::DocumentFeatures& document_features) { + NOTIMPLEMENTED(); +} -void PdfViewWebPlugin::DocumentLoadFailed() {} +void PdfViewWebPlugin::DocumentLoadFailed() { + NOTIMPLEMENTED(); +} pp::Instance* PdfViewWebPlugin::GetPluginInstance() { return nullptr; @@ -287,9 +307,15 @@ return loader; } +// Modeled on `OutOfProcessInstance::DidOpen()`. void PdfViewWebPlugin::DidOpen(std::unique_ptr<UrlLoader> loader, int32_t result) { - NOTIMPLEMENTED(); + if (result == PP_OK) { + if (!engine()->HandleDocumentLoad(std::move(loader))) + DocumentLoadFailed(); + } else { + NOTIMPLEMENTED(); + } } void PdfViewWebPlugin::DidOpenPreview(std::unique_ptr<UrlLoader> loader,
diff --git a/pdf/pdf_view_web_plugin.h b/pdf/pdf_view_web_plugin.h index dec9811..cedc3b3 100644 --- a/pdf/pdf_view_web_plugin.h +++ b/pdf/pdf_view_web_plugin.h
@@ -9,10 +9,10 @@ #include "pdf/pdf_view_plugin_base.h" #include "pdf/ppapi_migration/url_loader.h" #include "third_party/blink/public/web/web_plugin.h" +#include "third_party/blink/public/web/web_plugin_params.h" namespace blink { class WebPluginContainer; -struct WebPluginParams; } // namespace blink namespace chrome_pdf { @@ -117,6 +117,7 @@ // Call `Destroy()` instead. ~PdfViewWebPlugin() override; + blink::WebPluginParams initial_params_; blink::WebPluginContainer* container_ = nullptr; base::WeakPtrFactory<PdfViewWebPlugin> weak_factory_{this};
diff --git a/sandbox/policy/mac/gpu_v2.sb b/sandbox/policy/mac/gpu_v2.sb index 543a2724..4d7222c 100644 --- a/sandbox/policy/mac/gpu_v2.sb +++ b/sandbox/policy/mac/gpu_v2.sb
@@ -27,6 +27,7 @@ (global-name "com.apple.PowerManagement.control") (global-name "com.apple.SecurityServer") (global-name "com.apple.system.notification_center") + (global-name "com.apple.system.opendirectoryd.membership") ; https://crbug.com/1126350#c5 (global-name "com.apple.tsm.uiserver") (global-name "com.apple.windowserver.active") )
diff --git a/services/service_manager/embedder/BUILD.gn b/services/service_manager/embedder/BUILD.gn index fbbf2166..2379f07f 100644 --- a/services/service_manager/embedder/BUILD.gn +++ b/services/service_manager/embedder/BUILD.gn
@@ -12,7 +12,6 @@ public = [ "main.h", "main_delegate.h", - "process_type.h", "set_process_title.h", "shared_file_util.h", ]
diff --git a/services/service_manager/embedder/main.cc b/services/service_manager/embedder/main.cc index 607618c..1c84ca5 100644 --- a/services/service_manager/embedder/main.cc +++ b/services/service_manager/embedder/main.cc
@@ -35,13 +35,9 @@ #include "mojo/public/cpp/base/shared_memory_utils.h" #include "sandbox/policy/sandbox_type.h" #include "services/service_manager/embedder/main_delegate.h" -#include "services/service_manager/embedder/process_type.h" #include "services/service_manager/embedder/set_process_title.h" #include "services/service_manager/embedder/shared_file_util.h" #include "services/service_manager/embedder/switches.h" -#include "services/service_manager/public/cpp/service.h" -#include "services/service_manager/public/cpp/service_executable/service_executable_environment.h" -#include "services/service_manager/public/cpp/service_executable/switches.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/ui_base_paths.h" #include "ui/base/ui_base_switches.h" @@ -150,100 +146,6 @@ #endif } -void NonEmbedderProcessInit() { - logging::LoggingSettings settings; - settings.logging_dest = - logging::LOG_TO_SYSTEM_DEBUG_LOG | logging::LOG_TO_STDERR; - logging::InitLogging(settings); - // To view log output with IDs and timestamps use "adb logcat -v threadtime". - logging::SetLogItems(true, // Process ID - true, // Thread ID - true, // Timestamp - true); // Tick count - -#if !defined(OFFICIAL_BUILD) - // Initialize stack dumping before initializing sandbox to make sure symbol - // names in all loaded libraries will be cached. - // NOTE: On Chrome OS, crash reporting for the root process and non-browser - // service processes is handled by the OS-level crash_reporter. - if (!base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableInProcessStackTraces)) { - base::debug::EnableInProcessStackDumping(); - } -#endif - - base::ThreadPoolInstance::CreateAndStartWithDefaultParams( - "ServiceManagerProcess"); -} - -int RunServiceManager(MainDelegate* delegate) { - NonEmbedderProcessInit(); - - base::SingleThreadTaskExecutor main_thread_task_executor( - base::MessagePumpType::UI); - - base::Thread ipc_thread("IPC thread"); - ipc_thread.StartWithOptions( - base::Thread::Options(base::MessagePumpType::IO, 0)); - mojo::core::ScopedIPCSupport ipc_support( - ipc_thread.task_runner(), - mojo::core::ScopedIPCSupport::ShutdownPolicy::FAST); - - service_manager::BackgroundServiceManager background_service_manager( - delegate->GetServiceManifests()); - - base::RunLoop run_loop; - delegate->OnServiceManagerInitialized(run_loop.QuitClosure(), - &background_service_manager); - run_loop.Run(); - - ipc_thread.Stop(); - base::ThreadPoolInstance::Get()->Shutdown(); - - return 0; -} - -void InitializeResources() { - const std::string locale = - base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( - ::switches::kLang); - // This loads the embedder's common resources (e.g. chrome_100_percent.pak for - // Chrome.) - ui::ResourceBundle::InitSharedInstanceWithLocale( - locale, nullptr, ui::ResourceBundle::LOAD_COMMON_RESOURCES); -} - -int RunService(MainDelegate* delegate) { - NonEmbedderProcessInit(); - - InitializeResources(); - - service_manager::ServiceExecutableEnvironment environment; - - base::SingleThreadTaskExecutor main_thread_task_executor( - base::MessagePumpType::UI); - base::RunLoop run_loop; - - std::string service_name = - base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( - switches::kServiceName); - if (service_name.empty()) { - LOG(ERROR) << "Service process requires --service-name"; - return 1; - } - - std::unique_ptr<Service> service = - delegate->CreateEmbeddedService(service_name); - if (!service) { - LOG(ERROR) << "Failed to start embedded service: " << service_name; - return 1; - } - - service->set_termination_closure(run_loop.QuitClosure()); - run_loop.Run(); - return 0; -} - } // namespace MainParams::MainParams(MainDelegate* delegate) : delegate(delegate) {} @@ -256,7 +158,6 @@ int exit_code = -1; base::debug::GlobalActivityTracker* tracker = nullptr; - ProcessType process_type = delegate->OverrideProcessType(); #if defined(OS_MAC) std::unique_ptr<base::mac::ScopedNSAutoreleasePool> autorelease_pool; #endif @@ -336,10 +237,8 @@ SetupSignalHandlers(); #endif - const auto& command_line = *base::CommandLine::ForCurrentProcess(); - #if defined(OS_WIN) - base::win::SetupCRT(command_line); + base::win::SetupCRT(*base::CommandLine::ForCurrentProcess()); #endif MainDelegate::InitializeParams init_params; @@ -355,11 +254,6 @@ #endif mojo::core::Configuration mojo_config; - if (process_type == ProcessType::kDefault && - command_line.GetSwitchValueASCII(switches::kProcessType) == - switches::kProcessTypeServiceManager) { - mojo_config.is_broker_process = true; - } mojo_config.max_message_num_bytes = kMaximumMojoMessageSize; delegate->InitializeMojo(&mojo_config); @@ -388,7 +282,8 @@ // implementation of mojo::NodeController::CreateSharedBuffer(). #if !defined(OS_MAC) && !defined(OS_NACL_SFI) && !defined(OS_FUCHSIA) if (sandbox::policy::IsUnsandboxedSandboxType( - sandbox::policy::SandboxTypeFromCommandLine(command_line))) { + sandbox::policy::SandboxTypeFromCommandLine( + *base::CommandLine::ForCurrentProcess()))) { // Unsandboxed processes don't need shared memory brokering... because // they're not sandboxed. } else if (mojo_config.force_direct_shared_memory_allocation) { @@ -421,38 +316,9 @@ } } - const auto& command_line = *base::CommandLine::ForCurrentProcess(); - if (process_type == ProcessType::kDefault) { - std::string type_switch = - command_line.GetSwitchValueASCII(switches::kProcessType); - if (type_switch == switches::kProcessTypeServiceManager) { - process_type = ProcessType::kServiceManager; - } else if (type_switch == switches::kProcessTypeService) { - process_type = ProcessType::kService; - } else { - process_type = ProcessType::kEmbedder; - } - } - switch (process_type) { - case ProcessType::kDefault: - NOTREACHED(); - break; - - case ProcessType::kServiceManager: - exit_code = RunServiceManager(delegate); - break; - - case ProcessType::kService: - CommonSubprocessInit(); - exit_code = RunService(delegate); - break; - - case ProcessType::kEmbedder: - if (delegate->IsEmbedderSubprocess()) - CommonSubprocessInit(); - exit_code = delegate->RunEmbedderProcess(); - break; - } + if (delegate->IsEmbedderSubprocess()) + CommonSubprocessInit(); + exit_code = delegate->RunEmbedderProcess(); if (tracker) { if (exit_code == 0) { @@ -469,8 +335,7 @@ autorelease_pool.reset(); #endif - if (process_type == ProcessType::kEmbedder) - delegate->ShutDownEmbedderProcess(); + delegate->ShutDownEmbedderProcess(); return exit_code; }
diff --git a/services/service_manager/embedder/main_delegate.cc b/services/service_manager/embedder/main_delegate.cc index 65dec35..011b386 100644 --- a/services/service_manager/embedder/main_delegate.cc +++ b/services/service_manager/embedder/main_delegate.cc
@@ -20,31 +20,6 @@ void MainDelegate::ShutDownEmbedderProcess() {} -ProcessType MainDelegate::OverrideProcessType() { - return ProcessType::kDefault; -} - void MainDelegate::InitializeMojo(mojo::core::Configuration* config) {} -std::vector<Manifest> MainDelegate::GetServiceManifests() { - return std::vector<Manifest>(); -} - -bool MainDelegate::ShouldLaunchAsServiceProcess(const Identity& identity) { - return true; -} - -void MainDelegate::AdjustServiceProcessCommandLine( - const Identity& identity, - base::CommandLine* command_line) {} - -void MainDelegate::OnServiceManagerInitialized( - base::OnceClosure quit_closure, - BackgroundServiceManager* service_manager) {} - -std::unique_ptr<Service> MainDelegate::CreateEmbeddedService( - const std::string& service_name) { - return nullptr; -} - } // namespace service_manager
diff --git a/services/service_manager/embedder/main_delegate.h b/services/service_manager/embedder/main_delegate.h index fc3d453..27da85656 100644 --- a/services/service_manager/embedder/main_delegate.h +++ b/services/service_manager/embedder/main_delegate.h
@@ -5,23 +5,10 @@ #ifndef SERVICES_SERVICE_MANAGER_EMBEDDER_MAIN_DELEGATE_H_ #define SERVICES_SERVICE_MANAGER_EMBEDDER_MAIN_DELEGATE_H_ -#include <memory> -#include <vector> - -#include "base/callback_forward.h" #include "base/component_export.h" -#include "base/memory/scoped_refptr.h" -#include "base/single_thread_task_runner.h" #include "mojo/core/embedder/configuration.h" -#include "services/service_manager/background_service_manager.h" -#include "services/service_manager/embedder/process_type.h" -#include "services/service_manager/public/cpp/identity.h" -#include "services/service_manager/public/cpp/manifest.h" -#include "services/service_manager/public/cpp/service.h" -#include "services/service_manager/public/mojom/service.mojom.h" namespace base { -class CommandLine; namespace mac { class ScopedNSAutoreleasePool; } @@ -67,43 +54,9 @@ // Called just before process exit if RunEmbedderProcess() was called. virtual void ShutDownEmbedderProcess(); - // Force execution of the current process as a specific process type. May - // return |ProcessType::kDefault| to avoid overriding. - virtual ProcessType OverrideProcessType(); - // Allows the embedder to override the process-wide Mojo configuration and // initialization. virtual void InitializeMojo(mojo::core::Configuration* config); - - // Gets the list of service manifests with which to initialize the Service - // Manager. This list must describe the complete set of usable services in - // the system and remains fixed for the lifetime of the Service Manager. - virtual std::vector<Manifest> GetServiceManifests(); - - // Indicates whether a process started by the service manager for a given - // target service identity should be run as a real service process (|true|) - // or if the service manager should delegate to the embedder to initialize the - // new process (|false|). - virtual bool ShouldLaunchAsServiceProcess(const Identity& identity); - - // Allows the embedder to override command line switches for a service process - // to be launched. - virtual void AdjustServiceProcessCommandLine(const Identity& identity, - base::CommandLine* command_line); - - // Allows the embedder to perform arbitrary initialization within the Service - // Manager process immediately before the Service Manager runs its main loop. - // - // |quit_closure| is a callback the embedder may retain and invoke at any time - // to cleanly terminate Service Manager execution. - virtual void OnServiceManagerInitialized( - base::OnceClosure quit_closure, - BackgroundServiceManager* service_manager); - - // Runs an embedded service by name. If the embedder does not know how to - // create an instance of the named service, it should return null. - virtual std::unique_ptr<Service> CreateEmbeddedService( - const std::string& service_name); }; } // namespace service_manager
diff --git a/services/service_manager/embedder/process_type.h b/services/service_manager/embedder/process_type.h deleted file mode 100644 index ca9d9c1..0000000 --- a/services/service_manager/embedder/process_type.h +++ /dev/null
@@ -1,31 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_SERVICE_MANAGER_EMBEDDER_PROCESS_TYPE_H_ -#define SERVICES_SERVICE_MANAGER_EMBEDDER_PROCESS_TYPE_H_ - -namespace service_manager { - -enum class ProcessType { - // An unspecified process type. If this is given anywhere a ProcessType is - // expected, it must be interpreted as some reasonable default based on - // context. - kDefault, - - // A standalone Service Manager process. There can be only one. - kServiceManager, - - // A service process. A service process hosts one or more embedded service - // instances. - kService, - - // An embedder process. The Service Manager implementation does not control - // any aspect of the process's logic beyond primitive process initialization - // and shutdown. - kEmbedder, -}; - -} // namespace service_manager - -#endif // SERVICES_SERVICE_MANAGER_EMBEDDER_PROCESS_TYPE_H_
diff --git a/services/service_manager/embedder/switches.cc b/services/service_manager/embedder/switches.cc index 7bc83d1a..efceb3b 100644 --- a/services/service_manager/embedder/switches.cc +++ b/services/service_manager/embedder/switches.cc
@@ -35,14 +35,6 @@ // "service-runner", or any other arbitrary value supported by the embedder. const char kProcessType[] = "type"; -// The value of the |kProcessType| switch which tells the executable to assume -// the role of a standalone Service Manager instance. -const char kProcessTypeServiceManager[] = "service-manager"; - -// The value of the |kProcessType| switch which tells the executable to assume -// the role of a service instance. -const char kProcessTypeService[] = "service-runner"; - // The token to use to construct the message pipe for a service in a child // process. const char kServiceRequestChannelToken[] = "service-request-channel-token";
diff --git a/services/service_manager/embedder/switches.h b/services/service_manager/embedder/switches.h index 3b6690aa..3ed8212 100644 --- a/services/service_manager/embedder/switches.h +++ b/services/service_manager/embedder/switches.h
@@ -26,12 +26,6 @@ extern const char kProcessType[]; COMPONENT_EXPORT(SERVICE_MANAGER_EMBEDDER_SWITCHES) -extern const char kProcessTypeServiceManager[]; - -COMPONENT_EXPORT(SERVICE_MANAGER_EMBEDDER_SWITCHES) -extern const char kProcessTypeService[]; - -COMPONENT_EXPORT(SERVICE_MANAGER_EMBEDDER_SWITCHES) extern const char kServiceRequestChannelToken[]; COMPONENT_EXPORT(SERVICE_MANAGER_EMBEDDER_SWITCHES)
diff --git a/storage/browser/blob/blob_builder_from_stream_unittest.cc b/storage/browser/blob/blob_builder_from_stream_unittest.cc index 184f335..3c27c86 100644 --- a/storage/browser/blob/blob_builder_from_stream_unittest.cc +++ b/storage/browser/blob/blob_builder_from_stream_unittest.cc
@@ -416,8 +416,7 @@ mojo::AssociatedRemote<blink::mojom::ProgressClient> progress_client_remote; mojo::AssociatedReceiver<blink::mojom::ProgressClient> progress_receiver( &progress_client, - progress_client_remote - .BindNewEndpointAndPassDedicatedReceiverForTesting()); + progress_client_remote.BindNewEndpointAndPassDedicatedReceiver()); mojo::DataPipe pipe; base::RunLoop loop;
diff --git a/testing/buildbot/chrome.ci.json b/testing/buildbot/chrome.ci.json index 44ce26d..851d8d1c 100644 --- a/testing/buildbot/chrome.ci.json +++ b/testing/buildbot/chrome.ci.json
@@ -3670,6 +3670,39 @@ } ] }, + "linux-chromeos-chrome-easwa": { + "additional_compile_targets": [ + "chrome", + "chrome_sandbox", + "linux_symbols", + "symupload" + ], + "gtest_tests": [ + { + "args": [ + "--gtest-filter=*HelpApp*:*MediaApp*" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "name": "easwa_browser_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04", + "pool": "chrome.tests", + "ssd": "0" + } + ], + "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "browser_tests", + "test_id_prefix": "ninja://chrome/test:browser_tests/" + } + ] + }, "linux-rel-swarming": { "gtest_tests": [ { @@ -4033,6 +4066,34 @@ } ] }, + "soda-linux": { + "additional_compile_targets": [ + "unit_tests" + ], + "gtest_tests": [ + { + "args": [ + "--gtest_filter=SodaClient*" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Linux", + "pool": "chrome.tests" + } + ], + "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "unit_tests", + "test_id_prefix": "ninja://chrome/test:unit_tests/" + } + ] + }, "win-chrome": { "additional_compile_targets": [ "chrome",
diff --git a/testing/buildbot/chrome.json b/testing/buildbot/chrome.json index a72cc93..d52d44e 100644 --- a/testing/buildbot/chrome.json +++ b/testing/buildbot/chrome.json
@@ -3040,6 +3040,39 @@ } ] }, + "linux-chromeos-chrome-easwa": { + "additional_compile_targets": [ + "chrome", + "chrome_sandbox", + "linux_symbols", + "symupload" + ], + "gtest_tests": [ + { + "args": [ + "--gtest-filter=*HelpApp*:*MediaApp*" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "name": "easwa_browser_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-16.04", + "pool": "chrome.tests", + "ssd": "0" + } + ], + "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "browser_tests", + "test_id_prefix": "ninja://chrome/test:browser_tests/" + } + ] + }, "mac-chrome": { "additional_compile_targets": [ "chrome"
diff --git a/testing/buildbot/generate_buildbot_json.py b/testing/buildbot/generate_buildbot_json.py index fd9ca78..7fb870f 100755 --- a/testing/buildbot/generate_buildbot_json.py +++ b/testing/buildbot/generate_buildbot_json.py
@@ -1442,7 +1442,7 @@ def get_internal_waterfalls(self): # Similar to get_builders_that_do_not_actually_exist above, but for # waterfalls defined in internal configs. - return ['chrome', 'chrome.pgo'] + return ['chrome', 'chrome.pgo', 'internal.soda'] def check_input_file_consistency(self, verbose=False): self.check_input_files_sorting(verbose)
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl index 002aaaca..0b9b99b 100644 --- a/testing/buildbot/gn_isolate_map.pyl +++ b/testing/buildbot/gn_isolate_map.pyl
@@ -529,6 +529,7 @@ "../../chrome/test/chromedriver/test/run_webdriver_tests.py", "-v", "--chromedriver=chromedriver", + "--log-path=${ISOLATED_OUTDIR}/chromedriver.log", "--output-dir=${ISOLATED_OUTDIR}", "--test-path=../../third_party/blink/web_tests/external/wpt/webdriver/tests/", ],
diff --git a/testing/buildbot/internal.soda.json b/testing/buildbot/internal.soda.json new file mode 100644 index 0000000..d8969d0 --- /dev/null +++ b/testing/buildbot/internal.soda.json
@@ -0,0 +1,32 @@ +{ + "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {}, + "AAAAA2 See generate_buildbot_json.py to make changes": {}, + "soda-linux": { + "additional_compile_targets": [ + "unit_tests" + ], + "gtest_tests": [ + { + "args": [ + "--gtest_filter=SodaClient*" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Linux", + "pool": "chrome.tests" + } + ], + "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "unit_tests", + "test_id_prefix": "ninja://chrome/test:unit_tests/" + } + ] + } +}
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index d339b9c..5094b1028 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -23,7 +23,6 @@ 'android_ar_gtests': { 'monochrome_public_test_ar_apk': {}, }, - 'android_ddready_vr_gtests': { 'chrome_public_test_vr_apk-ddready-cardboard': { 'args': [ @@ -1235,6 +1234,18 @@ }, }, + 'easwa_browser_tests' : { + 'easwa_browser_tests': { + 'args': [ + '--gtest-filter=*HelpApp*:*MediaApp*' + ], + 'swarming': { + 'shards': 1, + }, + 'test': 'browser_tests', + } + }, + 'fieldtrial_browser_tests': { 'no_fieldtrial_browser_tests': { 'args': [ @@ -3998,7 +4009,11 @@ 'results_handler': 'layout tests', }, }, - + 'soda_gtests': { + 'unit_tests': { + 'args': ['--gtest_filter=SodaClient*'], + }, + }, # TODO(https://crbug.com/1057802): Remove these tests once Out-of-Process # Storage is on by default. 'storage_service_gtests': {
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index 1d6e69b..fcce948 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -174,6 +174,28 @@ 'isolated_scripts': 'chrome_sizes', }, }, + 'linux-chromeos-chrome-easwa': { + 'additional_compile_targets': [ + 'chrome', + 'chrome_sandbox', + 'linux_symbols', + 'symupload' + ], + 'mixins': [ + 'chrome-swarming-pool', + 'linux-xenial', + ], + 'swarming': { + 'dimension_sets': [ + { + 'ssd': '0', + }, + ], + }, + 'test_suites': { + 'gtest_tests': 'easwa_browser_tests', + }, + }, 'mac-chrome': { 'additional_compile_targets': [ 'chrome', @@ -5515,6 +5537,30 @@ }, }, { + 'project': 'chrome', + 'bucket': 'ci', + 'name': 'internal.soda', + 'machines': { + 'soda-linux': { + 'additional_compile_targets': [ + 'unit_tests', + ], + 'test_suites': { + 'gtest_tests': 'soda_gtests', + }, + 'swarming': { + 'dimension_sets': [ + { + 'os': 'Linux', + 'pool': 'chrome.tests', + }, + ], + "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com", + }, + }, + }, + }, + { 'project': 'chromium', 'bucket': 'try', 'name': 'tryserver.chromium.android',
diff --git a/testing/scripts/host_info.py b/testing/scripts/host_info.py index f23352d..6aa9b8a 100755 --- a/testing/scripts/host_info.py +++ b/testing/scripts/host_info.py
@@ -68,7 +68,7 @@ 'tools', 'device_status.py'), '--json-output', tempfile_path, - '--blacklist-file', os.path.join( + '--denylist-file', os.path.join( args.paths['checkout'], 'out', 'bad_devices.json') ] if args.args: @@ -86,7 +86,7 @@ results['devices'] = sorted(v['serial'] for v in device_info) details = [ - v['ro.build.fingerprint'] for v in device_info if not v['blacklisted']] + v['ro.build.fingerprint'] for v in device_info if not v['denylisted']] def unique_build_details(index): return sorted(list(set([v.split(':')[index] for v in details]))) @@ -106,8 +106,8 @@ failures.append(k) for v in device_info: - if v['blacklisted']: - failures.append('Device %s blacklisted' % v['serial']) + if v['denylisted']: + failures.append('Device %s denylisted' % v['serial']) return results
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 07ab6d4..c94dca45 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -87,6 +87,25 @@ ] } ], + "AndroidAppMenuUiRework": [ + { + "platforms": [ + "android" + ], + "experiments": [ + { + "name": "RegroupBackwardButton", + "params": { + "action_bar": "backward_button" + }, + "enable_features": [ + "TabbedAppOverflowMenuIcons", + "TabbedAppOverflowMenuRegroup" + ] + } + ] + } + ], "AndroidDarkSearch": [ { "platforms": [ @@ -650,6 +669,22 @@ ] } ], + "AutofillCreditCardAuthentication": [ + { + "platforms": [ + "android", + "android_webview" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "AutofillCreditCardAuthentication" + ] + } + ] + } + ], "AutofillEnableCardNicknameManagementAndUpstream": [ { "platforms": [
diff --git a/third_party/android_deps/BUILD.gn b/third_party/android_deps/BUILD.gn index 5a75561..2375a0b 100644 --- a/third_party/android_deps/BUILD.gn +++ b/third_party/android_deps/BUILD.gn
@@ -11,9 +11,6 @@ ":androidx_drawerlayout_drawerlayout_java", ":androidx_fragment_fragment_java", ":androidx_interpolator_interpolator_java", - ":androidx_legacy_legacy_support_core_ui_java", - ":androidx_legacy_legacy_support_core_utils_java", - ":androidx_legacy_legacy_support_v4_java", ":androidx_lifecycle_lifecycle_common_java", ":androidx_lifecycle_lifecycle_viewmodel_java", ":androidx_media_media_java", @@ -65,20 +62,6 @@ ] } -# The dependencies below are used by chromecast internal. -java_group("android_support_v7_preference_java") { - deps = [ ":androidx_preference_preference_java" ] -} -java_group("android_support_v14_preference_java") { - deps = [ ":androidx_legacy_legacy_preference_v14_java" ] -} -java_group("android_support_v17_leanback_java") { - deps = [ ":androidx_leanback_leanback_java" ] -} -java_group("android_support_v17_preference_java") { - deps = [ ":androidx_leanback_leanback_preference_java" ] -} - java_group("material_design_java") { deps = [ "$material_design_target" ] } @@ -334,6 +317,11 @@ ":androidx_viewpager_viewpager_java", ] resource_overlay = true + deps += [ "//third_party/android_deps/local_modifications/androidx_fragment_fragment:androidx_fragment_fragment_prebuilt_java" ] + + # Omit this file since we use our own copy, included above. + # We can remove this once we migrate to AndroidX master for all libraries. + jar_excluded_patterns = [ "androidx/fragment/app/DialogFragment*" ] ignore_proguard_configs = true } @@ -375,51 +363,6 @@ } # This is generated, do not edit. Update BuildConfigGenerator.groovy instead. -android_aar_prebuilt("androidx_legacy_legacy_support_core_ui_java") { - aar_path = "libs/androidx_legacy_legacy_support_core_ui/legacy-support-core-ui-1.0.0.aar" - info_path = "libs/androidx_legacy_legacy_support_core_ui/androidx_legacy_legacy_support_core_ui.info" - deps = [ - ":androidx_annotation_annotation_java", - ":androidx_asynclayoutinflater_asynclayoutinflater_java", - ":androidx_coordinatorlayout_coordinatorlayout_java", - ":androidx_core_core_java", - ":androidx_cursoradapter_cursoradapter_java", - ":androidx_customview_customview_java", - ":androidx_drawerlayout_drawerlayout_java", - ":androidx_interpolator_interpolator_java", - ":androidx_legacy_legacy_support_core_utils_java", - ":androidx_slidingpanelayout_slidingpanelayout_java", - ":androidx_swiperefreshlayout_swiperefreshlayout_java", - ":androidx_viewpager_viewpager_java", - ] - resource_overlay = true -} - -# This is generated, do not edit. Update BuildConfigGenerator.groovy instead. -android_aar_prebuilt("androidx_legacy_legacy_support_core_utils_java") { - aar_path = "libs/androidx_legacy_legacy_support_core_utils/legacy-support-core-utils-1.0.0.aar" - info_path = "libs/androidx_legacy_legacy_support_core_utils/androidx_legacy_legacy_support_core_utils.info" - deps = [ - ":androidx_annotation_annotation_java", - ":androidx_core_core_java", - ":androidx_documentfile_documentfile_java", - ":androidx_loader_loader_java", - ":androidx_localbroadcastmanager_localbroadcastmanager_java", - ":androidx_print_print_java", - ] - resource_overlay = true -} - -# This is generated, do not edit. Update BuildConfigGenerator.groovy instead. -android_aar_prebuilt("androidx_legacy_legacy_support_v13_java") { - aar_path = - "libs/androidx_legacy_legacy_support_v13/legacy-support-v13-1.0.0.aar" - info_path = "libs/androidx_legacy_legacy_support_v13/androidx_legacy_legacy_support_v13.info" - deps = [ ":androidx_legacy_legacy_support_v4_java" ] - resource_overlay = true -} - -# This is generated, do not edit. Update BuildConfigGenerator.groovy instead. android_aar_prebuilt("androidx_legacy_legacy_support_v4_java") { aar_path = "libs/androidx_legacy_legacy_support_v4/legacy-support-v4-1.0.0.aar" @@ -1988,6 +1931,50 @@ } # This is generated, do not edit. Update BuildConfigGenerator.groovy instead. +android_aar_prebuilt("androidx_legacy_legacy_support_core_ui_java") { + aar_path = "libs/androidx_legacy_legacy_support_core_ui/legacy-support-core-ui-1.0.0.aar" + info_path = "libs/androidx_legacy_legacy_support_core_ui/androidx_legacy_legacy_support_core_ui.info" + + # To remove visibility constraint, add this dependency to + # //third_party/android_deps/build.gradle. + visibility = [ ":*" ] + deps = [ + ":androidx_annotation_annotation_java", + ":androidx_asynclayoutinflater_asynclayoutinflater_java", + ":androidx_coordinatorlayout_coordinatorlayout_java", + ":androidx_core_core_java", + ":androidx_cursoradapter_cursoradapter_java", + ":androidx_customview_customview_java", + ":androidx_drawerlayout_drawerlayout_java", + ":androidx_interpolator_interpolator_java", + ":androidx_legacy_legacy_support_core_utils_java", + ":androidx_slidingpanelayout_slidingpanelayout_java", + ":androidx_swiperefreshlayout_swiperefreshlayout_java", + ":androidx_viewpager_viewpager_java", + ] + resource_overlay = true +} + +# This is generated, do not edit. Update BuildConfigGenerator.groovy instead. +android_aar_prebuilt("androidx_legacy_legacy_support_core_utils_java") { + aar_path = "libs/androidx_legacy_legacy_support_core_utils/legacy-support-core-utils-1.0.0.aar" + info_path = "libs/androidx_legacy_legacy_support_core_utils/androidx_legacy_legacy_support_core_utils.info" + + # To remove visibility constraint, add this dependency to + # //third_party/android_deps/build.gradle. + visibility = [ ":*" ] + deps = [ + ":androidx_annotation_annotation_java", + ":androidx_core_core_java", + ":androidx_documentfile_documentfile_java", + ":androidx_loader_loader_java", + ":androidx_localbroadcastmanager_localbroadcastmanager_java", + ":androidx_print_print_java", + ] + resource_overlay = true +} + +# This is generated, do not edit. Update BuildConfigGenerator.groovy instead. android_aar_prebuilt("androidx_lifecycle_lifecycle_livedata_java") { aar_path = "libs/androidx_lifecycle_lifecycle_livedata/lifecycle-livedata-2.0.0.aar"
diff --git a/third_party/android_deps/additional_readme_paths.json b/third_party/android_deps/additional_readme_paths.json index 712e39a..a2d7fb7c 100644 --- a/third_party/android_deps/additional_readme_paths.json +++ b/third_party/android_deps/additional_readme_paths.json
@@ -33,7 +33,6 @@ "libs/androidx_legacy_legacy_preference_v14", "libs/androidx_legacy_legacy_support_core_ui", "libs/androidx_legacy_legacy_support_core_utils", - "libs/androidx_legacy_legacy_support_v13", "libs/androidx_legacy_legacy_support_v4", "libs/androidx_lifecycle_lifecycle_common", "libs/androidx_lifecycle_lifecycle_common_java8",
diff --git a/third_party/android_deps/build.gradle b/third_party/android_deps/build.gradle index bd4cab8..5eaf0e5 100644 --- a/third_party/android_deps/build.gradle +++ b/third_party/android_deps/build.gradle
@@ -51,10 +51,6 @@ def androidXSupportLibVersion = '1.0.0' compile "androidx.core:core:1.1.0" compile "androidx.activity:activity:1.1.0" - compile "androidx.legacy:legacy-support-core-ui:${androidXSupportLibVersion}" - compile "androidx.legacy:legacy-support-core-utils:${androidXSupportLibVersion}" - compile "androidx.legacy:legacy-support-v4:${androidXSupportLibVersion}" - compile "androidx.legacy:legacy-support-v13:${androidXSupportLibVersion}" compile "androidx.annotation:annotation:1.1.0" compile "androidx.appcompat:appcompat:1.2.0-beta01" compile "androidx.appcompat:appcompat-resources:1.2.0-beta01" @@ -95,6 +91,9 @@ compile "androidx.multidex:multidex:2.0.0" compile "androidx.webkit:webkit:1.3.0-rc01" + // Used by 1p Play Services. + compile "androidx.legacy:legacy-support-v4:${androidXSupportLibVersion}" + // Replacement for com.android.support:design compile "com.google.android.material:material:1.2.0-alpha06"
diff --git a/third_party/android_deps/buildSrc/src/main/groovy/BuildConfigGenerator.groovy b/third_party/android_deps/buildSrc/src/main/groovy/BuildConfigGenerator.groovy index b6bf87ce..8be1857 100644 --- a/third_party/android_deps/buildSrc/src/main/groovy/BuildConfigGenerator.groovy +++ b/third_party/android_deps/buildSrc/src/main/groovy/BuildConfigGenerator.groovy
@@ -299,8 +299,16 @@ sb.append(' ignore_proguard_configs = true\n') break case 'androidx_fragment_fragment': - sb.append('\n') - sb.append(' ignore_proguard_configs = true\n') + sb.append("""\ + | deps += [ "//third_party/android_deps/local_modifications/androidx_fragment_fragment:androidx_fragment_fragment_prebuilt_java" ] + | # Omit this file since we use our own copy, included above. + | # We can remove this once we migrate to AndroidX master for all libraries. + | jar_excluded_patterns = [ + | "androidx/fragment/app/DialogFragment.java", + | ] + | + | ignore_proguard_configs = true + |""".stripMargin()) break case 'androidx_media_media': case 'androidx_versionedparcelable_versionedparcelable':
diff --git a/third_party/android_deps/local_modifications/androidx_fragment_fragment/BUILD.gn b/third_party/android_deps/local_modifications/androidx_fragment_fragment/BUILD.gn new file mode 100644 index 0000000..33eb2bef --- /dev/null +++ b/third_party/android_deps/local_modifications/androidx_fragment_fragment/BUILD.gn
@@ -0,0 +1,27 @@ +# Copyright 2020 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/android/rules.gni") + +# This rule contains the jar file produced by building +# :androidx_fragment_fragment_partial_java. After building the +# aforementioned target, the jar file can be found in: +# out/<dir>/lib.java/third_party/android_deps/local_modifications/androidx_fragment_fragment/androidx_fragment_fragment_partial_java.jar +android_java_prebuilt("androidx_fragment_fragment_prebuilt_java") { + jar_path = "androidx_fragment_fragment_java.jar" + + # Normally this would depend on //third_party/android_deps:androidx_fragment_fragment_java, + # but the dependency is reversed to keep the .class file customization + # transparent to dependents. Disable bytecode checks, which would otherwise + # complain about this. + enable_bytecode_checks = false +} + +android_library("androidx_fragment_fragment_partial_java") { + sources = [ "java/androidx/fragment/app/DialogFragment.java" ] + deps = [ + "//third_party/android_deps:androidx_annotation_annotation_java", + "//third_party/android_deps:androidx_fragment_fragment_java", + ] +}
diff --git a/third_party/android_deps/local_modifications/androidx_fragment_fragment/README b/third_party/android_deps/local_modifications/androidx_fragment_fragment/README new file mode 100644 index 0000000..5412163 --- /dev/null +++ b/third_party/android_deps/local_modifications/androidx_fragment_fragment/README
@@ -0,0 +1,11 @@ +This directory contains AndroidX's DialogFragment.java, copied from commit +88c22bfb, with c07daa2 merged in, which removes a problematic +Fragment.getActivity() call. + +To pull in these changes, we exclude DialogFragment from the +androidx_fragment_fragment library in CIPD (which is from an official +release), and add a dependency from that library to a prebuilt jar file +containing our customized DialogFragment.java. + +Note that this customization can be removed once we start pulling our +AndroidX dependencies from master.
diff --git a/third_party/android_deps/local_modifications/androidx_fragment_fragment/androidx_fragment_fragment_java.jar b/third_party/android_deps/local_modifications/androidx_fragment_fragment/androidx_fragment_fragment_java.jar new file mode 100644 index 0000000..9e7f008 --- /dev/null +++ b/third_party/android_deps/local_modifications/androidx_fragment_fragment/androidx_fragment_fragment_java.jar Binary files differ
diff --git a/third_party/android_deps/local_modifications/androidx_fragment_fragment/java/androidx/fragment/app/DialogFragment.java b/third_party/android_deps/local_modifications/androidx_fragment_fragment/java/androidx/fragment/app/DialogFragment.java new file mode 100644 index 0000000..018dba5 --- /dev/null +++ b/third_party/android_deps/local_modifications/androidx_fragment_fragment/java/androidx/fragment/app/DialogFragment.java
@@ -0,0 +1,540 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package androidx.fragment.app; +import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX; +import android.annotation.SuppressLint; +import android.app.Activity; +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import androidx.annotation.IntDef; +import androidx.annotation.MainThread; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.RestrictTo; +import androidx.annotation.StyleRes; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +/** + * Static library support version of the framework's {@link android.app.DialogFragment}. + * Used to write apps that run on platforms prior to Android 3.0. When running + * on Android 3.0 or above, this implementation is still used; it does not try + * to switch to the framework's implementation. See the framework SDK + * documentation for a class overview. + */ +public class DialogFragment extends Fragment + implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener { + /** @hide */ + @RestrictTo(LIBRARY_GROUP_PREFIX) + @IntDef({STYLE_NORMAL, STYLE_NO_TITLE, STYLE_NO_FRAME, STYLE_NO_INPUT}) + @Retention(RetentionPolicy.SOURCE) + private @interface DialogStyle {} + /** + * Style for {@link #setStyle(int, int)}: a basic, + * normal dialog. + */ + public static final int STYLE_NORMAL = 0; + /** + * Style for {@link #setStyle(int, int)}: don't include + * a title area. + */ + public static final int STYLE_NO_TITLE = 1; + /** + * Style for {@link #setStyle(int, int)}: don't draw + * any frame at all; the view hierarchy returned by {@link #onCreateView} + * is entirely responsible for drawing the dialog. + */ + public static final int STYLE_NO_FRAME = 2; + /** + * Style for {@link #setStyle(int, int)}: like + * {@link #STYLE_NO_FRAME}, but also disables all input to the dialog. + * The user can not touch it, and its window will not receive input focus. + */ + public static final int STYLE_NO_INPUT = 3; + private static final String SAVED_DIALOG_STATE_TAG = "android:savedDialogState"; + private static final String SAVED_STYLE = "android:style"; + private static final String SAVED_THEME = "android:theme"; + private static final String SAVED_CANCELABLE = "android:cancelable"; + private static final String SAVED_SHOWS_DIALOG = "android:showsDialog"; + private static final String SAVED_BACK_STACK_ID = "android:backStackId"; + private Handler mHandler; + private Runnable mDismissRunnable = new Runnable() { + @SuppressLint("SyntheticAccessor") + @Override + public void run() { + mOnDismissListener.onDismiss(mDialog); + } + }; + private DialogInterface.OnCancelListener mOnCancelListener = + new DialogInterface.OnCancelListener() { + @SuppressLint("SyntheticAccessor") + @Override + public void onCancel(@Nullable DialogInterface dialog) { + if (mDialog != null) { + DialogFragment.this.onCancel(mDialog); + } + } + }; + private DialogInterface.OnDismissListener mOnDismissListener = + new DialogInterface.OnDismissListener() { + @SuppressLint("SyntheticAccessor") + @Override + public void onDismiss(@Nullable DialogInterface dialog) { + if (mDialog != null) { + DialogFragment.this.onDismiss(mDialog); + } + } + }; + private int mStyle = STYLE_NORMAL; + private int mTheme = 0; + private boolean mCancelable = true; + private boolean mShowsDialog = true; + private int mBackStackId = -1; + private boolean mCreatingDialog; + @Nullable + private Dialog mDialog; + private boolean mViewDestroyed; + private boolean mDismissed; + private boolean mShownByMe; + public DialogFragment() { + } + /** + * Call to customize the basic appearance and behavior of the + * fragment's dialog. This can be used for some common dialog behaviors, + * taking care of selecting flags, theme, and other options for you. The + * same effect can be achieve by manually setting Dialog and Window + * attributes yourself. Calling this after the fragment's Dialog is + * created will have no effect. + * + * @param style Selects a standard style: may be {@link #STYLE_NORMAL}, + * {@link #STYLE_NO_TITLE}, {@link #STYLE_NO_FRAME}, or + * {@link #STYLE_NO_INPUT}. + * @param theme Optional custom theme. If 0, an appropriate theme (based + * on the style) will be selected for you. + */ + public void setStyle(@DialogStyle int style, @StyleRes int theme) { + mStyle = style; + if (mStyle == STYLE_NO_FRAME || mStyle == STYLE_NO_INPUT) { + mTheme = android.R.style.Theme_Panel; + } + if (theme != 0) { + mTheme = theme; + } + } + /** + * Display the dialog, adding the fragment to the given FragmentManager. This + * is a convenience for explicitly creating a transaction, adding the + * fragment to it with the given tag, and {@link FragmentTransaction#commit() committing} it. + * This does <em>not</em> add the transaction to the fragment back stack. When the fragment + * is dismissed, a new transaction will be executed to remove it from + * the activity. + * @param manager The FragmentManager this fragment will be added to. + * @param tag The tag for this fragment, as per + * {@link FragmentTransaction#add(Fragment, String) FragmentTransaction.add}. + */ + public void show(@NonNull FragmentManager manager, @Nullable String tag) { + mDismissed = false; + mShownByMe = true; + FragmentTransaction ft = manager.beginTransaction(); + ft.add(this, tag); + ft.commit(); + } + /** + * Display the dialog, adding the fragment using an existing transaction + * and then {@link FragmentTransaction#commit() committing} the transaction. + * @param transaction An existing transaction in which to add the fragment. + * @param tag The tag for this fragment, as per + * {@link FragmentTransaction#add(Fragment, String) FragmentTransaction.add}. + * @return Returns the identifier of the committed transaction, as per + * {@link FragmentTransaction#commit() FragmentTransaction.commit()}. + */ + public int show(@NonNull FragmentTransaction transaction, @Nullable String tag) { + mDismissed = false; + mShownByMe = true; + transaction.add(this, tag); + mViewDestroyed = false; + mBackStackId = transaction.commit(); + return mBackStackId; + } + /** + * Display the dialog, immediately adding the fragment to the given FragmentManager. This + * is a convenience for explicitly creating a transaction, adding the + * fragment to it with the given tag, and calling {@link FragmentTransaction#commitNow()}. + * This does <em>not</em> add the transaction to the fragment back stack. When the fragment + * is dismissed, a new transaction will be executed to remove it from + * the activity. + * @param manager The FragmentManager this fragment will be added to. + * @param tag The tag for this fragment, as per + * {@link FragmentTransaction#add(Fragment, String) FragmentTransaction.add}. + */ + public void showNow(@NonNull FragmentManager manager, @Nullable String tag) { + mDismissed = false; + mShownByMe = true; + FragmentTransaction ft = manager.beginTransaction(); + ft.add(this, tag); + ft.commitNow(); + } + /** + * Dismiss the fragment and its dialog. If the fragment was added to the + * back stack, all back stack state up to and including this entry will + * be popped. Otherwise, a new transaction will be committed to remove + * the fragment. + */ + public void dismiss() { + dismissInternal(false, false); + } + /** + * Version of {@link #dismiss()} that uses + * {@link FragmentTransaction#commitAllowingStateLoss() + * FragmentTransaction.commitAllowingStateLoss()}. See linked + * documentation for further details. + */ + public void dismissAllowingStateLoss() { + dismissInternal(true, false); + } + private void dismissInternal(boolean allowStateLoss, boolean fromOnDismiss) { + if (mDismissed) { + return; + } + mDismissed = true; + mShownByMe = false; + if (mDialog != null) { + // Instead of waiting for a posted onDismiss(), null out + // the listener and call onDismiss() manually to ensure + // that the callback happens before onDestroy() + mDialog.setOnDismissListener(null); + mDialog.dismiss(); + if (!fromOnDismiss) { + // onDismiss() is always called on the main thread, so + // we mimic that behavior here. The difference here is that + // we don't post the message to ensure that the onDismiss() + // callback still happens before onDestroy() + if (Looper.myLooper() == mHandler.getLooper()) { + onDismiss(mDialog); + } else { + mHandler.post(mDismissRunnable); + } + } + } + mViewDestroyed = true; + if (mBackStackId >= 0) { + getParentFragmentManager().popBackStack(mBackStackId, + FragmentManager.POP_BACK_STACK_INCLUSIVE); + mBackStackId = -1; + } else { + FragmentTransaction ft = getParentFragmentManager().beginTransaction(); + ft.remove(this); + if (allowStateLoss) { + ft.commitAllowingStateLoss(); + } else { + ft.commit(); + } + } + } + /** + * Return the {@link Dialog} this fragment is currently controlling. + * + * @see #requireDialog() + */ + @Nullable + public Dialog getDialog() { + return mDialog; + } + /** + * Return the {@link Dialog} this fragment is currently controlling. + * + * @throws IllegalStateException if the Dialog has not yet been created (before + * {@link #onCreateDialog(Bundle)}) or has been destroyed (after {@link #onDestroyView()}. + * @see #getDialog() + */ + @NonNull + public final Dialog requireDialog() { + Dialog dialog = getDialog(); + if (dialog == null) { + throw new IllegalStateException("DialogFragment " + this + " does not have a Dialog."); + } + return dialog; + } + @StyleRes + public int getTheme() { + return mTheme; + } + /** + * Control whether the shown Dialog is cancelable. Use this instead of + * directly calling {@link Dialog#setCancelable(boolean) + * Dialog.setCancelable(boolean)}, because DialogFragment needs to change + * its behavior based on this. + * + * @param cancelable If true, the dialog is cancelable. The default + * is true. + */ + public void setCancelable(boolean cancelable) { + mCancelable = cancelable; + if (mDialog != null) mDialog.setCancelable(cancelable); + } + /** + * Return the current value of {@link #setCancelable(boolean)}. + */ + public boolean isCancelable() { + return mCancelable; + } + /** + * Controls whether this fragment should be shown in a dialog. If not + * set, no Dialog will be created in {@link #onActivityCreated(Bundle)}, + * and the fragment's view hierarchy will thus not be added to it. This + * allows you to instead use it as a normal fragment (embedded inside of + * its activity). + * + * <p>This is normally set for you based on whether the fragment is + * associated with a container view ID passed to + * {@link FragmentTransaction#add(int, Fragment) FragmentTransaction.add(int, Fragment)}. + * If the fragment was added with a container, setShowsDialog will be + * initialized to false; otherwise, it will be true. + * + * @param showsDialog If true, the fragment will be displayed in a Dialog. + * If false, no Dialog will be created and the fragment's view hierarchy + * left undisturbed. + */ + public void setShowsDialog(boolean showsDialog) { + mShowsDialog = showsDialog; + } + /** + * Return the current value of {@link #setShowsDialog(boolean)}. + */ + public boolean getShowsDialog() { + return mShowsDialog; + } + @MainThread + @Override + public void onAttach(@NonNull Context context) { + super.onAttach(context); + if (!mShownByMe) { + // If not explicitly shown through our API, take this as an + // indication that the dialog is no longer dismissed. + mDismissed = false; + } + } + @MainThread + @Override + public void onDetach() { + super.onDetach(); + if (!mShownByMe && !mDismissed) { + // The fragment was not shown by a direct call here, it is not + // dismissed, and now it is being detached... well, okay, thou + // art now dismissed. Have fun. + mDismissed = true; + } + } + @MainThread + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + // This assumes that onCreate() is being called on the main thread + mHandler = new Handler(); + mShowsDialog = mContainerId == 0; + if (savedInstanceState != null) { + mStyle = savedInstanceState.getInt(SAVED_STYLE, STYLE_NORMAL); + mTheme = savedInstanceState.getInt(SAVED_THEME, 0); + mCancelable = savedInstanceState.getBoolean(SAVED_CANCELABLE, true); + mShowsDialog = savedInstanceState.getBoolean(SAVED_SHOWS_DIALOG, mShowsDialog); + mBackStackId = savedInstanceState.getInt(SAVED_BACK_STACK_ID, -1); + } + } + /** + * {@inheritDoc} + * + * <p> + * If this is called from within {@link #onCreateDialog(Bundle)}, the layout inflater from + * {@link Fragment#onGetLayoutInflater(Bundle)}, without the dialog theme, will be returned. + */ + @Override + @NonNull + public LayoutInflater onGetLayoutInflater(@Nullable Bundle savedInstanceState) { + LayoutInflater layoutInflater = super.onGetLayoutInflater(savedInstanceState); + if (!mShowsDialog || mCreatingDialog) { + return layoutInflater; + } + try { + mCreatingDialog = true; + mDialog = onCreateDialog(savedInstanceState); + setupDialog(mDialog, mStyle); + } finally { + mCreatingDialog = false; + } + return layoutInflater.cloneInContext(requireDialog().getContext()); + } + /** @hide */ + @RestrictTo(LIBRARY_GROUP_PREFIX) + public void setupDialog(@NonNull Dialog dialog, int style) { + switch (style) { + case STYLE_NO_INPUT: + Window window = dialog.getWindow(); + if (window != null) { + window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE + | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE); + } + // fall through... + case STYLE_NO_FRAME: + case STYLE_NO_TITLE: + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + } + } + /** + * Override to build your own custom Dialog container. This is typically + * used to show an AlertDialog instead of a generic Dialog; when doing so, + * {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)} does not need + * to be implemented since the AlertDialog takes care of its own content. + * + * <p>This method will be called after {@link #onCreate(Bundle)} and + * before {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}. The + * default implementation simply instantiates and returns a {@link Dialog} + * class. + * + * <p><em>Note: DialogFragment own the {@link Dialog#setOnCancelListener + * Dialog.setOnCancelListener} and {@link Dialog#setOnDismissListener + * Dialog.setOnDismissListener} callbacks. You must not set them yourself.</em> + * To find out about these events, override {@link #onCancel(DialogInterface)} + * and {@link #onDismiss(DialogInterface)}.</p> + * + * @param savedInstanceState The last saved instance state of the Fragment, + * or null if this is a freshly created Fragment. + * + * @return Return a new Dialog instance to be displayed by the Fragment. + */ + @MainThread + @NonNull + public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { + return new Dialog(requireContext(), getTheme()); + } + @Override + public void onCancel(@NonNull DialogInterface dialog) { + } + @Override + public void onDismiss(@NonNull DialogInterface dialog) { + if (!mViewDestroyed) { + // Note: we need to use allowStateLoss, because the dialog + // dispatches this asynchronously so we can receive the call + // after the activity is paused. Worst case, when the user comes + // back to the activity they see the dialog again. + dismissInternal(true, true); + } + } + @MainThread + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + if (!mShowsDialog) { + return; + } + View view = getView(); + if (mDialog != null) { + if (view != null) { + if (view.getParent() != null) { + throw new IllegalStateException( + "DialogFragment can not be attached to a container view"); + } + mDialog.setContentView(view); + } + final Context context = getContext(); + if (context instanceof Activity) { + mDialog.setOwnerActivity((Activity) context); + } + mDialog.setCancelable(mCancelable); + mDialog.setOnCancelListener(mOnCancelListener); + mDialog.setOnDismissListener(mOnDismissListener); + if (savedInstanceState != null) { + Bundle dialogState = savedInstanceState.getBundle(SAVED_DIALOG_STATE_TAG); + if (dialogState != null) { + mDialog.onRestoreInstanceState(dialogState); + } + } + } + } + @MainThread + @Override + public void onStart() { + super.onStart(); + if (mDialog != null) { + mViewDestroyed = false; + mDialog.show(); + } + } + @MainThread + @Override + public void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + if (mDialog != null) { + Bundle dialogState = mDialog.onSaveInstanceState(); + outState.putBundle(SAVED_DIALOG_STATE_TAG, dialogState); + } + if (mStyle != STYLE_NORMAL) { + outState.putInt(SAVED_STYLE, mStyle); + } + if (mTheme != 0) { + outState.putInt(SAVED_THEME, mTheme); + } + if (!mCancelable) { + outState.putBoolean(SAVED_CANCELABLE, mCancelable); + } + if (!mShowsDialog) { + outState.putBoolean(SAVED_SHOWS_DIALOG, mShowsDialog); + } + if (mBackStackId != -1) { + outState.putInt(SAVED_BACK_STACK_ID, mBackStackId); + } + } + @MainThread + @Override + public void onStop() { + super.onStop(); + if (mDialog != null) { + mDialog.hide(); + } + } + /** + * Remove dialog. + */ + @MainThread + @Override + public void onDestroyView() { + super.onDestroyView(); + if (mDialog != null) { + // Set removed here because this dismissal is just to hide + // the dialog -- we don't want this to cause the fragment to + // actually be removed. + mViewDestroyed = true; + // Instead of waiting for a posted onDismiss(), null out + // the listener and call onDismiss() manually to ensure + // that the callback happens before onDestroy() + mDialog.setOnDismissListener(null); + mDialog.dismiss(); + if (!mDismissed) { + // Don't send a second onDismiss() callback if we've already + // dismissed the dialog manually in dismissInternal() + onDismiss(mDialog); + } + mDialog = null; + } + } +}
diff --git a/third_party/android_swipe_refresh/BUILD.gn b/third_party/android_swipe_refresh/BUILD.gn index 6352c443..8224213 100644 --- a/third_party/android_swipe_refresh/BUILD.gn +++ b/third_party/android_swipe_refresh/BUILD.gn
@@ -16,6 +16,5 @@ deps = [ "//third_party/android_deps:androidx_annotation_annotation_java", "//third_party/android_deps:androidx_interpolator_interpolator_java", - "//third_party/android_deps:androidx_legacy_legacy_support_core_ui_java", ] }
diff --git a/third_party/blink/common/associated_interfaces/associated_interface_provider.cc b/third_party/blink/common/associated_interfaces/associated_interface_provider.cc index 226a471..93b82ccf 100644 --- a/third_party/blink/common/associated_interfaces/associated_interface_provider.cc +++ b/third_party/blink/common/associated_interfaces/associated_interface_provider.cc
@@ -20,7 +20,7 @@ explicit LocalProvider( scoped_refptr<base::SingleThreadTaskRunner> task_runner) { associated_interface_provider_receiver_.Bind( - remote_.BindNewEndpointAndPassDedicatedReceiverForTesting(), + remote_.BindNewEndpointAndPassDedicatedReceiver(), std::move(task_runner)); }
diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl index 8df7dd6f..7bebf4d 100644 --- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl +++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
@@ -7698,7 +7698,7 @@ optional StreamCompression streamCompression # A domain for letting clients substitute browser's network layer with client code. -experimental domain Fetch +domain Fetch depends on Network depends on IO depends on Page @@ -7709,12 +7709,12 @@ # Stages of the request to handle. Request will intercept before the request is # sent. Response will intercept after the response is received (but before response # body is received. - experimental type RequestStage extends string + type RequestStage extends string enum Request Response - experimental type RequestPattern extends object + type RequestPattern extends object properties # Wildcards ('*' -> zero or more, '?' -> exactly one) are allowed. Escape character is # backslash. Omitting is equivalent to "*". @@ -7731,7 +7731,7 @@ string value # Authorization challenge for HTTP status code 401 or 407. - experimental type AuthChallenge extends object + type AuthChallenge extends object properties # Source of the authentication challenge. optional enum source @@ -7745,7 +7745,7 @@ string realm # Response to an AuthChallenge. - experimental type AuthChallengeResponse extends object + type AuthChallengeResponse extends object properties # The decision on what to do in response to the authorization challenge. Default means # deferring to the default behavior of the net stack, which will likely either the Cancel
diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn index 361bc12..d263afb 100644 --- a/third_party/blink/public/mojom/BUILD.gn +++ b/third_party/blink/public/mojom/BUILD.gn
@@ -77,6 +77,7 @@ "insecure_input/insecure_input_service.mojom", "keyboard_lock/keyboard_lock.mojom", "leak_detector/leak_detector.mojom", + "link_to_text/link_to_text.mojom", "loader/code_cache.mojom", "loader/content_security_notifier.mojom", "loader/fetch_client_settings_object.mojom",
diff --git a/third_party/blink/public/mojom/android_font_lookup/android_font_lookup.mojom b/third_party/blink/public/mojom/android_font_lookup/android_font_lookup.mojom index c81d20c..0602d8c 100644 --- a/third_party/blink/public/mojom/android_font_lookup/android_font_lookup.mojom +++ b/third_party/blink/public/mojom/android_font_lookup/android_font_lookup.mojom
@@ -11,8 +11,6 @@ interface AndroidFontLookup { // Returns a list of ICU case folded full font names available to be fetched // locally from on-device storage, without a network roundtrip. - // TODO(crbug.com/1111148): Complete implementation of this method in - // AndroidFontLookupImpl.java. Currently returns empty list. GetUniqueNameLookupTable() => (array<string> available_unique_font_names);
diff --git a/third_party/blink/public/mojom/link_to_text/OWNERS b/third_party/blink/public/mojom/link_to_text/OWNERS new file mode 100644 index 0000000..bf01ee9e --- /dev/null +++ b/third_party/blink/public/mojom/link_to_text/OWNERS
@@ -0,0 +1,4 @@ +# COMPONENT: UI>Browser>Sharing + +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS \ No newline at end of file
diff --git a/third_party/blink/public/mojom/link_to_text/link_to_text.mojom b/third_party/blink/public/mojom/link_to_text/link_to_text.mojom new file mode 100644 index 0000000..342f4a1 --- /dev/null +++ b/third_party/blink/public/mojom/link_to_text/link_to_text.mojom
@@ -0,0 +1,14 @@ +// 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. + +[JavaPackage="org.chromium.blink.mojom"] +module blink.mojom; + +// TextFragmentSelectorProducer is used for requesting renderer to generate +// text fragment selector for the latest text selection. Implemented in renderer. +interface TextFragmentSelectorProducer { + // Generates text fragment selector according to + // https://github.com/WICG/scroll-to-text-fragment#proposed-solution. + GenerateSelector() => (string selector); +};
diff --git a/third_party/blink/public/mojom/web_feature/web_feature.mojom b/third_party/blink/public/mojom/web_feature/web_feature.mojom index 50241098..6388c4b4 100644 --- a/third_party/blink/public/mojom/web_feature/web_feature.mojom +++ b/third_party/blink/public/mojom/web_feature/web_feature.mojom
@@ -2794,6 +2794,7 @@ kCSSContainAllWithoutContentVisibility = 3467, kTimerInstallFromBeforeUnload = 3468, kTimerInstallFromUnload = 3469, + kElementAttachInternalsBeforeConstructor = 3470, // Add new features immediately above this line. Don't change assigned // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition.cc b/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition.cc index 763fdc7e..82d310fd 100644 --- a/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition.cc +++ b/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition.cc
@@ -214,6 +214,9 @@ return false; } + // 8.1.new: set custom element state to kPreCustomized. + element.SetCustomElementState(CustomElementState::kPreCustomized); + Element* result = CallConstructor(); // To report exception thrown from callConstructor()
diff --git a/third_party/blink/renderer/core/dom/element.h b/third_party/blink/renderer/core/dom/element.h index 2d88b0c4..897dc26 100644 --- a/third_party/blink/renderer/core/dom/element.h +++ b/third_party/blink/renderer/core/dom/element.h
@@ -804,6 +804,8 @@ // legacy layout on the entire subtree, unless this is overridden by // ShouldForceNGLayout(). bool ShouldForceLegacyLayout() const { + if (ShouldForceNGLayout()) + return false; if (TypeShouldForceLegacyLayout()) return true; if (!HasRareData())
diff --git a/third_party/blink/renderer/core/dom/node.cc b/third_party/blink/renderer/core/dom/node.cc index 91b64e82..cef59fe 100644 --- a/third_party/blink/renderer/core/dom/node.cc +++ b/third_party/blink/renderer/core/dom/node.cc
@@ -3232,12 +3232,17 @@ case CustomElementState::kCustom: DCHECK(old_state == CustomElementState::kUndefined || - old_state == CustomElementState::kFailed); + old_state == CustomElementState::kFailed || + old_state == CustomElementState::kPreCustomized); break; case CustomElementState::kFailed: DCHECK_NE(CustomElementState::kFailed, old_state); break; + + case CustomElementState::kPreCustomized: + DCHECK_EQ(CustomElementState::kFailed, old_state); + break; } DCHECK(IsHTMLElement());
diff --git a/third_party/blink/renderer/core/dom/node.h b/third_party/blink/renderer/core/dom/node.h index c5679a7..261c41a 100644 --- a/third_party/blink/renderer/core/dom/node.h +++ b/third_party/blink/renderer/core/dom/node.h
@@ -101,8 +101,9 @@ // https://dom.spec.whatwg.org/#concept-element-custom-element-state kUncustomized = 0, kCustom = 1 << kNodeCustomElementShift, - kUndefined = 2 << kNodeCustomElementShift, - kFailed = 3 << kNodeCustomElementShift, + kPreCustomized = 2 << kNodeCustomElementShift, + kUndefined = 3 << kNodeCustomElementShift, + kFailed = 4 << kNodeCustomElementShift, }; enum class SlotChangeType { @@ -970,24 +971,24 @@ kChildNeedsStyleRecalcFlag = 1 << 16, kStyleChangeMask = 0x3 << kNodeStyleChangeShift, - kCustomElementStateMask = 0x3 << kNodeCustomElementShift, + kCustomElementStateMask = 0x7 << kNodeCustomElementShift, - kHasNameOrIsEditingTextFlag = 1 << 21, - kHasEventTargetDataFlag = 1 << 22, + kHasNameOrIsEditingTextFlag = 1 << 22, + kHasEventTargetDataFlag = 1 << 23, - kV0CustomElementFlag = 1 << 23, - kV0CustomElementUpgradedFlag = 1 << 24, + kV0CustomElementFlag = 1 << 24, + kV0CustomElementUpgradedFlag = 1 << 25, - kNeedsReattachLayoutTree = 1 << 25, - kChildNeedsReattachLayoutTree = 1 << 26, + kNeedsReattachLayoutTree = 1 << 26, + kChildNeedsReattachLayoutTree = 1 << 27, - kHasDuplicateAttributes = 1 << 27, + kHasDuplicateAttributes = 1 << 28, - kForceReattachLayoutTree = 1 << 28, + kForceReattachLayoutTree = 1 << 29, kDefaultNodeFlags = kIsFinishedParsingChildrenFlag, - // 4 bits remaining. + // 3 bits remaining. }; ALWAYS_INLINE bool GetFlag(NodeFlags mask) const {
diff --git a/third_party/blink/renderer/core/exported/web_view_test.cc b/third_party/blink/renderer/core/exported/web_view_test.cc index 2bd09ae7..ea9483da 100644 --- a/third_party/blink/renderer/core/exported/web_view_test.cc +++ b/third_party/blink/renderer/core/exported/web_view_test.cc
@@ -4115,8 +4115,7 @@ mojo::PendingAssociatedRemote<mojom::blink::FrameWidgetHost> BindNewFrameWidgetInterfaces() { frame_widget_host_receiver_.reset(); - return frame_widget_host_receiver_ - .BindNewEndpointAndPassDedicatedRemoteForTesting(); + return frame_widget_host_receiver_.BindNewEndpointAndPassDedicatedRemote(); } int GetAndResetHasTouchEventHandlerCallCount(bool state) {
diff --git a/third_party/blink/renderer/core/fileapi/public_url_manager_test.cc b/third_party/blink/renderer/core/fileapi/public_url_manager_test.cc index daba5f4..1489d43 100644 --- a/third_party/blink/renderer/core/fileapi/public_url_manager_test.cc +++ b/third_party/blink/renderer/core/fileapi/public_url_manager_test.cc
@@ -77,7 +77,7 @@ HeapMojoAssociatedRemote<BlobURLStore> url_store_remote(execution_context_); url_store_receiver_.Bind( - url_store_remote.BindNewEndpointAndPassDedicatedReceiverForTesting()); + url_store_remote.BindNewEndpointAndPassDedicatedReceiver()); url_manager().SetURLStoreForTesting(std::move(url_store_remote)); }
diff --git a/third_party/blink/renderer/core/frame/deprecation.cc b/third_party/blink/renderer/core/frame/deprecation.cc index d1712bd..49991d5 100644 --- a/third_party/blink/renderer/core/frame/deprecation.cc +++ b/third_party/blink/renderer/core/frame/deprecation.cc
@@ -67,6 +67,7 @@ kM86 = 86, kM87 = 87, kM88 = 88, + kM89 = 89, }; // Returns estimated milestone dates as milliseconds since January 1, 1970. @@ -112,25 +113,17 @@ case kM83: return {2020, 5, 0, 18, 4}; case kM84: - // This release is not yet scheduled, so this date is a guess. - // https://groups.google.com/a/chromium.org/d/msg/chromium-dev/N1NxbSVOZas/ySlEKDKkBgAJ return {2020, 7, 0, 14, 4}; case kM85: - // This release is not yet scheduled, so this date is a guess. - // https://groups.google.com/a/chromium.org/d/msg/chromium-dev/N1NxbSVOZas/ySlEKDKkBgAJ return {2020, 8, 0, 25, 4}; case kM86: - // This release is not yet scheduled, so this date is a guess. - // https://groups.google.com/a/chromium.org/d/msg/chromium-dev/N1NxbSVOZas/ySlEKDKkBgAJ return {2020, 10, 0, 6, 4}; case kM87: - // This release is not yet scheduled, so this date is a guess. - // https://groups.google.com/a/chromium.org/d/msg/chromium-dev/N1NxbSVOZas/ySlEKDKkBgAJ return {2020, 11, 0, 17, 4}; case kM88: - // This release is not yet scheduled, so this date is a guess. - // https://groups.google.com/a/chromium.org/d/msg/chromium-dev/N1NxbSVOZas/ySlEKDKkBgAJ return {2021, 1, 0, 19, 4}; + case kM89: + return {2021, 3, 0, 2, 4}; } NOTREACHED(); @@ -575,6 +568,11 @@ "RTCConfiguration.encodedInsertableStreams", kM88, "6321945865879552")}; + case WebFeature::kCommaSeparatorInAllowAttribute: + return {"CommaSeparatorInAllowAttribute", kM89, + ReplacedWillBeRemoved("Comma separator in iframe allow attribute", + "semicolons", kM89, "5740835259809792")}; + // Features that aren't deprecated don't have a deprecation message. default: return {"NotDeprecated", kUnknown, ""};
diff --git a/third_party/blink/renderer/core/frame/frame_test_helpers.cc b/third_party/blink/renderer/core/frame/frame_test_helpers.cc index e6ac373..c440d6f 100644 --- a/third_party/blink/renderer/core/frame/frame_test_helpers.cc +++ b/third_party/blink/renderer/core/frame/frame_test_helpers.cc
@@ -257,17 +257,16 @@ mojo::AssociatedRemote<mojom::blink::FrameWidget> frame_widget_remote; mojo::PendingAssociatedReceiver<mojom::blink::FrameWidget> frame_widget_receiver = - frame_widget_remote - .BindNewEndpointAndPassDedicatedReceiverForTesting(); + frame_widget_remote.BindNewEndpointAndPassDedicatedReceiver(); mojo::AssociatedRemote<mojom::blink::FrameWidgetHost> frame_widget_host; mojo::PendingAssociatedReceiver<mojom::blink::FrameWidgetHost> frame_widget_host_receiver = - frame_widget_host.BindNewEndpointAndPassDedicatedReceiverForTesting(); + frame_widget_host.BindNewEndpointAndPassDedicatedReceiver(); mojo::AssociatedRemote<mojom::blink::Widget> widget_remote; mojo::PendingAssociatedReceiver<mojom::blink::Widget> widget_receiver = - widget_remote.BindNewEndpointAndPassDedicatedReceiverForTesting(); + widget_remote.BindNewEndpointAndPassDedicatedReceiver(); // Create a local root, if necessary. if (!frame->Parent()) { @@ -346,17 +345,16 @@ mojo::AssociatedRemote<mojom::blink::FrameWidget> frame_widget_remote; mojo::PendingAssociatedReceiver<mojom::blink::FrameWidget> frame_widget_receiver = - frame_widget_remote - .BindNewEndpointAndPassDedicatedReceiverForTesting(); + frame_widget_remote.BindNewEndpointAndPassDedicatedReceiver(); mojo::AssociatedRemote<mojom::blink::FrameWidgetHost> frame_widget_host; mojo::PendingAssociatedReceiver<mojom::blink::FrameWidgetHost> frame_widget_host_receiver = - frame_widget_host.BindNewEndpointAndPassDedicatedReceiverForTesting(); + frame_widget_host.BindNewEndpointAndPassDedicatedReceiver(); mojo::AssociatedRemote<mojom::blink::Widget> widget_remote; mojo::PendingAssociatedReceiver<mojom::blink::Widget> widget_receiver = - widget_remote.BindNewEndpointAndPassDedicatedReceiverForTesting(); + widget_remote.BindNewEndpointAndPassDedicatedReceiver(); WebFrameWidget* frame_widget = WebFrameWidget::CreateForChildLocalRoot( widget_client, frame, frame_widget_host.Unbind(), @@ -434,16 +432,16 @@ mojo::AssociatedRemote<mojom::blink::FrameWidget> frame_widget; mojo::PendingAssociatedReceiver<mojom::blink::FrameWidget> frame_widget_receiver = - frame_widget.BindNewEndpointAndPassDedicatedReceiverForTesting(); + frame_widget.BindNewEndpointAndPassDedicatedReceiver(); mojo::AssociatedRemote<mojom::blink::FrameWidgetHost> frame_widget_host; mojo::PendingAssociatedReceiver<mojom::blink::FrameWidgetHost> frame_widget_host_receiver = - frame_widget_host.BindNewEndpointAndPassDedicatedReceiverForTesting(); + frame_widget_host.BindNewEndpointAndPassDedicatedReceiver(); mojo::AssociatedRemote<mojom::blink::Widget> widget_remote; mojo::PendingAssociatedReceiver<mojom::blink::Widget> widget_receiver = - widget_remote.BindNewEndpointAndPassDedicatedReceiverForTesting(); + widget_remote.BindNewEndpointAndPassDedicatedReceiver(); // TODO(dcheng): The main frame widget currently has a special case. // Eliminate this once WebView is no longer a WebWidget. @@ -760,7 +758,7 @@ mojo::PendingAssociatedRemote<mojom::blink::WidgetHost> TestWebWidgetClient::BindNewWidgetHost() { receiver_.reset(); - return receiver_.BindNewEndpointAndPassDedicatedRemoteForTesting(); + return receiver_.BindNewEndpointAndPassDedicatedRemote(); } bool TestWebWidgetClient::HaveScrollEventHandlers() const {
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc index 29079e5c..137aade 100644 --- a/third_party/blink/renderer/core/frame/local_frame.cc +++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -152,6 +152,7 @@ #include "third_party/blink/renderer/core/page/plugin_script_forbidden_scope.h" #include "third_party/blink/renderer/core/page/pointer_lock_controller.h" #include "third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.h" +#include "third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator.h" #include "third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_as_text.h" #include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h" #include "third_party/blink/renderer/core/paint/object_painter.h" @@ -357,6 +358,13 @@ WTF::BindRepeating(&LocalFrame::BindToHighPriorityReceiver, WrapWeakPersistent(this)), GetTaskRunner(blink::TaskType::kInternalHighPriorityLocalFrame)); + + if (IsMainFrame()) { + GetInterfaceRegistry()->AddInterface( + WTF::BindRepeating(&LocalFrame::BindTextFragmentSelectorProducer, + WrapWeakPersistent(this))); + } + SetOpenerDoNotNotify(opener); loader_.Init(); } @@ -455,6 +463,7 @@ visitor->Trace(receiver_); visitor->Trace(main_frame_receiver_); visitor->Trace(high_priority_frame_receiver_); + visitor->Trace(text_fragment_selector_generator_); Frame::Trace(visitor); Supplementable<LocalFrame>::Trace(visitor); } @@ -592,7 +601,11 @@ // up calling back to LocalFrameClient via WindowProxy. GetScriptController().ClearForClose(); - DCHECK(!view_->IsAttached()); + if (text_fragment_selector_generator_) + text_fragment_selector_generator_->ClearSelection(); + + // TODO(crbug.com/729196): Trace why LocalFrameView::DetachFromLayout crashes. + CHECK(!view_->IsAttached()); SetView(nullptr); GetEventHandlerRegistry().DidRemoveAllEventHandlers(*DomWindow()); @@ -1386,6 +1399,10 @@ } DCHECK(ad_tracker_ ? RuntimeEnabledFeatures::AdTaggingEnabled() : !RuntimeEnabledFeatures::AdTaggingEnabled()); + if (IsMainFrame()) { + text_fragment_selector_generator_ = + MakeGarbageCollected<TextFragmentSelectorGenerator>(); + } Initialize(); @@ -3166,6 +3183,16 @@ GetTaskRunner(blink::TaskType::kInternalHighPriorityLocalFrame)); } +void LocalFrame::BindTextFragmentSelectorProducer( + mojo::PendingReceiver<mojom::blink::TextFragmentSelectorProducer> + receiver) { + if (IsDetached() || !text_fragment_selector_generator_) + return; + + text_fragment_selector_generator_->BindTextFragmentSelectorProducer( + std::move(receiver)); +} + SpellChecker& LocalFrame::GetSpellChecker() const { DCHECK(DomWindow()); return DomWindow()->GetSpellChecker();
diff --git a/third_party/blink/renderer/core/frame/local_frame.h b/third_party/blink/renderer/core/frame/local_frame.h index 785b893..213f430 100644 --- a/third_party/blink/renderer/core/frame/local_frame.h +++ b/third_party/blink/renderer/core/frame/local_frame.h
@@ -45,6 +45,7 @@ #include "third_party/blink/public/mojom/frame/lifecycle.mojom-blink-forward.h" #include "third_party/blink/public/mojom/frame/reporting_observer.mojom-blink-forward.h" #include "third_party/blink/public/mojom/input/focus_type.mojom-blink-forward.h" +#include "third_party/blink/public/mojom/link_to_text/link_to_text.mojom-blink.h" #include "third_party/blink/public/mojom/loader/pause_subresource_loading_handle.mojom-blink-forward.h" #include "third_party/blink/public/mojom/optimization_guide/optimization_guide.mojom-blink.h" #include "third_party/blink/public/mojom/reporting/reporting.mojom-blink.h" @@ -130,6 +131,7 @@ class ScriptController; class SmoothScrollSequencer; class SpellChecker; +class TextFragmentSelectorGenerator; class TextSuggestionController; class VirtualKeyboardOverlayChangedObserver; class WebContentSettingsClient; @@ -684,6 +686,10 @@ return LocalFrameToken(GetFrameToken()); } + TextFragmentSelectorGenerator* GetTextFragmentSelectorGenerator() const { + return text_fragment_selector_generator_; + } + private: friend class FrameNavigationDisabler; FRIEND_TEST_ALL_PREFIXES(LocalFrameTest, CharacterIndexAtPointWithPinchZoom); @@ -756,6 +762,10 @@ void BindToHighPriorityReceiver( mojo::PendingReceiver<mojom::blink::HighPriorityLocalFrame> receiver); + void BindTextFragmentSelectorProducer( + mojo::PendingReceiver<mojom::blink::TextFragmentSelectorProducer> + receiver); + std::unique_ptr<FrameScheduler> frame_scheduler_; // Holds all PauseSubresourceLoadingHandles allowing either |this| to delete @@ -897,6 +907,8 @@ Member<RawSystemClipboard> raw_system_clipboard_; mojom::blink::BlinkOptimizationGuideHintsPtr optimization_guide_hints_; + + Member<TextFragmentSelectorGenerator> text_fragment_selector_generator_; }; inline FrameLoader& LocalFrame::Loader() const {
diff --git a/third_party/blink/renderer/core/html/custom/custom_element_definition.cc b/third_party/blink/renderer/core/html/custom/custom_element_definition.cc index dbc617f5..6c647a44 100644 --- a/third_party/blink/renderer/core/html/custom/custom_element_definition.cc +++ b/third_party/blink/renderer/core/html/custom/custom_element_definition.cc
@@ -196,10 +196,10 @@ // https://html.spec.whatwg.org/C/#concept-upgrade-an-element void CustomElementDefinition::Upgrade(Element& element) { - // 4.13.5.1 If element is custom, then return. - // 4.13.5.2 If element's custom element state is "failed", then return. - if (element.GetCustomElementState() == CustomElementState::kCustom || - element.GetCustomElementState() == CustomElementState::kFailed) { + // 4.13.5.1 If element's custom element state is not "undefined" or + // "uncustomized", then return. + if (element.GetCustomElementState() != CustomElementState::kUndefined && + element.GetCustomElementState() != CustomElementState::kUncustomized) { return; }
diff --git a/third_party/blink/renderer/core/html/custom/element_internals.cc b/third_party/blink/renderer/core/html/custom/element_internals.cc index 70f3934..9f6f846d 100644 --- a/third_party/blink/renderer/core/html/custom/element_internals.cc +++ b/third_party/blink/renderer/core/html/custom/element_internals.cc
@@ -329,10 +329,11 @@ if (Target().IsFormAssociatedCustomElement()) return true; // Custom element could be in the process of upgrading here, during which - // it will have state kFailed according to: + // it will have state kFailed or kPreCustomized according to: // https://html.spec.whatwg.org/multipage/custom-elements.html#upgrades if (Target().GetCustomElementState() != CustomElementState::kUndefined && - Target().GetCustomElementState() != CustomElementState::kFailed) { + Target().GetCustomElementState() != CustomElementState::kFailed && + Target().GetCustomElementState() != CustomElementState::kPreCustomized) { return false; } // An element is in "undefined" state in its constructor JavaScript code.
diff --git a/third_party/blink/renderer/core/html/html_element.cc b/third_party/blink/renderer/core/html/html_element.cc index 28f1d9a..500eb4e6 100644 --- a/third_party/blink/renderer/core/html/html_element.cc +++ b/third_party/blink/renderer/core/html/html_element.cc
@@ -1583,6 +1583,7 @@ "Unable to attach ElementInternals to a customized built-in element."); return nullptr; } + CustomElementRegistry* registry = CustomElement::Registry(*this); auto* definition = registry ? registry->DefinitionForName(localName()) : nullptr; @@ -1592,6 +1593,7 @@ "Unable to attach ElementInternals to non-custom elements."); return nullptr; } + if (definition->DisableInternals()) { exception_state.ThrowDOMException( DOMExceptionCode::kNotSupportedError, @@ -1604,6 +1606,23 @@ "ElementInternals for the specified element was already attached."); return nullptr; } + + // If element's custom element state is not "precustomized" or "custom", + // throw "NotSupportedError" DOMException. + if (GetCustomElementState() != CustomElementState::kCustom && + GetCustomElementState() != CustomElementState::kPreCustomized) { + if (RuntimeEnabledFeatures::DeclarativeShadowDOMEnabled( + GetExecutionContext())) { + exception_state.ThrowDOMException( + DOMExceptionCode::kNotSupportedError, + "The attachInternals() function cannot be called prior to the " + "execution of the custom element constructor."); + return nullptr; + } + UseCounter::Count(GetDocument(), + WebFeature::kElementAttachInternalsBeforeConstructor); + } + UseCounter::Count(GetDocument(), WebFeature::kElementAttachInternals); SetDidAttachInternals(); return &EnsureElementInternals();
diff --git a/third_party/blink/renderer/core/html/html_iframe_element.cc b/third_party/blink/renderer/core/html/html_iframe_element.cc index 3d708f4..a367672 100644 --- a/third_party/blink/renderer/core/html/html_iframe_element.cc +++ b/third_party/blink/renderer/core/html/html_iframe_element.cc
@@ -39,6 +39,7 @@ #include "third_party/blink/renderer/core/feature_policy/iframe_policy.h" #include "third_party/blink/renderer/core/fetch/trust_token_issuance_authorization.h" #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h" +#include "third_party/blink/renderer/core/frame/deprecation.h" #include "third_party/blink/renderer/core/frame/sandbox_flags.h" #include "third_party/blink/renderer/core/html/html_document.h" #include "third_party/blink/renderer/core/html/trust_token_attribute_parsing.h" @@ -271,8 +272,9 @@ WebFeature::kFeaturePolicyAllowAttribute); } if (value.Contains(',')) { - UseCounter::Count(GetDocument(), - WebFeature::kCommaSeparatorInAllowAttribute); + Deprecation::CountDeprecation( + GetDocument().GetExecutionContext(), + WebFeature::kCommaSeparatorInAllowAttribute); } } } else if (name == html_names::kDisallowdocumentaccessAttr &&
diff --git a/third_party/blink/renderer/core/html/html_iframe_element_test.cc b/third_party/blink/renderer/core/html/html_iframe_element_test.cc index 5dfeb16..f7ed45f 100644 --- a/third_party/blink/renderer/core/html/html_iframe_element_test.cc +++ b/third_party/blink/renderer/core/html/html_iframe_element_test.cc
@@ -403,7 +403,7 @@ << ConsoleMessages().front(); } -TEST_F(HTMLIFrameElementSimTest, CommaSeparatorIsCounted) { +TEST_F(HTMLIFrameElementSimTest, CommaSeparatorIsDeprecated) { EXPECT_FALSE( GetDocument().Loader()->GetUseCounterHelper().HasRecordedMeasurement( WebFeature::kCommaSeparatorInAllowAttribute)); @@ -414,6 +414,12 @@ allow="fullscreen, geolocation"></iframe> )"); + EXPECT_EQ(ConsoleMessages().size(), 1u) + << "Comma separator in allow attribute should log a deprecation message " + "to the console."; + EXPECT_TRUE(ConsoleMessages().front().Contains("5740835259809792")) + << "Console message should mention the chromestatus entry."; + EXPECT_TRUE( GetDocument().Loader()->GetUseCounterHelper().HasRecordedMeasurement( WebFeature::kCommaSeparatorInAllowAttribute));
diff --git a/third_party/blink/renderer/core/html/parser/html_construction_site.cc b/third_party/blink/renderer/core/html/parser/html_construction_site.cc index b7644d32..870c7f5 100644 --- a/third_party/blink/renderer/core/html/parser/html_construction_site.cc +++ b/third_party/blink/renderer/core/html/parser/html_construction_site.cc
@@ -989,8 +989,10 @@ document, tag_name, GetCreateElementFlags(), is); } // Definition for the created element does not exist here and it cannot be - // custom or failed. + // custom, precustomized, or failed. DCHECK_NE(element->GetCustomElementState(), CustomElementState::kCustom); + DCHECK_NE(element->GetCustomElementState(), + CustomElementState::kPreCustomized); DCHECK_NE(element->GetCustomElementState(), CustomElementState::kFailed); // TODO(dominicc): Move these steps so they happen for custom
diff --git a/third_party/blink/renderer/core/mathml/mathml_element.cc b/third_party/blink/renderer/core/mathml/mathml_element.cc index 4ad7df7..cd9a5bf5 100644 --- a/third_party/blink/renderer/core/mathml/mathml_element.cc +++ b/third_party/blink/renderer/core/mathml/mathml_element.cc
@@ -9,6 +9,7 @@ #include "third_party/blink/renderer/core/css/parser/css_parser.h" #include "third_party/blink/renderer/core/css_value_keywords.h" #include "third_party/blink/renderer/core/dom/document.h" +#include "third_party/blink/renderer/core/dom/node_computed_style.h" #include "third_party/blink/renderer/core/html/html_element.h" namespace blink { @@ -144,4 +145,8 @@ HasTagName(mathml_names::kMsTag); } +bool MathMLElement::ShouldForceNGLayout() const { + return ComputedStyleRef().IsDisplayMathType(); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/mathml/mathml_element.h b/third_party/blink/renderer/core/mathml/mathml_element.h index 9b2fc77..b4ab8cd4 100644 --- a/third_party/blink/renderer/core/mathml/mathml_element.h +++ b/third_party/blink/renderer/core/mathml/mathml_element.h
@@ -55,8 +55,7 @@ private: // Force NG layout as MathML elements don't have legacy layout implementation. - // TODO(crbug.com/1127197): Check the display of the computed style. - bool ShouldForceNGLayout() const final { return true; } + bool ShouldForceNGLayout() const final; }; template <typename T>
diff --git a/third_party/blink/renderer/core/mathml/mathml_padded_element.cc b/third_party/blink/renderer/core/mathml/mathml_padded_element.cc index 858cc37..6f54654d 100644 --- a/third_party/blink/renderer/core/mathml/mathml_padded_element.cc +++ b/third_party/blink/renderer/core/mathml/mathml_padded_element.cc
@@ -85,7 +85,7 @@ LayoutObject* MathMLPaddedElement::CreateLayoutObject( const ComputedStyle& style, LegacyLayout legacy) { - DCHECK_NE(legacy, LegacyLayout::kForce); + DCHECK(!style.IsDisplayMathType() || legacy != LegacyLayout::kForce); if (!RuntimeEnabledFeatures::MathMLCoreEnabled() || !style.IsDisplayMathType()) return MathMLElement::CreateLayoutObject(style, legacy);
diff --git a/third_party/blink/renderer/core/mathml/mathml_radical_element.cc b/third_party/blink/renderer/core/mathml/mathml_radical_element.cc index fcabbd39..5409492b 100644 --- a/third_party/blink/renderer/core/mathml/mathml_radical_element.cc +++ b/third_party/blink/renderer/core/mathml/mathml_radical_element.cc
@@ -19,7 +19,7 @@ LayoutObject* MathMLRadicalElement::CreateLayoutObject( const ComputedStyle& style, LegacyLayout legacy) { - DCHECK_NE(legacy, LegacyLayout::kForce); + DCHECK(!style.IsDisplayMathType() || legacy != LegacyLayout::kForce); if (!RuntimeEnabledFeatures::MathMLCoreEnabled() || !style.IsDisplayMathType()) return MathMLElement::CreateLayoutObject(style, legacy);
diff --git a/third_party/blink/renderer/core/mathml/mathml_row_element.cc b/third_party/blink/renderer/core/mathml/mathml_row_element.cc index 535f9ed..57abe138 100644 --- a/third_party/blink/renderer/core/mathml/mathml_row_element.cc +++ b/third_party/blink/renderer/core/mathml/mathml_row_element.cc
@@ -15,9 +15,9 @@ LayoutObject* MathMLRowElement::CreateLayoutObject(const ComputedStyle& style, LegacyLayout legacy) { - DCHECK_NE(legacy, LegacyLayout::kForce); + DCHECK(!style.IsDisplayMathType() || legacy != LegacyLayout::kForce); if (!RuntimeEnabledFeatures::MathMLCoreEnabled() || - (!style.IsDisplayMathType() && !HasTagName(mathml_names::kMathTag))) + !style.IsDisplayMathType()) return MathMLElement::CreateLayoutObject(style, legacy); return new LayoutNGMathMLBlock(this); }
diff --git a/third_party/blink/renderer/core/page/DEPS b/third_party/blink/renderer/core/page/DEPS index 3799876..1ddb8e26 100644 --- a/third_party/blink/renderer/core/page/DEPS +++ b/third_party/blink/renderer/core/page/DEPS
@@ -7,4 +7,7 @@ "chrome_client_impl_test\.cc": [ "+base/run_loop.h", ], + "text_fragment_selector_generator_test\.cc": [ + "+base/run_loop.h", + ], }
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 34bae4f..dc69a0c 100644 --- a/third_party/blink/renderer/core/page/context_menu_controller.cc +++ b/third_party/blink/renderer/core/page/context_menu_controller.cc
@@ -524,11 +524,14 @@ void ContextMenuController::UpdateTextFragmentSelectorGenerator( LocalFrame* selected_frame) { + if (!selected_frame->GetTextFragmentSelectorGenerator()) + return; + VisibleSelectionInFlatTree selection = selected_frame->Selection().ComputeVisibleSelectionInFlatTree(); EphemeralRangeInFlatTree selection_range(selection.Start(), selection.End()); - page_->GetTextFragmentSelectorGenerator().UpdateSelection(selected_frame, - selection_range); + selected_frame->GetTextFragmentSelectorGenerator()->UpdateSelection( + selected_frame, selection_range); } } // namespace blink
diff --git a/third_party/blink/renderer/core/page/page.cc b/third_party/blink/renderer/core/page/page.cc index 4acfdcfa..97cb430 100644 --- a/third_party/blink/renderer/core/page/page.cc +++ b/third_party/blink/renderer/core/page/page.cc
@@ -75,7 +75,6 @@ #include "third_party/blink/renderer/core/page/scoped_page_pauser.h" #include "third_party/blink/renderer/core/page/scrolling/overscroll_controller.h" #include "third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.h" -#include "third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator.h" #include "third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.h" #include "third_party/blink/renderer/core/page/spatial_navigation_controller.h" #include "third_party/blink/renderer/core/page/validation_message_client_impl.h" @@ -226,9 +225,7 @@ next_related_page_(this), prev_related_page_(this), autoplay_flags_(0), - web_text_autosizer_page_info_({0, 0, 1.f}), - text_fragment_selector_generator_( - MakeGarbageCollected<TextFragmentSelectorGenerator>()) { + web_text_autosizer_page_info_({0, 0, 1.f}) { DCHECK(!AllPages().Contains(this)); AllPages().insert(this); @@ -343,7 +340,6 @@ void Page::DocumentDetached(Document* document) { pointer_lock_controller_->DocumentDetached(document); - text_fragment_selector_generator_->DocumentDetached(document); context_menu_controller_->DocumentDetached(document); if (validation_message_client_) validation_message_client_->DocumentDetached(*document); @@ -921,7 +917,6 @@ visitor->Trace(plugins_changed_observers_); visitor->Trace(next_related_page_); visitor->Trace(prev_related_page_); - visitor->Trace(text_fragment_selector_generator_); Supplementable<Page>::Trace(visitor); }
diff --git a/third_party/blink/renderer/core/page/page.h b/third_party/blink/renderer/core/page/page.h index b6a1caa..4e4e496 100644 --- a/third_party/blink/renderer/core/page/page.h +++ b/third_party/blink/renderer/core/page/page.h
@@ -76,7 +76,6 @@ class PluginData; class PluginsChangedObserver; class PointerLockController; -class TextFragmentSelectorGenerator; class ScopedPagePauser; class ScrollingCoordinator; class ScrollbarTheme; @@ -377,10 +376,6 @@ static void PrepareForLeakDetection(); - TextFragmentSelectorGenerator& GetTextFragmentSelectorGenerator() const { - return *text_fragment_selector_generator_; - } - private: friend class ScopedPagePauser; @@ -502,8 +497,6 @@ WebScopedVirtualTimePauser history_navigation_virtual_time_pauser_; - const Member<TextFragmentSelectorGenerator> text_fragment_selector_generator_; - DISALLOW_COPY_AND_ASSIGN(Page); };
diff --git a/third_party/blink/renderer/core/page/scrolling/text_fragment_selector.cc b/third_party/blink/renderer/core/page/scrolling/text_fragment_selector.cc index 42c93d9..787fb1b 100644 --- a/third_party/blink/renderer/core/page/scrolling/text_fragment_selector.cc +++ b/third_party/blink/renderer/core/page/scrolling/text_fragment_selector.cc
@@ -4,6 +4,7 @@ #include "third_party/blink/renderer/core/page/scrolling/text_fragment_selector.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h" +#include "third_party/blink/renderer/platform/wtf/text/string_builder.h" namespace blink { @@ -81,4 +82,28 @@ TextFragmentSelector::TextFragmentSelector(SelectorType type) : type_(type) {} +String TextFragmentSelector::ToString() const { + StringBuilder selector; + if (!prefix_.IsEmpty()) { + selector.Append(EncodeWithURLEscapeSequences(prefix_)); + selector.Append("-,"); + } + + if (!start_.IsEmpty()) { + selector.Append(EncodeWithURLEscapeSequences(start_)); + } + + if (!end_.IsEmpty()) { + selector.Append(","); + selector.Append(EncodeWithURLEscapeSequences(end_)); + } + + if (!suffix_.IsEmpty()) { + selector.Append(",-"); + selector.Append(EncodeWithURLEscapeSequences(suffix_)); + } + + return selector.ToString(); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/page/scrolling/text_fragment_selector.h b/third_party/blink/renderer/core/page/scrolling/text_fragment_selector.h index 06013500..3161748 100644 --- a/third_party/blink/renderer/core/page/scrolling/text_fragment_selector.h +++ b/third_party/blink/renderer/core/page/scrolling/text_fragment_selector.h
@@ -34,10 +34,11 @@ ~TextFragmentSelector() = default; SelectorType Type() const { return type_; } - String Start() const { return start_; } - String End() const { return end_; } - String Prefix() const { return prefix_; } - String Suffix() const { return suffix_; } + const String& Start() const { return start_; } + const String& End() const { return end_; } + const String& Prefix() const { return prefix_; } + const String& Suffix() const { return suffix_; } + String ToString() const; private: const SelectorType type_;
diff --git a/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator.cc b/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator.cc index 5164e55..bcecdb3 100644 --- a/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator.cc +++ b/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator.cc
@@ -4,6 +4,8 @@ #include "third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator.h" +#include "third_party/blink/public/common/browser_interface_broker_proxy.h" +#include "third_party/blink/public/platform/interface_registry.h" #include "third_party/blink/renderer/core/editing/ephemeral_range.h" #include "third_party/blink/renderer/core/editing/finder/find_buffer.h" #include "third_party/blink/renderer/core/editing/iterators/text_iterator.h" @@ -18,6 +20,11 @@ void TextFragmentSelectorGenerator::UpdateSelection( LocalFrame* selection_frame, const EphemeralRangeInFlatTree& selection_range) { + DCHECK(selection_frame); + + // Scroll-to-text doesn't support iframes. + DCHECK(selection_frame->IsMainFrame()); + selection_frame_ = selection_frame; selection_range_ = MakeGarbageCollected<Range>( selection_range.GetDocument(), @@ -25,7 +32,21 @@ ToPositionInDOMTree(selection_range.EndPosition())); } -void TextFragmentSelectorGenerator::GenerateSelector() { +void TextFragmentSelectorGenerator::BindTextFragmentSelectorProducer( + mojo::PendingReceiver<mojom::blink::TextFragmentSelectorProducer> + producer) { + selector_producer_.reset(); + selector_producer_.Bind( + std::move(producer), + selection_frame_->GetTaskRunner(blink::TaskType::kInternalDefault)); +} + +void TextFragmentSelectorGenerator::GenerateSelector( + GenerateSelectorCallback callback) { + DCHECK(selection_range_); + DCHECK(callback); + + pending_generate_selector_callback_ = std::move(callback); EphemeralRangeInFlatTree ephemeral_range(selection_range_); const TextFragmentSelector kInvalidSelector( @@ -38,8 +59,10 @@ FindBuffer::GetFirstBlockLevelAncestorInclusive( *ephemeral_range.EndPosition().AnchorNode()); - if (!start_first_block_ancestor.isSameNode(&end_first_block_ancestor)) + if (!start_first_block_ancestor.isSameNode(&end_first_block_ancestor)) { NotifySelectorReady(kInvalidSelector); + return; + } // TODO(gayane): If same node, need to check if start and end are interrupted // by a block. Example: <div>start of the selection <div> sub block </div>end @@ -50,8 +73,10 @@ String selected_text = PlainText(ephemeral_range); if (selected_text.length() < kNoContextMinChars || - selected_text.length() > kExactTextMaxChars) + selected_text.length() > kExactTextMaxChars) { NotifySelectorReady(kInvalidSelector); + return; + } selector_ = std::make_unique<TextFragmentSelector>( TextFragmentSelector::SelectorType::kExact, selected_text, "", "", ""); @@ -72,19 +97,14 @@ } } -void TextFragmentSelectorGenerator::SetCallbackForTesting( - base::OnceCallback<void(const TextFragmentSelector&)> callback) { - callback_for_tests_ = std::move(callback); -} - void TextFragmentSelectorGenerator::NotifySelectorReady( const TextFragmentSelector& selector) { - if (!callback_for_tests_.is_null()) - std::move(callback_for_tests_).Run(selector); + DCHECK(pending_generate_selector_callback_); + std::move(pending_generate_selector_callback_).Run(selector.ToString()); } -void TextFragmentSelectorGenerator::DocumentDetached(Document* document) { - if (selection_range_ && selection_range_->OwnerDocument() == *document) { +void TextFragmentSelectorGenerator::ClearSelection() { + if (selection_range_) { selection_range_->Dispose(); selection_range_ = nullptr; selection_frame_ = nullptr; @@ -94,6 +114,7 @@ void TextFragmentSelectorGenerator::Trace(Visitor* visitor) const { visitor->Trace(selection_frame_); visitor->Trace(selection_range_); + visitor->Trace(selector_producer_); } } // namespace blink
diff --git a/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator.h b/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator.h index 18220769..a0de513 100644 --- a/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator.h +++ b/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator.h
@@ -5,9 +5,11 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_SCROLLING_TEXT_FRAGMENT_SELECTOR_GENERATOR_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_SCROLLING_TEXT_FRAGMENT_SELECTOR_GENERATOR_H_ +#include "third_party/blink/public/mojom/link_to_text/link_to_text.mojom-blink.h" #include "third_party/blink/renderer/core/editing/forward.h" #include "third_party/blink/renderer/core/page/scrolling/text_fragment_finder.h" #include "third_party/blink/renderer/core/page/scrolling/text_fragment_selector.h" +#include "third_party/blink/renderer/platform/mojo/heap_mojo_receiver.h" namespace blink { @@ -21,30 +23,33 @@ // triggered when users request "link to text" for the selected text. class CORE_EXPORT TextFragmentSelectorGenerator final : public GarbageCollected<TextFragmentSelectorGenerator>, - public TextFragmentFinder::Client { + public TextFragmentFinder::Client, + public blink::mojom::blink::TextFragmentSelectorProducer { public: explicit TextFragmentSelectorGenerator() = default; + void BindTextFragmentSelectorProducer( + mojo::PendingReceiver<mojom::blink::TextFragmentSelectorProducer> + producer); + // Sets the frame and range of the current selection. void UpdateSelection(LocalFrame* selection_frame, const EphemeralRangeInFlatTree& selection_range); + // blink::mojom::blink::TextFragmentSelectorProducer interface // Generates selector for current selection. - void GenerateSelector(); + void GenerateSelector(GenerateSelectorCallback callback) override; // TextFragmentFinder::Client interface void DidFindMatch(const EphemeralRangeInFlatTree& match, const TextFragmentAnchorMetrics::Match match_metrics, bool is_unique) override; - // Sets the callback used for notifying test results of |GenerateSelector|. - void SetCallbackForTesting( - base::OnceCallback<void(const TextFragmentSelector&)> callback); - // Notifies the results of |GenerateSelector|. void NotifySelectorReady(const TextFragmentSelector& selector); - void DocumentDetached(Document* document); + // Releases members if necessary. + void ClearSelection(); void Trace(Visitor*) const; @@ -53,7 +58,12 @@ Member<Range> selection_range_; std::unique_ptr<TextFragmentSelector> selector_; - base::OnceCallback<void(const TextFragmentSelector&)> callback_for_tests_; + // Used for communication between |TextFragmentSelectorGenerator| in renderer + // and |TextFragmentSelectorClientImpl| in browser. + HeapMojoReceiver<blink::mojom::blink::TextFragmentSelectorProducer, + TextFragmentSelectorGenerator> + selector_producer_{this, nullptr}; + GenerateSelectorCallback pending_generate_selector_callback_; DISALLOW_COPY_AND_ASSIGN(TextFragmentSelectorGenerator); };
diff --git a/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator_test.cc b/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator_test.cc index ddb466f7..4a3e33c 100644 --- a/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator_test.cc +++ b/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator_test.cc
@@ -6,8 +6,14 @@ #include <gtest/gtest.h> +#include "base/run_loop.h" #include "base/test/bind_test_util.h" +#include "mojo/public/cpp/bindings/receiver_set.h" +#include "third_party/blink/public/common/browser_interface_broker_proxy.h" +#include "third_party/blink/public/mojom/link_to_text/link_to_text.mojom-blink.h" #include "third_party/blink/renderer/core/editing/ephemeral_range.h" +#include "third_party/blink/renderer/core/frame/local_frame.h" +#include "third_party/blink/renderer/core/html/html_iframe_element.h" #include "third_party/blink/renderer/core/testing/sim/sim_request.h" #include "third_party/blink/renderer/core/testing/sim/sim_test.h" @@ -19,6 +25,33 @@ SimTest::SetUp(); WebView().MainFrameWidget()->Resize(WebSize(800, 600)); } + + void GenerateAndVerifySelector(Position selected_start, + Position selected_end, + String expected_selector) { + GetDocument() + .GetFrame() + ->GetTextFragmentSelectorGenerator() + ->UpdateSelection(GetDocument().GetFrame(), + ToEphemeralRangeInFlatTree( + EphemeralRange(selected_start, selected_end))); + + bool callback_called = false; + auto lambda = [](bool& callback_called, const String& expected_selector, + const String& selector) { + EXPECT_EQ(selector, expected_selector); + callback_called = true; + }; + auto callback = + WTF::Bind(lambda, std::ref(callback_called), expected_selector); + GetDocument() + .GetFrame() + ->GetTextFragmentSelectorGenerator() + ->GenerateSelector(std::move(callback)); + base::RunLoop().RunUntilIdle(); + + EXPECT_TRUE(callback_called); + } }; TEST_F(TextFragmentSelectorGeneratorTest, ExactTextSelector) { @@ -33,22 +66,9 @@ Node* first_paragraph = GetDocument().getElementById("first")->firstChild(); const auto& selected_start = Position(first_paragraph, 0); const auto& selected_end = Position(first_paragraph, 28); - bool callback_called = false; - base::OnceCallback<void(const TextFragmentSelector&)> callback = - base::BindLambdaForTesting([&](const TextFragmentSelector& selector) { - EXPECT_EQ(selector.Type(), TextFragmentSelector::SelectorType::kExact); - EXPECT_EQ(selector.Start(), "First paragraph text that is"); - callback_called = true; - }); - TextFragmentSelectorGenerator generator; - generator.UpdateSelection( - GetDocument().GetFrame(), - ToEphemeralRangeInFlatTree(EphemeralRange(selected_start, selected_end))); - generator.SetCallbackForTesting(std::move(callback)); - generator.GenerateSelector(); - - EXPECT_TRUE(callback_called); + GenerateAndVerifySelector(selected_start, selected_end, + "First%20paragraph%20text%20that%20is"); } TEST_F(TextFragmentSelectorGeneratorTest, ExactTextWithNestedTextNodes) { @@ -64,22 +84,9 @@ const auto& selected_start = Position(first_paragraph->firstChild(), 0); const auto& selected_end = Position(first_paragraph->firstChild()->nextSibling()->firstChild(), 6); - bool callback_called = false; - base::OnceCallback<void(const TextFragmentSelector&)> callback = - base::BindLambdaForTesting([&](const TextFragmentSelector& selector) { - EXPECT_EQ(selector.Type(), TextFragmentSelector::SelectorType::kExact); - EXPECT_EQ(selector.Start(), "First paragraph text that is longer"); - callback_called = true; - }); - TextFragmentSelectorGenerator generator; - generator.UpdateSelection( - GetDocument().GetFrame(), - ToEphemeralRangeInFlatTree(EphemeralRange(selected_start, selected_end))); - generator.SetCallbackForTesting(std::move(callback)); - generator.GenerateSelector(); - - EXPECT_TRUE(callback_called); + GenerateAndVerifySelector(selected_start, selected_end, + "First%20paragraph%20text%20that%20is%20longer"); } TEST_F(TextFragmentSelectorGeneratorTest, ExactTextWithExtraSpace) { @@ -94,22 +101,9 @@ Node* second_paragraph = GetDocument().getElementById("second")->firstChild(); const auto& selected_start = Position(second_paragraph, 0); const auto& selected_end = Position(second_paragraph, 23); - bool callback_called = false; - base::OnceCallback<void(const TextFragmentSelector&)> callback = - base::BindLambdaForTesting([&](const TextFragmentSelector& selector) { - EXPECT_EQ(selector.Type(), TextFragmentSelector::SelectorType::kExact); - EXPECT_EQ(selector.Start(), "Second paragraph text"); - callback_called = true; - }); - TextFragmentSelectorGenerator generator; - generator.UpdateSelection( - GetDocument().GetFrame(), - ToEphemeralRangeInFlatTree(EphemeralRange(selected_start, selected_end))); - generator.SetCallbackForTesting(std::move(callback)); - generator.GenerateSelector(); - - EXPECT_TRUE(callback_called); + GenerateAndVerifySelector(selected_start, selected_end, + "Second%20paragraph%20text"); } // Multi-block selection is currently not implemented. @@ -126,22 +120,8 @@ Node* second_paragraph = GetDocument().getElementById("second")->firstChild(); const auto& selected_start = Position(first_paragraph, 0); const auto& selected_end = Position(second_paragraph, 6); - bool callback_called = false; - base::OnceCallback<void(const TextFragmentSelector&)> callback = - base::BindLambdaForTesting([&](const TextFragmentSelector& selector) { - EXPECT_EQ(selector.Type(), - TextFragmentSelector::SelectorType::kInvalid); - callback_called = true; - }); - TextFragmentSelectorGenerator generator; - generator.UpdateSelection( - GetDocument().GetFrame(), - ToEphemeralRangeInFlatTree(EphemeralRange(selected_start, selected_end))); - generator.SetCallbackForTesting(std::move(callback)); - generator.GenerateSelector(); - - EXPECT_TRUE(callback_called); + GenerateAndVerifySelector(selected_start, selected_end, ""); } } // namespace blink
diff --git a/third_party/blink/renderer/modules/cache_storage/cache_test.cc b/third_party/blink/renderer/modules/cache_storage/cache_test.cc index ad61fb6..b00892bf 100644 --- a/third_party/blink/renderer/modules/cache_storage/cache_test.cc +++ b/third_party/blink/renderer/modules/cache_storage/cache_test.cc
@@ -267,8 +267,7 @@ cache_ = std::move(cache); receiver_ = std::make_unique< mojo::AssociatedReceiver<mojom::blink::CacheStorageCache>>( - cache_.get(), - cache_remote.BindNewEndpointAndPassDedicatedReceiverForTesting()); + cache_.get(), cache_remote.BindNewEndpointAndPassDedicatedReceiver()); return MakeGarbageCollected<Cache>( fetcher, cache_remote.Unbind(), blink::scheduler::GetSingleThreadTaskRunnerForTesting());
diff --git a/third_party/blink/renderer/modules/canvas/BUILD.gn b/third_party/blink/renderer/modules/canvas/BUILD.gn index dcbce9e..098a4e35 100644 --- a/third_party/blink/renderer/modules/canvas/BUILD.gn +++ b/third_party/blink/renderer/modules/canvas/BUILD.gn
@@ -48,6 +48,9 @@ seed_corpuses = [ "//third_party/blink/web_tests/fast/canvas" ] deps = [ "../../platform:blink_fuzzer_test_support", + "//base/test:test_support", "//third_party/blink/renderer/core", + "//third_party/blink/renderer/core:testing", + "//third_party/blink/renderer/platform:test_support", ] }
diff --git a/third_party/blink/renderer/modules/delegated_ink/delegated_ink_trail_presenter.cc b/third_party/blink/renderer/modules/delegated_ink/delegated_ink_trail_presenter.cc index 72eb5b7..c8431ee4 100644 --- a/third_party/blink/renderer/modules/delegated_ink/delegated_ink_trail_presenter.cc +++ b/third_party/blink/renderer/modules/delegated_ink/delegated_ink_trail_presenter.cc
@@ -10,7 +10,9 @@ #include "third_party/blink/renderer/core/dom/element.h" #include "third_party/blink/renderer/core/events/pointer_event.h" #include "third_party/blink/renderer/core/frame/local_frame.h" +#include "third_party/blink/renderer/core/frame/visual_viewport.h" #include "third_party/blink/renderer/core/geometry/dom_rect.h" +#include "third_party/blink/renderer/core/layout/layout_embedded_content.h" #include "third_party/blink/renderer/core/layout/layout_view.h" #include "third_party/blink/renderer/core/page/chrome_client.h" #include "third_party/blink/renderer/core/page/page.h" @@ -97,14 +99,39 @@ layout_box = layout_view; } - // TODO(1052145): Move this further into the document lifecycle when layout - // is up to date. - PhysicalRect physical_rect_area = layout_box->LocalToAbsoluteRect( + // Intersect with the visible viewport so that the presentation area can't + // extend beyond the edges of the window or over the scrollbars. The frame + // visual viewport loop accounts for all iframe viewports, and the page visual + // viewport accounts for the full window. Convert everything to root frame + // coordinates in order to make sure offsets aren't lost along the way. + // + // TODO(1052145): Overflow and clip-path clips are ignored here, which results + // in delegated ink trails ignoring the clips and appearing incorrectly in + // some situations. This could also occur due to transformations, as the + // |presenation_area| is currently always a rectilinear bounding box. Ideally + // both of these situations are handled correctly, or the trail doesn't appear + // if we are unable to accurately render it. + PhysicalRect border_box_rect_absolute = layout_box->LocalToAbsoluteRect( layout_box->PhysicalBorderBoxRect(), kTraverseDocumentBoundaries); - gfx::RectF area(physical_rect_area.X().ToFloat(), - physical_rect_area.Y().ToFloat(), - physical_rect_area.Width().ToFloat(), - physical_rect_area.Height().ToFloat()); + + while (layout_view->GetFrame()->OwnerLayoutObject()) { + PhysicalRect frame_visual_viewport_absolute = + layout_view->LocalToAbsoluteRect( + PhysicalRect( + layout_view->GetScrollableArea()->VisibleContentRect()), + kTraverseDocumentBoundaries); + border_box_rect_absolute.Intersect(frame_visual_viewport_absolute); + + layout_view = layout_view->GetFrame()->OwnerLayoutObject()->View(); + } + + border_box_rect_absolute.Intersect(PhysicalRect( + local_frame_->GetPage()->GetVisualViewport().VisibleContentRect())); + + gfx::RectF area(border_box_rect_absolute.X().ToFloat(), + border_box_rect_absolute.Y().ToFloat(), + border_box_rect_absolute.Width().ToFloat(), + border_box_rect_absolute.Height().ToFloat()); const double diameter_in_physical_pixels = style->diameter() * effective_zoom; std::unique_ptr<viz::DelegatedInkMetadata> metadata =
diff --git a/third_party/blink/renderer/modules/delegated_ink/delegated_ink_trail_presenter_unittest.cc b/third_party/blink/renderer/modules/delegated_ink/delegated_ink_trail_presenter_unittest.cc index 23169f624..4b974e7 100644 --- a/third_party/blink/renderer/modules/delegated_ink/delegated_ink_trail_presenter_unittest.cc +++ b/third_party/blink/renderer/modules/delegated_ink/delegated_ink_trail_presenter_unittest.cc
@@ -30,6 +30,7 @@ : area_(area) { area_.Scale(device_pixel_ratio); } + TestDelegatedInkMetadata() = default; void ExpectEqual(TestDelegatedInkMetadata actual) const { // LayoutUnits cast floats to ints, causing the actual point and area to be @@ -64,7 +65,19 @@ } // namespace class DelegatedInkTrailPresenterUnitTest : public SimTest { - protected: + public: + void SetWebViewSize(float width, float height) { + WebView().MainFrameWidget()->Resize(WebSize(width, height)); + } + + void SetWebViewSizeGreaterThanCanvas(float width, float height) { + // The presentation area is intersected with the visible content rect, so + // make sure that the page size is larger than the canvas to ensure it + // isn't clipped. Adding 1 to the height and width is enough to ensure that + // doesn't happen. + SetWebViewSize(width + 1, height + 1); + } + PointerEvent* CreatePointerMoveEvent(gfx::PointF pt) { PointerEventInit* init = PointerEventInit::Create(); init->setClientX(pt.x()); @@ -84,9 +97,29 @@ } }; +// Test scenarios with the presentation area extending beyond the edges of the +// window to confirm it gets clipped correctly. +class DelegatedInkTrailPresenterCanvasBeyondViewport + : public DelegatedInkTrailPresenterUnitTest, + public testing::WithParamInterface<bool> { + public: + bool CanvasShouldBePastViewport() { return GetParam(); } + float GetViewportWidth() const { return kViewportWidth; } + float GetViewportHeight() const { return kViewportHeight; } + void SetWebViewSize() { + DelegatedInkTrailPresenterUnitTest::SetWebViewSize(kViewportWidth, + kViewportHeight); + } + + private: + const float kViewportWidth = 175.f; + const float kViewportHeight = 180.f; +}; + // Confirm that all the information is collected and transformed correctly, if // necessary. Numbers and color used were chosen arbitrarily. -TEST_F(DelegatedInkTrailPresenterUnitTest, CollectAndPropagateMetadata) { +TEST_P(DelegatedInkTrailPresenterCanvasBeyondViewport, + CollectAndPropagateMetadata) { SimRequest main_resource("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); main_resource.Complete(R"HTML( @@ -108,8 +141,16 @@ const float kCanvasWidth = 191.f; const float kCanvasHeight = 234.f; - TestDelegatedInkMetadata expected_metadata( - gfx::RectF(0, 0, kCanvasWidth, kCanvasHeight)); + TestDelegatedInkMetadata expected_metadata; + + if (!CanvasShouldBePastViewport()) { + SetWebViewSizeGreaterThanCanvas(kCanvasWidth, kCanvasHeight); + expected_metadata.SetArea(gfx::RectF(0, 0, kCanvasWidth, kCanvasHeight)); + } else { + SetWebViewSize(); + expected_metadata.SetArea( + gfx::RectF(0, 0, GetViewportWidth(), GetViewportHeight())); + } DelegatedInkTrailPresenter* presenter = CreatePresenter( GetDocument().getElementById("canvas"), GetDocument().GetFrame()); @@ -130,38 +171,10 @@ expected_metadata.ExpectEqual(GetActualMetadata()); } -// Confirm that presentation area defaults to the size of the viewport. -// Numbers and color used were chosen arbitrarily. -TEST_F(DelegatedInkTrailPresenterUnitTest, PresentationAreaNotProvided) { - const int kViewportHeight = 555; - const int kViewportWidth = 333; - WebView().MainFrameWidget()->Resize(WebSize(kViewportWidth, kViewportHeight)); - - DelegatedInkTrailPresenter* presenter = - CreatePresenter(nullptr, GetDocument().GetFrame()); - DCHECK(presenter); - - TestDelegatedInkMetadata expected_metadata( - gfx::RectF(0, 0, kViewportWidth, kViewportHeight)); - - InkTrailStyle style; - style.setDiameter(3.6); - style.setColor("yellow"); - expected_metadata.SetDiameter(style.diameter()); - expected_metadata.SetColor(SK_ColorYELLOW); - - gfx::PointF pt(70, 109); - presenter->updateInkTrailStartPoint( - ToScriptStateForMainWorld(GetDocument().GetFrame()), - CreatePointerMoveEvent(pt), &style); - expected_metadata.SetPoint(pt); - - expected_metadata.ExpectEqual(GetActualMetadata()); -} - // Confirm that everything is still calculated correctly when the // DevicePixelRatio is not 1. Numbers and color used were chosen arbitrarily. -TEST_F(DelegatedInkTrailPresenterUnitTest, NotDefaultDevicePixelRatio) { +TEST_P(DelegatedInkTrailPresenterCanvasBeyondViewport, + NotDefaultDevicePixelRatio) { const float kZoom = 1.7; SetPageZoomFactor(kZoom); @@ -186,8 +199,18 @@ const float kCanvasWidth = 281.f; const float kCanvasHeight = 190.f; - TestDelegatedInkMetadata expected_metadata( - gfx::RectF(0, 0, kCanvasWidth, kCanvasHeight), kZoom); + TestDelegatedInkMetadata expected_metadata; + + if (!CanvasShouldBePastViewport()) { + SetWebViewSizeGreaterThanCanvas(kCanvasWidth * kZoom, + kCanvasHeight * kZoom); + expected_metadata = TestDelegatedInkMetadata( + gfx::RectF(0, 0, kCanvasWidth, kCanvasHeight), kZoom); + } else { + SetWebViewSize(); + expected_metadata.SetArea( + gfx::RectF(0, 0, GetViewportWidth(), GetViewportHeight())); + } DelegatedInkTrailPresenter* presenter = CreatePresenter( GetDocument().getElementById("canvas"), GetDocument().GetFrame()); @@ -211,7 +234,7 @@ // Confirm that the offset is correct. Numbers and color used were chosen // arbitrarily. -TEST_F(DelegatedInkTrailPresenterUnitTest, CanvasNotAtOrigin) { +TEST_P(DelegatedInkTrailPresenterCanvasBeyondViewport, CanvasNotAtOrigin) { SimRequest main_resource("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); main_resource.Complete(R"HTML( @@ -224,8 +247,8 @@ width: 250px; height: 350px; position: fixed; - top: 375px; - left: 166px; + top: 59px; + left: 16px; } </style> <canvas id='canvas'></canvas> @@ -235,11 +258,23 @@ const float kCanvasWidth = 250.f; const float kCanvasHeight = 350.f; - const float kCanvasTopOffset = 375.f; - const float kCanvasLeftOffset = 166.f; + const float kCanvasTopOffset = 59.f; + const float kCanvasLeftOffset = 16.f; - TestDelegatedInkMetadata expected_metadata(gfx::RectF( - kCanvasLeftOffset, kCanvasTopOffset, kCanvasWidth, kCanvasHeight)); + TestDelegatedInkMetadata expected_metadata; + + if (!CanvasShouldBePastViewport()) { + SetWebViewSizeGreaterThanCanvas(kCanvasWidth + kCanvasLeftOffset, + kCanvasHeight + kCanvasTopOffset); + expected_metadata.SetArea(gfx::RectF(kCanvasLeftOffset, kCanvasTopOffset, + kCanvasWidth, kCanvasHeight)); + } else { + SetWebViewSize(); + expected_metadata.SetArea( + gfx::RectF(kCanvasLeftOffset, kCanvasTopOffset, + GetViewportWidth() - kCanvasLeftOffset, + GetViewportHeight() - kCanvasTopOffset)); + } DelegatedInkTrailPresenter* presenter = CreatePresenter( GetDocument().getElementById("canvas"), GetDocument().GetFrame()); @@ -262,7 +297,7 @@ // Confirm that values, specifically offsets, are transformed correctly when // the canvas is in an iframe. Numbers and color used were chosen arbitrarily. -TEST_F(DelegatedInkTrailPresenterUnitTest, CanvasInIFrame) { +TEST_P(DelegatedInkTrailPresenterCanvasBeyondViewport, CanvasInIFrame) { SimRequest main_resource("https://example.com/test.html", "text/html"); SimRequest frame_resource("https://example.com/iframe.html", "text/html"); LoadURL("https://example.com/test.html"); @@ -272,7 +307,7 @@ body { margin: 0; } - iframe { + #iframe { width: 500px; height: 500px; position: fixed; @@ -309,20 +344,35 @@ const float kIframeBorder = 2.f; const float kIframeLeftOffset = 57.f + kIframeBorder; const float kIframeTopOffset = 26.f + kIframeBorder; + const float kIframeHeight = 500.f; + const float kIframeWidth = 500.f; const float kCanvasLeftOffset = 16.f; const float kCanvasTopOffset = 33.f; const float kCanvasHeight = 250.f; const float kCanvasWidth = 250.f; + TestDelegatedInkMetadata expected_metadata; + + if (!CanvasShouldBePastViewport()) { + SetWebViewSizeGreaterThanCanvas(kIframeWidth + kIframeLeftOffset, + kIframeHeight + kIframeTopOffset); + expected_metadata.SetArea(gfx::RectF(kIframeLeftOffset + kCanvasLeftOffset, + kIframeTopOffset + kCanvasTopOffset, + kCanvasWidth, kCanvasHeight)); + } else { + SetWebViewSize(); + expected_metadata.SetArea(gfx::RectF( + kIframeLeftOffset + kCanvasLeftOffset, + kIframeTopOffset + kCanvasTopOffset, + GetViewportWidth() - (kIframeLeftOffset + kCanvasLeftOffset), + GetViewportHeight() - (kIframeTopOffset + kCanvasTopOffset))); + } + auto* iframe_element = To<HTMLIFrameElement>(GetDocument().getElementById("iframe")); auto* iframe_localframe = To<LocalFrame>(iframe_element->ContentFrame()); Document* iframe_document = iframe_element->contentDocument(); - TestDelegatedInkMetadata expected_metadata(gfx::RectF( - kIframeLeftOffset + kCanvasLeftOffset, - kIframeTopOffset + kCanvasTopOffset, kCanvasWidth, kCanvasHeight)); - DelegatedInkTrailPresenter* presenter = CreatePresenter( iframe_localframe->GetDocument()->getElementById("canvas"), iframe_document->GetFrame()); @@ -344,9 +394,136 @@ expected_metadata.ExpectEqual(GetActualMetadata()); } +// Confirm that values, specifically offsets, are transformed correctly when +// the canvas is in a nested iframe. Numbers and color used were chosen +// arbitrarily. +TEST_P(DelegatedInkTrailPresenterCanvasBeyondViewport, NestedIframe) { + SimRequest main_resource("https://example.com/test.html", "text/html"); + SimRequest frame_resource("https://example.com/iframe.html", "text/html"); + SimRequest frame2_resource("https://example.com/iframe2.html", "text/html"); + LoadURL("https://example.com/test.html"); + main_resource.Complete(R"HTML( + <!DOCTYPE html> + <style> + body { + margin: 0; + } + #OuterIframe { + width: 500px; + height: 500px; + position: fixed; + top: 26px; + left: 57px; + } + </style> + <iframe id='OuterIframe' src='https://example.com/iframe.html'> + </iframe> + )HTML"); + + frame_resource.Complete(R"HTML( + <!DOCTYPE html> + <style> + body { + margin: 0; + } + #InnerIframe { + width: 400px; + height: 400px; + position: fixed; + top: 11px; + left: 18px; + } + </style> + <iframe id='InnerIframe' src='https://example.com/iframe2.html'> + </iframe> + )HTML"); + + frame2_resource.Complete(R"HTML( + <!DOCTYPE html> + <style> + body { + margin: 0; + } + canvas { + width: 250px; + height: 250px; + position: fixed; + top: 28px; + left: 6px; + } + </style> + <canvas id='canvas'></canvas> + )HTML"); + + Compositor().BeginFrame(); + + // When creating the expected metadata, we have to take into account the + // offsets that are applied to the iframe that the canvas is in, and the 2px + // border around the iframe. + const float kIframeBorder = 2.f; + const float kOuterIframeLeftOffset = 57.f + kIframeBorder; + const float kOuterIframeTopOffset = 26.f + kIframeBorder; + const float kOuterIframeHeight = 500.f; + const float kOuterIframeWidth = 500.f; + const float kInnerIframeLeftOffset = + kOuterIframeLeftOffset + 18.f + kIframeBorder; + const float kInnerIframeTopOffset = + kOuterIframeTopOffset + 11.f + kIframeBorder; + const float kCanvasLeftOffset = 6.f; + const float kCanvasTopOffset = 28.f; + const float kCanvasHeight = 250.f; + const float kCanvasWidth = 250.f; + + TestDelegatedInkMetadata expected_metadata; + + if (!CanvasShouldBePastViewport()) { + SetWebViewSizeGreaterThanCanvas(kOuterIframeWidth + kOuterIframeLeftOffset, + kOuterIframeHeight + kOuterIframeTopOffset); + expected_metadata.SetArea(gfx::RectF( + kInnerIframeLeftOffset + kCanvasLeftOffset, + kInnerIframeTopOffset + kCanvasTopOffset, kCanvasWidth, kCanvasHeight)); + } else { + SetWebViewSize(); + expected_metadata.SetArea(gfx::RectF( + kInnerIframeLeftOffset + kCanvasLeftOffset, + kInnerIframeTopOffset + kCanvasTopOffset, + GetViewportWidth() - (kInnerIframeLeftOffset + kCanvasLeftOffset), + GetViewportHeight() - (kInnerIframeTopOffset + kCanvasTopOffset))); + } + + auto* outer_iframe_element = + To<HTMLIFrameElement>(GetDocument().getElementById("OuterIframe")); + auto* inner_iframe_element = To<HTMLIFrameElement>( + outer_iframe_element->contentDocument()->getElementById("InnerIframe")); + auto* iframe_localframe = + To<LocalFrame>(inner_iframe_element->ContentFrame()); + Document* iframe_document = inner_iframe_element->contentDocument(); + + DelegatedInkTrailPresenter* presenter = CreatePresenter( + iframe_localframe->GetDocument()->getElementById("canvas"), + iframe_document->GetFrame()); + DCHECK(presenter); + + InkTrailStyle style; + style.setDiameter(100000.3); + style.setColor("yellow"); + expected_metadata.SetDiameter(style.diameter()); + expected_metadata.SetColor(SK_ColorYELLOW); + + gfx::PointF pt(350, 375); + presenter->updateInkTrailStartPoint( + ToScriptStateForMainWorld(iframe_document->GetFrame()), + CreatePointerMoveEvent(pt), &style); + expected_metadata.SetPoint(gfx::PointF(pt.x() + kInnerIframeLeftOffset, + pt.y() + kInnerIframeTopOffset)); + + expected_metadata.ExpectEqual(GetActualMetadata()); +} + // Confirm that values are correct when an iframe is used and presentation area // isn't provided. Numbers and color used were chosen arbitrarily. -TEST_F(DelegatedInkTrailPresenterUnitTest, IFrameNoPresentationArea) { +TEST_P(DelegatedInkTrailPresenterCanvasBeyondViewport, + IFrameNoPresentationArea) { SimRequest main_resource("https://example.com/test.html", "text/html"); SimRequest frame_resource("https://example.com/iframe.html", "text/html"); LoadURL("https://example.com/test.html"); @@ -356,7 +533,7 @@ body { margin: 0; } - iframe { + #iframe { width: 500px; height: 500px; position: fixed; @@ -387,13 +564,25 @@ const float kIframeHeight = 500.f; const float kIframeWidth = 500.f; + TestDelegatedInkMetadata expected_metadata; + + if (!CanvasShouldBePastViewport()) { + SetWebViewSizeGreaterThanCanvas(kIframeWidth + kIframeLeftOffset, + kIframeHeight + kIframeTopOffset); + expected_metadata.SetArea(gfx::RectF(kIframeLeftOffset, kIframeTopOffset, + kIframeWidth, kIframeHeight)); + } else { + SetWebViewSize(); + expected_metadata.SetArea( + gfx::RectF(kIframeLeftOffset, kIframeTopOffset, + GetViewportWidth() - kIframeLeftOffset, + GetViewportHeight() - kIframeTopOffset)); + } + Document* iframe_document = To<HTMLIFrameElement>(GetDocument().getElementById("iframe")) ->contentDocument(); - TestDelegatedInkMetadata expected_metadata(gfx::RectF( - kIframeLeftOffset, kIframeTopOffset, kIframeWidth, kIframeHeight)); - DelegatedInkTrailPresenter* presenter = CreatePresenter(nullptr, iframe_document->GetFrame()); DCHECK(presenter); @@ -414,4 +603,333 @@ expected_metadata.ExpectEqual(GetActualMetadata()); } +INSTANTIATE_TEST_SUITE_P(, + DelegatedInkTrailPresenterCanvasBeyondViewport, + testing::Bool()); + +// Confirm that presentation area defaults to the size of the viewport. +// Numbers and color used were chosen arbitrarily. +TEST_F(DelegatedInkTrailPresenterUnitTest, PresentationAreaNotProvided) { + const int kViewportHeight = 555; + const int kViewportWidth = 333; + SetWebViewSize(kViewportWidth, kViewportHeight); + + DelegatedInkTrailPresenter* presenter = + CreatePresenter(nullptr, GetDocument().GetFrame()); + DCHECK(presenter); + + TestDelegatedInkMetadata expected_metadata( + gfx::RectF(0, 0, kViewportWidth, kViewportHeight)); + + InkTrailStyle style; + style.setDiameter(3.6); + style.setColor("yellow"); + expected_metadata.SetDiameter(style.diameter()); + expected_metadata.SetColor(SK_ColorYELLOW); + + gfx::PointF pt(70, 109); + presenter->updateInkTrailStartPoint( + ToScriptStateForMainWorld(GetDocument().GetFrame()), + CreatePointerMoveEvent(pt), &style); + expected_metadata.SetPoint(pt); + + expected_metadata.ExpectEqual(GetActualMetadata()); +} + +// Test that the presentation area is clipped correctly by the dimensions of +// the iframe, even when the iframe and canvas each fit entirely within the +// visual viewport. +TEST_F(DelegatedInkTrailPresenterUnitTest, CanvasExtendsOutsideOfIframe) { + SimRequest main_resource("https://example.com/test.html", "text/html"); + SimRequest frame_resource("https://example.com/iframe.html", "text/html"); + LoadURL("https://example.com/test.html"); + main_resource.Complete(R"HTML( + <!DOCTYPE html> + <style> + body { + margin: 0; + } + #iframe { + width: 150px; + height: 150px; + position: fixed; + top: 13px; + left: 19px; + } + </style> + <iframe id='iframe' src='https://example.com/iframe.html'> + </iframe> + )HTML"); + + frame_resource.Complete(R"HTML( + <!DOCTYPE html> + <style> + body { + margin: 0; + } + canvas { + width: 199px; + height: 202px; + } + </style> + <canvas id='canvas'></canvas> + )HTML"); + + Compositor().BeginFrame(); + + // When creating the expected metadata, we have to take into account the + // offsets that are applied to the iframe that the canvas is in, and the 2px + // border around the iframe. + const float kIframeBorder = 2.f; + const float kIframeLeftOffset = 19.f + kIframeBorder; + const float kIframeTopOffset = 13.f + kIframeBorder; + const float kIframeHeight = 150.f; + const float kIframeWidth = 150.f; + const float kCanvasHeight = 202.f; + const float kCanvasWidth = 199.f; + + // Ensure that the webpage is larger than the iframe and canvas. + SetWebViewSize(kCanvasWidth + kIframeLeftOffset + 1, + kCanvasHeight + kIframeTopOffset + 1); + + TestDelegatedInkMetadata expected_metadata(gfx::RectF( + kIframeLeftOffset, kIframeTopOffset, kIframeWidth, kIframeHeight)); + + auto* iframe_element = + To<HTMLIFrameElement>(GetDocument().getElementById("iframe")); + auto* iframe_localframe = To<LocalFrame>(iframe_element->ContentFrame()); + Document* iframe_document = iframe_element->contentDocument(); + + DelegatedInkTrailPresenter* presenter = CreatePresenter( + iframe_localframe->GetDocument()->getElementById("canvas"), + iframe_document->GetFrame()); + DCHECK(presenter); + + InkTrailStyle style; + style.setDiameter(99.999); + style.setColor("lime"); + expected_metadata.SetDiameter(style.diameter()); + expected_metadata.SetColor(SK_ColorGREEN); + + gfx::PointF pt(102, 67); + presenter->updateInkTrailStartPoint( + ToScriptStateForMainWorld(iframe_document->GetFrame()), + CreatePointerMoveEvent(pt), &style); + expected_metadata.SetPoint( + gfx::PointF(pt.x() + kIframeLeftOffset, pt.y() + kIframeTopOffset)); + + expected_metadata.ExpectEqual(GetActualMetadata()); +} + +// Test that the presentation area is clipped correctly when it is offset left +// and above the iframe boundaries. +TEST_F(DelegatedInkTrailPresenterUnitTest, CanvasLeftAndAboveIframeBoundaries) { + SimRequest main_resource("https://example.com/test.html", "text/html"); + SimRequest frame_resource("https://example.com/iframe.html", "text/html"); + LoadURL("https://example.com/test.html"); + main_resource.Complete(R"HTML( + <!DOCTYPE html> + <style> + body { + margin: 0; + } + #iframe { + width: 300px; + height: 301px; + position: fixed; + top: 13px; + left: 19px; + } + </style> + <iframe id='iframe' src='https://example.com/iframe.html'> + </iframe> + )HTML"); + + frame_resource.Complete(R"HTML( + <!DOCTYPE html> + <style> + body { + margin: 0; + } + canvas { + width: 189px; + height: 145px; + position: fixed; + top: -70px; + left: -99px; + } + </style> + <canvas id='canvas'></canvas> + )HTML"); + + Compositor().BeginFrame(); + + // When creating the expected metadata, we have to take into account the + // offsets that are applied to the iframe that the canvas is in, and the 2px + // border around the iframe. + const float kIframeBorder = 2.f; + const float kIframeLeftOffset = 19.f + kIframeBorder; + const float kIframeTopOffset = 13.f + kIframeBorder; + const float kIframeHeight = 301.f; + const float kIframeWidth = 300.f; + const float kCanvasHeight = 145.f; + const float kCanvasWidth = 189.f; + const float kCanvasLeftOffset = -99.f; + const float kCanvasTopOffset = -70.f; + + // Ensure that the webpage is larger than the iframe. + SetWebViewSize(kIframeHeight + kIframeLeftOffset + 1, + kIframeWidth + kIframeTopOffset + 1); + + TestDelegatedInkMetadata expected_metadata(gfx::RectF( + kIframeLeftOffset, kIframeTopOffset, kCanvasWidth + kCanvasLeftOffset, + kCanvasHeight + kCanvasTopOffset)); + + auto* iframe_element = + To<HTMLIFrameElement>(GetDocument().getElementById("iframe")); + auto* iframe_localframe = To<LocalFrame>(iframe_element->ContentFrame()); + Document* iframe_document = iframe_element->contentDocument(); + + DelegatedInkTrailPresenter* presenter = CreatePresenter( + iframe_localframe->GetDocument()->getElementById("canvas"), + iframe_document->GetFrame()); + DCHECK(presenter); + + InkTrailStyle style; + style.setDiameter(99.999); + style.setColor("lime"); + expected_metadata.SetDiameter(style.diameter()); + expected_metadata.SetColor(SK_ColorGREEN); + + gfx::PointF pt(102, 67); + presenter->updateInkTrailStartPoint( + ToScriptStateForMainWorld(iframe_document->GetFrame()), + CreatePointerMoveEvent(pt), &style); + expected_metadata.SetPoint( + gfx::PointF(pt.x() + kIframeLeftOffset, pt.y() + kIframeTopOffset)); + + expected_metadata.ExpectEqual(GetActualMetadata()); +} + +// Confirm that values, specifically presentation area, are transformed +// correctly when the iframe that the canvas is in is clipped by its parent +// iframe. Numbers and color used were chosen arbitrarily. +TEST_F(DelegatedInkTrailPresenterUnitTest, OuterIframeClipsInnerIframe) { + SimRequest main_resource("https://example.com/test.html", "text/html"); + SimRequest frame_resource("https://example.com/iframe.html", "text/html"); + SimRequest frame2_resource("https://example.com/iframe2.html", "text/html"); + LoadURL("https://example.com/test.html"); + main_resource.Complete(R"HTML( + <!DOCTYPE html> + <style> + body { + margin: 0; + } + #OuterIframe { + width: 500px; + height: 500px; + position: fixed; + top: 26px; + left: 57px; + } + </style> + <iframe id='OuterIframe' src='https://example.com/iframe.html'> + </iframe> + )HTML"); + + frame_resource.Complete(R"HTML( + <!DOCTYPE html> + <style> + body { + margin: 0; + } + #InnerIframe { + width: 400px; + height: 400px; + position: fixed; + top: 311px; + left: 334px; + } + </style> + <iframe id='InnerIframe' src='https://example.com/iframe2.html'> + </iframe> + )HTML"); + + frame2_resource.Complete(R"HTML( + <!DOCTYPE html> + <style> + body { + margin: 0; + } + canvas { + width: 250px; + height: 250px; + position: fixed; + top: 1px; + left: 2px; + } + </style> + <canvas id='canvas'></canvas> + )HTML"); + + Compositor().BeginFrame(); + + // When creating the expected metadata, we have to take into account the + // offsets that are applied to the iframe that the canvas is in, and the 2px + // border around the iframe. + const float kIframeBorder = 2.f; + const float kOuterIframeLeftOffset = 57.f + kIframeBorder; + const float kOuterIframeTopOffset = 26.f + kIframeBorder; + const float kOuterIframeHeight = 500.f; + const float kOuterIframeWidth = 500.f; + const float kInnerIframeLeftOffset = + kOuterIframeLeftOffset + 334.f + kIframeBorder; + const float kInnerIframeTopOffset = + kOuterIframeTopOffset + 311.f + kIframeBorder; + const float kCanvasLeftOffset = 2.f; + const float kCanvasTopOffset = 1.f; + + // Ensure that the webpage is larger than the iframe and canvas. + const float kViewportWidth = kOuterIframeWidth + kOuterIframeLeftOffset + 1.f; + const float kViewportHeight = + kOuterIframeHeight + kOuterIframeTopOffset + 1.f; + SetWebViewSize(kViewportWidth, kViewportHeight); + + TestDelegatedInkMetadata expected_metadata( + gfx::RectF(kInnerIframeLeftOffset + kCanvasLeftOffset, + kInnerIframeTopOffset + kCanvasTopOffset, + kOuterIframeWidth + kOuterIframeLeftOffset - + kInnerIframeLeftOffset - kCanvasLeftOffset, + kOuterIframeHeight + kOuterIframeTopOffset - + kInnerIframeTopOffset - kCanvasTopOffset)); + + auto* outer_iframe_element = + To<HTMLIFrameElement>(GetDocument().getElementById("OuterIframe")); + auto* inner_iframe_element = To<HTMLIFrameElement>( + outer_iframe_element->contentDocument()->getElementById("InnerIframe")); + auto* iframe_localframe = + To<LocalFrame>(inner_iframe_element->ContentFrame()); + Document* iframe_document = inner_iframe_element->contentDocument(); + + DelegatedInkTrailPresenter* presenter = CreatePresenter( + iframe_localframe->GetDocument()->getElementById("canvas"), + iframe_document->GetFrame()); + DCHECK(presenter); + + InkTrailStyle style; + style.setDiameter(19); + style.setColor("red"); + expected_metadata.SetDiameter(style.diameter()); + expected_metadata.SetColor(SK_ColorRED); + + gfx::PointF pt(357, 401); + presenter->updateInkTrailStartPoint( + ToScriptStateForMainWorld(iframe_document->GetFrame()), + CreatePointerMoveEvent(pt), &style); + expected_metadata.SetPoint(gfx::PointF(pt.x() + kInnerIframeLeftOffset, + pt.y() + kInnerIframeTopOffset)); + + expected_metadata.ExpectEqual(GetActualMetadata()); +} + } // namespace blink
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_request_test.cc b/third_party/blink/renderer/modules/indexeddb/idb_request_test.cc index 212bd13..99d9c2f 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_request_test.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_request_test.cc
@@ -412,7 +412,7 @@ mojo::AssociatedRemote<mojom::blink::IDBDatabase> remote; std::unique_ptr<BackendDatabaseWithMockedClose> mock_database = std::make_unique<BackendDatabaseWithMockedClose>( - remote.BindNewEndpointAndPassDedicatedReceiverForTesting()); + remote.BindNewEndpointAndPassDedicatedReceiver()); EXPECT_CALL(*mock_database, Close()).Times(1); auto transaction_backend = std::make_unique<MockWebIDBTransaction>( @@ -435,7 +435,7 @@ mojo::AssociatedRemote<mojom::blink::IDBDatabase> remote; std::unique_ptr<BackendDatabaseWithMockedClose> mock_database = std::make_unique<BackendDatabaseWithMockedClose>( - remote.BindNewEndpointAndPassDedicatedReceiverForTesting()); + remote.BindNewEndpointAndPassDedicatedReceiver()); EXPECT_CALL(*mock_database, Close()).Times(1); auto transaction_backend = std::make_unique<MockWebIDBTransaction>(
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl_unittest.cc b/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl_unittest.cc index a56104c7..26480f8f 100644 --- a/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl_unittest.cc +++ b/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl_unittest.cc
@@ -115,7 +115,7 @@ WebIDBCursorImplTest() : null_key_(IDBKey::CreateNone()) { mojo::AssociatedRemote<mojom::blink::IDBCursor> remote; mock_cursor_ = std::make_unique<MockCursorImpl>( - remote.BindNewEndpointAndPassDedicatedReceiverForTesting()); + remote.BindNewEndpointAndPassDedicatedReceiver()); cursor_ = std::make_unique<WebIDBCursorImpl>( remote.Unbind(), 1, blink::scheduler::GetSingleThreadTaskRunnerForTesting());
diff --git a/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate_test.cc b/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate_test.cc index 9ef4ae09..cd37ccb 100644 --- a/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate_test.cc +++ b/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate_test.cc
@@ -113,7 +113,7 @@ HeapMojoAssociatedRemote<device::mojom::blink::ScreenOrientation> screen_orientation(frame.DomWindow()); ScreenOrientationClient().BindPendingReceiver( - screen_orientation.BindNewEndpointAndPassDedicatedReceiverForTesting()); + screen_orientation.BindNewEndpointAndPassDedicatedReceiver()); ScreenOrientationController::From(*frame.DomWindow()) ->SetScreenOrientationAssociatedRemoteForTests( std::move(screen_orientation));
diff --git a/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate_test.cc b/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate_test.cc index 560e7e0..3f3b2aa 100644 --- a/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate_test.cc +++ b/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate_test.cc
@@ -56,8 +56,7 @@ EmptyChromeClient::InstallSupplements(frame); HeapMojoAssociatedRemote<device::mojom::blink::ScreenOrientation> screen_orientation(frame.DomWindow()); - ignore_result( - screen_orientation.BindNewEndpointAndPassDedicatedReceiverForTesting()); + ignore_result(screen_orientation.BindNewEndpointAndPassDedicatedReceiver()); ScreenOrientationController::From(*frame.DomWindow()) ->SetScreenOrientationAssociatedRemoteForTests( std::move(screen_orientation));
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver.cc b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver.cc index 0a9cf5b12..fc46e57 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver.cc
@@ -212,6 +212,7 @@ return; } stopped_ = true; + UpdateMembers(); } void RTCRtpTransceiver::setCodecPreferences(
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver_impl.cc b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver_impl.cc index 900be89..f88d1933 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver_impl.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver_impl.cc
@@ -256,7 +256,12 @@ return error; } - webrtc::RTCError Stop() { return webrtc_transceiver_->StopStandard(); } + webrtc::RTCError Stop() { + auto error = webrtc_transceiver_->StopStandard(); + // After stop(), direction always returns 'stopped'. + state_.set_direction(webrtc::RtpTransceiverDirection::kStopped); + return error; + } webrtc::RTCError setCodecPreferences( std::vector<webrtc::RtpCodecCapability> codec_preferences) {
diff --git a/third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller_test.cc b/third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller_test.cc index ce13ab8..5da6f89a 100644 --- a/third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller_test.cc +++ b/third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller_test.cc
@@ -63,8 +63,7 @@ PageTestBase::SetUp(IntSize()); HeapMojoAssociatedRemote<device::mojom::blink::ScreenOrientation> screen_orientation(GetFrame().DomWindow()); - ignore_result( - screen_orientation.BindNewEndpointAndPassDedicatedReceiverForTesting()); + ignore_result(screen_orientation.BindNewEndpointAndPassDedicatedReceiver()); Controller()->SetScreenOrientationAssociatedRemoteForTests( std::move(screen_orientation)); }
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn index 43823db0..03f3c33 100644 --- a/third_party/blink/renderer/platform/BUILD.gn +++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -1547,7 +1547,6 @@ sources += [ "widget/input/synchronous_compositor_proxy.cc", "widget/input/synchronous_compositor_proxy.h", - "widget/input/synchronous_compositor_registry.h", ] } @@ -1597,6 +1596,8 @@ "//crypto", "//device/vr/public/mojom:mojom_blink", "//gin", + "//gpu:gpu", + "//gpu/command_buffer/client:webgpu_interface", "//jingle:webrtc_glue", "//media", "//media/capture:capture_switches", @@ -1818,6 +1819,7 @@ "//cc", "//cc:test_support", "//components/viz/test:test_support", + "//gpu:raster", "//testing/gmock", "//testing/gtest:gtest", "//testing/perf", @@ -2271,9 +2273,9 @@ "testing/blink_fuzzer_test_support.cc", "testing/blink_fuzzer_test_support.h", ] + public_deps = [ ":test_support" ] deps = [ ":platform", - ":test_support", "//base/test:test_config", "//content/test:test_support", ]
diff --git a/third_party/blink/renderer/platform/mojo/heap_mojo_associated_receiver_set_test.cc b/third_party/blink/renderer/platform/mojo/heap_mojo_associated_receiver_set_test.cc index 3dc9d88..d9bb1100 100644 --- a/third_party/blink/renderer/platform/mojo/heap_mojo_associated_receiver_set_test.cc +++ b/third_party/blink/renderer/platform/mojo/heap_mojo_associated_receiver_set_test.cc
@@ -131,7 +131,7 @@ auto& associated_receiver_set = owner()->associated_receiver_set(); mojo::AssociatedRemote<sample::blink::Service> associated_remote; auto associated_receiver = - associated_remote.BindNewEndpointAndPassDedicatedReceiverForTesting(); + associated_remote.BindNewEndpointAndPassDedicatedReceiver(); mojo::ReceiverId rid = associated_receiver_set.Add( std::move(associated_receiver), task_runner()); @@ -148,7 +148,7 @@ auto& associated_receiver_set = owner()->associated_receiver_set(); mojo::AssociatedRemote<sample::blink::Service> associated_remote; auto associated_receiver = - associated_remote.BindNewEndpointAndPassDedicatedReceiverForTesting(); + associated_remote.BindNewEndpointAndPassDedicatedReceiver(); mojo::ReceiverId rid = associated_receiver_set.Add( std::move(associated_receiver), task_runner()); @@ -167,7 +167,7 @@ mojo::AssociatedRemote<sample::blink::Service> associated_remote; auto associated_receiver = - associated_remote.BindNewEndpointAndPassDedicatedReceiverForTesting(); + associated_remote.BindNewEndpointAndPassDedicatedReceiver(); mojo::ReceiverId rid = owner()->associated_receiver_set().Add( std::move(associated_receiver), task_runner()); @@ -188,7 +188,7 @@ auto& associated_receiver_set = owner()->associated_receiver_set(); mojo::AssociatedRemote<sample::blink::Service> associated_remote; auto associated_receiver = - associated_remote.BindNewEndpointAndPassDedicatedReceiverForTesting(); + associated_remote.BindNewEndpointAndPassDedicatedReceiver(); mojo::ReceiverId rid = associated_receiver_set.Add( std::move(associated_receiver), task_runner()); @@ -205,7 +205,7 @@ auto& associated_receiver_set = owner()->associated_receiver_set(); mojo::AssociatedRemote<sample::blink::Service> associated_remote; auto associated_receiver = - associated_remote.BindNewEndpointAndPassDedicatedReceiverForTesting(); + associated_remote.BindNewEndpointAndPassDedicatedReceiver(); mojo::ReceiverId rid = associated_receiver_set.Add( std::move(associated_receiver), task_runner());
diff --git a/third_party/blink/renderer/platform/mojo/heap_mojo_associated_remote.h b/third_party/blink/renderer/platform/mojo/heap_mojo_associated_remote.h index 0db58374..4a3760e 100644 --- a/third_party/blink/renderer/platform/mojo/heap_mojo_associated_remote.h +++ b/third_party/blink/renderer/platform/mojo/heap_mojo_associated_remote.h
@@ -64,9 +64,9 @@ std::move(task_runner)); } mojo::PendingAssociatedReceiver<Interface> - BindNewEndpointAndPassDedicatedReceiverForTesting() WARN_UNUSED_RESULT { + BindNewEndpointAndPassDedicatedReceiver() WARN_UNUSED_RESULT { return wrapper_->associated_remote() - .BindNewEndpointAndPassDedicatedReceiverForTesting(); + .BindNewEndpointAndPassDedicatedReceiver(); } void Bind(mojo::PendingAssociatedRemote<Interface> pending_associated_remote, scoped_refptr<base::SequencedTaskRunner> task_runner) {
diff --git a/third_party/blink/web_tests/WebDriverExpectations b/third_party/blink/web_tests/WebDriverExpectations index 5e1772e..94bcb81 100644 --- a/third_party/blink/web_tests/WebDriverExpectations +++ b/third_party/blink/web_tests/WebDriverExpectations
@@ -184,3 +184,5 @@ crbug.com/1123907 [ Linux ] external/wpt/webdriver/tests/fullscreen_window/stress.py>>test_stress[2] [ Failure Pass ] crbug.com/1123907 [ Linux ] external/wpt/webdriver/tests/fullscreen_window/stress.py>>test_stress[3] [ Failure Pass ] crbug.com/1123907 [ Linux ] external/wpt/webdriver/tests/fullscreen_window/stress.py>>test_stress[4] [ Failure Pass ] +crbug.com/1123907 [ Linux ] external/wpt/webdriver/tests/fullscreen_window/stress.py>>test_stress [ Failure Pass ] +crbug.com/1128104 [ Linux ] external/wpt/webdriver/tests/release_actions/sequence.py>>test_no_release_mouse_sequence_keeps_dblclick_state [ Failure ]
diff --git a/third_party/blink/web_tests/external/wpt/mathml/crashtests/display-and-column-properties.html b/third_party/blink/web_tests/external/wpt/mathml/crashtests/display-and-column-properties.html new file mode 100644 index 0000000..c40a2a0 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/mathml/crashtests/display-and-column-properties.html
@@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html class="test-wait"> + <head> + <title>MathML elements with display and column properties</title> + <meta charset="utf-8"/> + <style> + math { + column-width: 100px; + } + </style> + </head> + <body> + <math></math> + <math style="display: list-item"></math> + <script> + window.addEventListener("load", function() { + // Force initial layout. + document.documentElement.getBoundingClientRect(); + + // Change display and reforce layout. + let maths = document.getElementsByTagName("math"); + maths[0].setAttribute("style", "display: list-item"); + maths[1].removeAttribute("style"); + document.documentElement.getBoundingClientRect(); + + document.documentElement.classList.remove("test-wait"); + }); + </script> + </body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/display-2.html b/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/display-2.html new file mode 100644 index 0000000..e0d41e4 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/display-2.html
@@ -0,0 +1,134 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>Verify that one can override the layout of MathML elements with the CSS display property</title> +<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#layout-algorithms"> +<meta name="assert" content="Verify that one can override the display of a MathML element."> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/mathml/support/layout-comparison.js"></script> +<script src="/mathml/support/mathml-fragments.js"></script> +<style> + mfrac { + padding: 0; + } +</style> +<script> + const Xsize = 25; + const templates = { + "block display": `<math style="display: block;">XXX</math>`, + "block display with contrained width": `<math style="display: block; width: ${2*Xsize}px;">XXX</math>`, + "list display inside display block": `<math style="display: block">\ + <mmultiscripts style="display: list-item;">X</mmultiscripts>\ + <maction style="display: list-item;">X</maction>\ + <mpadded style="display: list-item;">X</mpadded>\ +</math>`, + "inline display": `<math style="display: inline;">XXX</math>`, + "inline-block display": `<math style="display: inline-block">XXX</math>`, + "table display (math)": `<math style="display: table">\ + <mfrac style='display: table-row'>\ + <msub style='display: table-cell'>X</msub>\ + <msup style='display: table-cell'>X</msup>\ + <msubsup style='display: table-cell'>X</msubsup>\ + </mfrac>\ + <mtable style='display: table-row'>\ + <munder style='display: table-cell'>X</munder>\ + <mover style='display: table-cell'>X</mover>\ + <munderover style='display: table-cell'>X</munderover>\ + </mtable>\ +</math>`, + "table display (mrow)": `<math display="block">\ +<mrow style="display: table">\ + <mfrac style='display: table-row'>\ + <msub style='display: table-cell'>X</msub>\ + <msup style='display: table-cell'>X</msup>\ + <msubsup style='display: table-cell'>X</msubsup>\ + </mfrac>\ + <mtable style='display: table-row'>\ + <munder style='display: table-cell'>X</munder>\ + <mover style='display: table-cell'>X</mover>\ + <munderover style='display: table-cell'>X</munderover>\ + </mtable>\ +</mrow></math>`, + "inline-table display (math)": `<math style="display: inline-table">\ + <mfrac style='display: table-row'>\ + <msub style='display: table-cell'>X</msub>\ + <msup style='display: table-cell'>X</msup>\ + <msubsup style='display: table-cell'>X</msubsup>\ + </mfrac>\ + <mtable style='display: table-row'>\ + <munder style='display: table-cell'>X</munder>\ + <mover style='display: table-cell'>X</mover>\ + <munderover style='display: table-cell'>X</munderover>\ + </mtable>\ +</math>`, + "inline-table display (mrow)": `<math display="block">\ +<mrow style="display: inline-table">\ + <mfrac style='display: table-row'>\ + <msub style='display: table-cell'>X</msub>\ + <msup style='display: table-cell'>X</msup>\ + <msubsup style='display: table-cell'>X</msubsup>\ + </mfrac>\ + <mtable style='display: table-row'>\ + <munder style='display: table-cell'>X</munder>\ + <mover style='display: table-cell'>X</mover>\ + <munderover style='display: table-cell'>X</munderover>\ + </mtable>\ +</mrow></math>`, + "flexbox display (math)": `<math style="display: flex; flex-direction: column;">XXX</math>`, + "flexbox display (mrow)": `<math display="block"><mrow style="display: flex; flex-direction: column;">XXX</mrow></math>`, + "grid display (math)": `<math style="display: grid; grid-gap: 2px; grid-template-columns: ${Xsize}px ${Xsize}px ${Xsize}px;>">XXXXXXXXX</math>`, + "grid display (mrow)": `<math display="block"><mrow style="display: grid; grid-gap: 2px; grid-template-columns: ${Xsize}px ${Xsize}px ${Xsize}px;>">XXXXXXXXX</mrow></math>`, + "ruby display (math)": `<math style="display: ruby;">\ +<mrow style="display: ruby-base;">X</mrow>\ +<mrow style="display: ruby-text">XX</mrow>\ +</math>`, + "ruby display (mrow)": `<math display="block"><mrow style="display: ruby;">\ +<mrow style="display: ruby-base;">X</mrow>\ +<mrow style="display: ruby-text">XX</mrow>\ +</mrow></math>`, + "block display with column width (math)": `<math style="display: block; column-width: ${2*Xsize}px">\ + <mrow>XXXX</mrow><mrow>XXXX</mrow><mrow>XXXX</mrow>\ +</math>`, + "block display with column width (mrow)": `<math style="display: block"><mrow style="display: block; column-width: ${2*Xsize}px">\ + <mrow>XXXX</mrow><mrow>XXXX</mrow><mrow>XXXX</mrow>\ +</mrow></math>`, + }; + + setup({ explicit_done: true }); + window.addEventListener("load", runTests); + + function runTests() { + + for (let key in templates) { + if (!templates.hasOwnProperty(key)) + continue; + let mathtest = templates[key]. + replace(/X/g, `<mspace style="display: inline-block; width: ${Xsize}px; height: ${Xsize}px; background: black"></mspace>`); + let reference = mathtest. + replace(/maction|math|mfrac|mmultiscripts|mover|mover|mpadded|mrow|mspace|msubsup|msub|msup|mtable|munderover|munder/g, "div"); + document.body.insertAdjacentHTML("beforeend", `<div style="position: absolute;">\ +<div><span>${key}:</span>${mathtest}</div>\ +<div><span>${key}:</span>${reference}</div>\ +</div>`); + let div = document.body.lastElementChild; + let elementDiv = div.firstElementChild; + let referenceDiv = div.lastElementChild; + + test(function() { + const epsilon = 1; + compareLayout(elementDiv, referenceDiv, epsilon); + }, `${key}`); + + div.style = "display: none;"; // Hide the div after measurement. + } + + done(); + } +</script> +</head> +<body> + <div id="log"></div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/element-internals-shadowroot.tentative.html b/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/element-internals-shadowroot.tentative.html index 0f01cc4..8469a6c 100644 --- a/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/element-internals-shadowroot.tentative.html +++ b/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/element-internals-shadowroot.tentative.html
@@ -41,4 +41,73 @@ assert_true(constructed); }, 'ElementInternals.shadowRoot allows access to closed shadow root'); +test(() => { + let constructed = false; + const element = document.createElement('x-1'); + assert_throws_dom('NotSupportedError', () => element.attachInternals(),'attachInternals cannot be called before definition exists'); + customElements.define('x-1', class extends HTMLElement { + constructor() { + super(); + assert_true(!!this.attachInternals()); + constructed = true; + } + }); + assert_false(constructed); + assert_throws_dom('NotSupportedError', () => element.attachInternals(),'attachInternals cannot be called before constructor'); + customElements.upgrade(element); + assert_true(constructed); + assert_throws_dom('NotSupportedError', () => element.attachInternals(),'attachInternals already called'); +}, 'ElementInternals cannot be called before constructor, upgrade case'); + +test(() => { + let constructed = false; + const element = document.createElement('x-2'); + customElements.define('x-2', class extends HTMLElement { + constructor() { + super(); + // Don't attachInternals() here + constructed = true; + } + }); + assert_throws_dom('NotSupportedError', () => element.attachInternals(),'attachInternals cannot be called before constructor'); + assert_false(constructed); + customElements.upgrade(element); + assert_true(constructed); + assert_true(!!element.attachInternals(),'After the constructor, ok to call from outside'); +}, 'ElementInternals *can* be called after constructor, upgrade case'); + +test(() => { + let constructed = false; + customElements.define('x-3', class extends HTMLElement { + constructor() { + super(); + assert_true(!!this.attachInternals()); + constructed = true; + } + }); + const element = document.createElement('x-3'); + assert_true(constructed); + assert_throws_dom('NotSupportedError', () => element.attachInternals(), 'attachInternals already called'); +}, 'ElementInternals cannot be called after constructor calls it, create case'); + +test(() => { + let constructed = false; + const element = document.createElement('x-5'); + customElements.define('x-5', class extends HTMLElement { + static disabledFeatures = [ 'internals' ]; + constructor() { + super(); + assert_throws_dom('NotSupportedError', () => this.attachInternals(), 'attachInternals forbidden by disabledFeatures, constructor'); + constructed = true; + } + }); + assert_false(constructed); + assert_throws_dom('NotSupportedError', () => element.attachInternals(), 'attachInternals forbidden by disabledFeatures, pre-upgrade'); + customElements.upgrade(element); + assert_true(constructed); + assert_throws_dom('NotSupportedError', () => element.attachInternals(), 'attachInternals forbidden by disabledFeatures, post-upgrade'); +}, 'ElementInternals disabled by disabledFeatures'); + + + </script>
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpTransceiver.https-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpTransceiver.https-expected.txt index 71f96185..cdefe3f 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpTransceiver.https-expected.txt +++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpTransceiver.https-expected.txt
@@ -24,16 +24,16 @@ FAIL checkRemoveTrackNegotiation assert_equals: pc2.setRemoteDescription(offer) should've added 2 tracks to receive stream expected 2 but got 0 FAIL checkMute assert_true: expected true got false FAIL checkStop assert_equals: getReceivers does not expose a receiver of a stopped transceiver expected 0 but got 1 -FAIL checkStopAfterCreateOffer assert_equals: expected "[{stopped:true}]" but got "[{stopped:false}]" -FAIL checkStopAfterSetLocalOffer assert_equals: expected "[{stopped:true}]" but got "[{stopped:false}]" -FAIL checkStopAfterSetRemoteOffer assert_equals: expected "[{mid:null,stopped:true}]" but got "[{mid:\"0\",stopped:false}]" -FAIL checkStopAfterCreateAnswer assert_equals: expected "[{mid:null,stopped:true}]" but got "[{mid:\"0\",stopped:false}]" -FAIL checkStopAfterSetLocalAnswer assert_equals: expected "[{mid:null,stopped:true}]" but got "[{mid:\"0\",stopped:false}]" +PASS checkStopAfterCreateOffer +PASS checkStopAfterSetLocalOffer +PASS checkStopAfterSetRemoteOffer +PASS checkStopAfterCreateAnswer +PASS checkStopAfterSetLocalAnswer PASS checkStopAfterClose -FAIL checkLocalRollback assert_equals: expected "[{stopped:true}]" but got "[{stopped:false}]" +PASS checkLocalRollback PASS checkRollbackAndSetRemoteOfferWithDifferentType -FAIL checkRemoteRollback assert_equals: expected "{currentDirection:null,mid:null,stopped:true}" but got "{currentDirection:null,mid:null,stopped:false}" -FAIL checkMsectionReuse assert_equals: expected "[{currentDirection:null,mid:null,stopped:true}]" but got "[{currentDirection:\"inactive\",mid:\"0\",stopped:false}]" +FAIL checkRemoteRollback promise_test: Unhandled rejection with value: object "InvalidAccessError: Failed to execute 'addTrack' on 'RTCPeerConnection': A sender already exists for the track." +FAIL checkMsectionReuse assert_equals: expected "[{currentDirection:null,mid:null}]" but got "[{currentDirection:\"inactive\",mid:\"0\"}]" PASS checkStopAfterCreateOfferWithReusedMsection PASS checkAddIceCandidateToStoppedTransceiver FAIL checkBundleTagRejected promise_test: Unhandled rejection with value: object "InvalidAccessError: Failed to execute 'setRemoteDescription' on 'RTCPeerConnection': Failed to set remote offer sdp: The m= section with mid='1' should be rejected."
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpTransceiver.https.html b/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpTransceiver.https.html index 412736b..2e1dcbb 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpTransceiver.https.html +++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpTransceiver.https.html
@@ -199,7 +199,6 @@ direction: "sendrecv", mid: null, currentDirection: null, - stopped: false }, { receiver: {track: {kind: "video", readyState: "live", muted: true}}, @@ -207,7 +206,6 @@ direction: "sendrecv", mid: null, currentDirection: null, - stopped: false } ]); }; @@ -232,7 +230,6 @@ direction: "sendrecv", mid: null, currentDirection: null, - stopped: false }, { receiver: {track: {kind: "video"}}, @@ -240,7 +237,6 @@ direction: "sendrecv", mid: null, currentDirection: null, - stopped: false } ]); }; @@ -265,7 +261,6 @@ direction: "sendrecv", mid: null, currentDirection: null, - stopped: false }, { receiver: {track: {kind: "video"}}, @@ -273,7 +268,6 @@ direction: "sendrecv", mid: null, currentDirection: null, - stopped: false } ]); }; @@ -293,7 +287,6 @@ direction: "recvonly", mid: null, currentDirection: null, - stopped: false }, { receiver: {track: {kind: "video"}}, @@ -301,7 +294,6 @@ direction: "recvonly", mid: null, currentDirection: null, - stopped: false } ]); }; @@ -336,7 +328,6 @@ sender: {track: null}, direction: "recvonly", currentDirection: null, - stopped: false } ]); }; @@ -365,7 +356,6 @@ // rtcweb-jsep says this is recvonly, w3c-webrtc does not... direction: "recvonly", currentDirection: null, - stopped: false } ]); }; @@ -435,7 +425,6 @@ sender: {track: null}, direction: "recvonly", currentDirection: null, - stopped: false } ]); @@ -466,7 +455,6 @@ sender: {track: {kind: "audio"}}, direction: "sendrecv", currentDirection: null, - stopped: false } ]); @@ -486,7 +474,6 @@ sender: {track: {kind: "audio"}}, direction: "sendrecv", currentDirection: "sendonly", - stopped: false, mid: lastMid } ]); @@ -500,7 +487,6 @@ sender: {track: {kind: "audio"}}, direction: "sendrecv", currentDirection: "sendonly", - stopped: false, mid: lastMid } ]); @@ -1253,15 +1239,14 @@ assert_equals(pc1.getSenders().length, 0, 'getSenders does not expose a sender of a stopped transceiver'); await onended; - + // The transceiver has [[stopping]] = true, [[stopped]] = false hasPropsAndUniqueMids(pc1.getTransceivers(), [ { sender: {track: {kind: "audio"}}, receiver: {track: {kind: "audio", readyState: "ended"}}, - stopped: true, - currentDirection: null, - direction: "sendrecv" + currentDirection: "sendrecv", + direction: "stopped" } ]); @@ -1297,15 +1282,16 @@ await onended; + // pc2's transceiver was stopped remotely, so has + // [[stopping]] = true, [[stopped]] = true. hasProps(pc2.getTransceivers(), [ { sender: {track: {kind: "audio"}}, receiver: {track: {kind: "audio", readyState: "ended"}}, - stopped: true, mid: null, - currentDirection: null, - direction: "sendrecv" + currentDirection: "stopped", + direction: "stopped" } ]); @@ -1335,13 +1321,14 @@ let offer = await pc1.createOffer(); - pc1.getTransceivers()[0].stop(); - + const transceiverThatWasStopped = pc1.getTransceivers()[0]; + transceiverThatWasStopped.stop(); await pc2.setRemoteDescription(offer) trickle(t, pc1, pc2); await pc1.setLocalDescription(offer); let answer = await pc2.createAnswer(); + const negotiationNeededAwaiter = negotiationNeeded(pc1); const trackEvents = await setRemoteDescriptionReturnTrackEvents(pc1, answer); // Spec language doesn't say anything about checking whether the transceiver // is stopped here. @@ -1353,16 +1340,20 @@ } ]); + assert_equals(transceiverThatWasStopped, pc1.getTransceivers()[0]); + // The transceiver should still be [[stopping]]=true, [[stopped]]=false. hasPropsAndUniqueMids(pc1.getTransceivers(), [ { - stopped: true, + currentDirection: "sendrecv", + direction: "stopped" } ]); - await negotiationNeeded(pc1); + await negotiationNeededAwaiter; trickle(t, pc2, pc1); + await pc2.setLocalDescription(answer); await iceConnected(pc1); @@ -1374,22 +1365,8 @@ answer = await pc2.createAnswer(); await pc2.setLocalDescription(answer); await pc1.setRemoteDescription(answer); - - hasProps(pc1.getTransceivers(), - [ - { - stopped: true, - mid: null - } - ]); - - hasProps(pc2.getTransceivers(), - [ - { - stopped: true, - mid: null - } - ]); + assert_equals(pc1.getTransceivers().length, 0); + assert_equals(pc2.getTransceivers().length, 0); }; const checkStopAfterSetLocalOffer = async t => { @@ -1413,6 +1390,7 @@ pc1.getTransceivers()[0].stop(); let answer = await pc2.createAnswer(); + const negotiationNeededAwaiter = negotiationNeeded(pc1); const trackEvents = await setRemoteDescriptionReturnTrackEvents(pc1, answer); // Spec language doesn't say anything about checking whether the transceiver // is stopped here. @@ -1427,10 +1405,11 @@ hasPropsAndUniqueMids(pc1.getTransceivers(), [ { - stopped: true, + direction: "stopped", + currentDirection: "sendrecv" } ]); - await negotiationNeeded(pc1); + await negotiationNeededAwaiter; trickle(t, pc2, pc1); await pc2.setLocalDescription(answer); @@ -1445,21 +1424,8 @@ await pc2.setLocalDescription(answer); await pc1.setRemoteDescription(answer); - hasProps(pc1.getTransceivers(), - [ - { - stopped: true, - mid: null - } - ]); - - hasProps(pc2.getTransceivers(), - [ - { - stopped: true, - mid: null - } - ]); + assert_equals(pc1.getTransceivers().length, 0); + assert_equals(pc2.getTransceivers().length, 0); }; const checkStopAfterSetRemoteOffer = async t => { @@ -1479,22 +1445,35 @@ await pc2.setRemoteDescription(offer) await pc1.setLocalDescription(offer); - // Stop on _answerer_side now. Should take effect in answer. + // Stop on _answerer_ side now. Should not stop transceiver in answer, + // but cause firing of negotiationNeeded at pc2, and disabling + // of the transceiver with direction = inactive in answer. pc2.getTransceivers()[0].stop(); + assert_equals(pc2.getTransceivers()[0].direction, 'stopped'); const answer = await pc2.createAnswer(); const trackEvents = await setRemoteDescriptionReturnTrackEvents(pc1, answer); hasProps(trackEvents, []); - hasProps(pc1.getTransceivers(), + hasProps(pc2.getTransceivers(), [ { - stopped: true, - mid: null + direction: "stopped", + currentDirection: null, } ]); + const negotiationNeededAwaiter = negotiationNeeded(pc2); await pc2.setLocalDescription(answer); + hasProps(pc2.getTransceivers(), + [ + { + direction: "stopped", + currentDirection: "inactive", + } + ]); + + await negotiationNeededAwaiter; }; const checkStopAfterCreateAnswer = async t => { @@ -1532,16 +1511,25 @@ hasPropsAndUniqueMids(pc2.getTransceivers(), [ { - stopped: true, + direction: "stopped", + currentDirection: null, } ]); trickle(t, pc2, pc1); - // The negotiaionneeded event is fired during processing of + // The negotiationneeded event is fired during processing of // setLocalDescription() - const negotiationNeededWaiter = negotiationNeeded(pc2); + const negotiationNeededAwaiter = negotiationNeeded(pc2); await pc2.setLocalDescription(answer); - await negotiationNeededWaiter; + hasPropsAndUniqueMids(pc2.getTransceivers(), + [ + { + direction: "stopped", + currentDirection: "sendrecv", + } + ]); + + await negotiationNeededAwaiter; await iceConnected(pc1); await iceConnected(pc2); @@ -1552,19 +1540,22 @@ await pc2.setLocalDescription(answer); await pc1.setRemoteDescription(answer); + // Since this offer/answer exchange was initiated from pc1, + // pc2 still doesn't get to say that it has a stopped transceiver, + // but does get to set it to inactive. hasProps(pc1.getTransceivers(), [ { - stopped: true, - mid: null + direction: "sendrecv", + currentDirection: "inactive", } ]); hasProps(pc2.getTransceivers(), [ { - stopped: true, - mid: null + direction: "stopped", + currentDirection: "inactive", } ]); }; @@ -1607,7 +1598,8 @@ hasPropsAndUniqueMids(pc2.getTransceivers(), [ { - stopped: true, + direction: "stopped", + currentDirection: "sendrecv", } ]); @@ -1615,28 +1607,17 @@ await iceConnected(pc1); await iceConnected(pc2); - offer = await pc1.createOffer(); - await pc1.setLocalDescription(offer); - await pc2.setRemoteDescription(offer); - answer = await pc2.createAnswer(); - await pc2.setLocalDescription(answer); - await pc1.setRemoteDescription(answer); + // Initiate an offer/answer exchange from pc2 in order + // to negotiate the stopped transceiver. + offer = await pc2.createOffer(); + await pc2.setLocalDescription(offer); + await pc1.setRemoteDescription(offer); + answer = await pc1.createAnswer(); + await pc1.setLocalDescription(answer); + await pc2.setRemoteDescription(answer); - hasProps(pc1.getTransceivers(), - [ - { - stopped: true, - mid: null - } - ]); - - hasProps(pc2.getTransceivers(), - [ - { - stopped: true, - mid: null - } - ]); + assert_equals(pc1.getTransceivers().length, 0); + assert_equals(pc2.getTransceivers().length, 0); }; const checkStopAfterClose = async t => { @@ -1683,7 +1664,6 @@ sender: {track}, direction: "sendrecv", currentDirection: null, - stopped: false } ]); @@ -1703,7 +1683,6 @@ direction: "sendonly", mid: null, currentDirection: null, - stopped: false } ]); @@ -1713,7 +1692,11 @@ pc.getTransceivers()[0].stop(); await pc.setLocalDescription({type: "rollback"}); - hasProps(pc.getTransceivers(), [{ stopped: true }]); + hasProps(pc.getTransceivers(), [ + { + direction: "stopped", + } + ]); }; const checkRollbackAndSetRemoteOfferWithDifferentType = async t => { @@ -1744,7 +1727,6 @@ direction: "sendrecv", mid: null, currentDirection: null, - stopped: false } ]); @@ -1756,7 +1738,6 @@ direction: "sendrecv", mid: null, currentDirection: null, - stopped: false } ]); @@ -1770,14 +1751,12 @@ direction: "sendrecv", mid: null, currentDirection: null, - stopped: false }, { receiver: {track: {kind: "video"}}, sender: {track: null}, direction: "recvonly", currentDirection: "recvonly", - stopped: false } ]); @@ -1788,7 +1767,6 @@ sender: {track: videoTrack}, direction: "sendrecv", currentDirection: "sendonly", - stopped: false } ]); @@ -1823,7 +1801,6 @@ hasProps(removedTransceiver, { - stopped: true, mid: null, currentDirection: null } @@ -1834,7 +1811,6 @@ hasProps(removedTransceiver, { receiver: {track: {readyState: "ended"}}, - stopped: true, mid: null, currentDirection: null } @@ -1849,7 +1825,6 @@ sender: {track: null}, direction: "recvonly", currentDirection: null, - stopped: false } ]); @@ -1869,7 +1844,6 @@ direction: "sendrecv", mid: mid0, currentDirection: null, - stopped: false } ]); @@ -1889,7 +1863,6 @@ direction: "recvonly", mid: mid0, currentDirection: null, - stopped: false } ]); @@ -1903,7 +1876,6 @@ direction: "sendrecv", mid: mid0, currentDirection: null, - stopped: false } ]); @@ -1917,7 +1889,6 @@ direction: "sendrecv", mid: null, currentDirection: null, - stopped: false } ]); @@ -1954,7 +1925,6 @@ direction: "sendrecv", mid: mid0, currentDirection: "sendrecv", - stopped: false } ]); @@ -1990,21 +1960,20 @@ direction: "sendrecv", mid: null, currentDirection: null, - stopped: true } ]); // stop() cannot be rolled back! + // Transceiver should have [[stopping]]=true, [[stopped]]=false await pc2.setRemoteDescription({type: "rollback"}); hasProps(pc2.getTransceivers(), [ { receiver: {track: {kind: "audio"}}, sender: {track: {kind: "audio"}}, - direction: "sendrecv", + direction: "stopped", mid: null, - currentDirection: null, - stopped: true + currentDirection: "sendrecv", } ]); }; @@ -2062,7 +2031,6 @@ { mid: null, currentDirection: null, - stopped: true } ]); @@ -2071,7 +2039,6 @@ { mid: null, currentDirection: null, - stopped: true } ]); @@ -2087,7 +2054,6 @@ hasProps(pc1.getTransceivers(), [ { - stopped: true }, { sender: {track: track2} @@ -2103,7 +2069,6 @@ hasProps(pc2.getTransceivers(), [ { - stopped: true }, { sender: {track} @@ -2181,7 +2146,6 @@ }, { mid: null, - stopped: true }, { sender: {track: null}, @@ -2206,7 +2170,6 @@ [ {}, { - stopped: true }, { mid: mid1,
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/mathml/relations/css-styling/display-2-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/mathml/relations/css-styling/display-2-expected.txt new file mode 100644 index 0000000..57a3c69 --- /dev/null +++ b/third_party/blink/web_tests/platform/linux/external/wpt/mathml/relations/css-styling/display-2-expected.txt
@@ -0,0 +1,20 @@ +This is a testharness.js-based test. +PASS block display +PASS block display with contrained width +PASS list display inside display block +PASS inline display +PASS inline-block display +FAIL table display (math) assert_approx_equals: block size expected 80 +/- 1 but got 78 +PASS table display (mrow) +FAIL inline-table display (math) assert_approx_equals: block size expected 60 +/- 1 but got 58 +PASS inline-table display (mrow) +PASS flexbox display (math) +PASS flexbox display (mrow) +PASS grid display (math) +PASS grid display (mrow) +FAIL ruby display (math) assert_approx_equals: block size expected 80 +/- 1 but got 30 +FAIL ruby display (mrow) assert_approx_equals: block size expected 80 +/- 1 but got 45 +FAIL block display with column width (math) assert_approx_equals: block size expected 80 +/- 1 but got 45 +FAIL block display with column width (mrow) assert_approx_equals: block size expected 80 +/- 1 but got 45 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/mathml/relations/css-styling/display-2-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/mathml/relations/css-styling/display-2-expected.txt new file mode 100644 index 0000000..2ec5d3b --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/external/wpt/mathml/relations/css-styling/display-2-expected.txt
@@ -0,0 +1,20 @@ +This is a testharness.js-based test. +PASS block display +PASS block display with contrained width +PASS list display inside display block +PASS inline display +PASS inline-block display +PASS table display (math) +PASS table display (mrow) +PASS inline-table display (math) +PASS inline-table display (mrow) +PASS flexbox display (math) +PASS flexbox display (mrow) +PASS grid display (math) +PASS grid display (mrow) +FAIL ruby display (math) assert_approx_equals: block size expected 76 +/- 1 but got 29 +FAIL ruby display (mrow) assert_approx_equals: block size expected 76 +/- 1 but got 43 +FAIL block display with column width (math) assert_approx_equals: block size expected 76 +/- 1 but got 43 +FAIL block display with column width (mrow) assert_approx_equals: block size expected 76 +/- 1 but got 43 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/mathml/relations/css-styling/display-2-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/mathml/relations/css-styling/display-2-expected.txt new file mode 100644 index 0000000..57a3c69 --- /dev/null +++ b/third_party/blink/web_tests/platform/win/external/wpt/mathml/relations/css-styling/display-2-expected.txt
@@ -0,0 +1,20 @@ +This is a testharness.js-based test. +PASS block display +PASS block display with contrained width +PASS list display inside display block +PASS inline display +PASS inline-block display +FAIL table display (math) assert_approx_equals: block size expected 80 +/- 1 but got 78 +PASS table display (mrow) +FAIL inline-table display (math) assert_approx_equals: block size expected 60 +/- 1 but got 58 +PASS inline-table display (mrow) +PASS flexbox display (math) +PASS flexbox display (mrow) +PASS grid display (math) +PASS grid display (mrow) +FAIL ruby display (math) assert_approx_equals: block size expected 80 +/- 1 but got 30 +FAIL ruby display (mrow) assert_approx_equals: block size expected 80 +/- 1 but got 45 +FAIL block display with column width (math) assert_approx_equals: block size expected 80 +/- 1 but got 45 +FAIL block display with column width (mrow) assert_approx_equals: block size expected 80 +/- 1 but got 45 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCRtpTransceiver.https-expected.txt b/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCRtpTransceiver.https-expected.txt index 511ad56..66385f4 100644 --- a/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCRtpTransceiver.https-expected.txt +++ b/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCRtpTransceiver.https-expected.txt
@@ -2,14 +2,14 @@ Harness Error. harness_status.status = 1 , harness_status.message = Unhandled rejection: Cannot read property 'receiver' of undefined FAIL checkAddTransceiverNoTrack promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'." FAIL checkAddTransceiverWithTrack promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'." -FAIL checkAddTransceiverWithAddTrack assert_equals: expected "[{currentDirection:null,direction:\"sendrecv\",mid:null,receiver:{track:{kind:\"audio\"}},sender:{track:{}},stopped:false},{currentDirection:null,direction:\"sendrecv\",mid:null,receiver:{track:{kind:\"video\"}},sender:{track:{}},stopped:false}]" but got "[]" +FAIL checkAddTransceiverWithAddTrack assert_equals: expected "[{currentDirection:null,direction:\"sendrecv\",mid:null,receiver:{track:{kind:\"audio\"}},sender:{track:{}}},{currentDirection:null,direction:\"sendrecv\",mid:null,receiver:{track:{kind:\"video\"}},sender:{track:{}}}]" but got "[]" FAIL checkAddTransceiverWithDirection promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'." PASS checkMsidNoTrackId FAIL checkAddTransceiverWithSetRemoteOfferSending promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'." FAIL checkAddTransceiverWithSetRemoteOfferNoSend promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'." FAIL checkAddTransceiverBadKind assert_true: addTransceiver("foo") throws a TypeError expected true got false -FAIL checkNoMidOffer assert_equals: expected "[{currentDirection:null,direction:\"recvonly\",receiver:{track:{kind:\"audio\"}},sender:{track:null},stopped:false}]" but got "[]" -FAIL checkNoMidAnswer assert_equals: expected "[{currentDirection:null,direction:\"sendrecv\",receiver:{track:{kind:\"audio\"}},sender:{track:{kind:\"audio\"}},stopped:false}]" but got "[]" +FAIL checkNoMidOffer assert_equals: expected "[{currentDirection:null,direction:\"recvonly\",receiver:{track:{kind:\"audio\"}},sender:{track:null}}]" but got "[]" +FAIL checkNoMidAnswer assert_equals: expected "[{currentDirection:null,direction:\"sendrecv\",receiver:{track:{kind:\"audio\"}},sender:{track:{kind:\"audio\"}}}]" but got "[]" FAIL checkSetDirection promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'." FAIL checkCurrentDirection assert_equals: expected "[{currentDirection:null}]" but got "[]" FAIL checkSendrecvWithNoSendTrack promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'." @@ -31,7 +31,7 @@ FAIL checkStopAfterCreateAnswer promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'stop' of undefined" FAIL checkStopAfterSetLocalAnswer promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'receiver' of undefined" FAIL checkStopAfterClose assert_equals: Stopping a transceiver on a closed PC should throw. throws InvalidStateError expected "InvalidStateError" but got "TypeError" -FAIL checkLocalRollback assert_equals: expected "[{currentDirection:null,direction:\"sendrecv\",receiver:{track:{kind:\"audio\"}},sender:{track:{}},stopped:false}]" but got "[]" +FAIL checkLocalRollback assert_equals: expected "[{currentDirection:null,direction:\"sendrecv\",receiver:{track:{kind:\"audio\"}},sender:{track:{}}}]" but got "[]" FAIL checkRollbackAndSetRemoteOfferWithDifferentType promise_test: Unhandled rejection with value: object "OperationError: Failed to execute 'setLocalDescription' on 'RTCPeerConnection': Rollback not supported in Plan B" FAIL checkRemoteRollback promise_test: Unhandled rejection with value: object "OperationError: Failed to execute 'setRemoteDescription' on 'RTCPeerConnection': Rollback not supported in Plan B" FAIL checkMsectionReuse promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'mid' of undefined"
diff --git a/third_party/usrsctp/BUILD.gn b/third_party/usrsctp/BUILD.gn index 00ed6acb..b869852 100644 --- a/third_party/usrsctp/BUILD.gn +++ b/third_party/usrsctp/BUILD.gn
@@ -9,6 +9,12 @@ "usrsctplib/usrsctplib", "usrsctplib/usrsctplib/netinet", ] + + # This is part of the public config because it's used both by usrsctp and + # the client (WebRTC), to determine if the length field needs populating. + if (is_mac || is_ios || target_os == "freebsd") { + defines = [ "HAVE_SCONN_LEN" ] + } } config("usrsctp_warnings") { @@ -129,11 +135,9 @@ } else if (is_apple) { defines += [ "HAVE_SA_LEN", - "HAVE_SCONN_LEN", "__APPLE_USE_RFC_2292", "__Userspace_os_Darwin", ] - cflags += [ "-U__APPLE__" ] } if (is_win) {
diff --git a/third_party/usrsctp/README.chromium b/third_party/usrsctp/README.chromium index 18ebfe0d..33139cb7 100644 --- a/third_party/usrsctp/README.chromium +++ b/third_party/usrsctp/README.chromium
@@ -1,8 +1,8 @@ Name: usrsctp URL: http://github.com/sctplab/usrsctp Version: 0 -Date: Feb 2, 2020 -Revision: bee946a606752a443bd70bca1cb296527fed706d +Date: Aug 28, 2020 +Revision: 995c0b84414466d77d52011e5b572cbe213b770a License: New BSD License File: LICENSE Security Critical: yes
diff --git a/third_party/widevine/cdm/widevine.gni b/third_party/widevine/cdm/widevine.gni index 769489b..ddf5c94 100644 --- a/third_party/widevine/cdm/widevine.gni +++ b/third_party/widevine/cdm/widevine.gni
@@ -47,8 +47,17 @@ bundle_widevine_cdm = false } +declare_args() { +# Enable Widevine CDM host verification, which will sign additional binaries +# with Widevine certs and copy signature files as needed. Only enabled by +# default on official bots. For developers building with "is_official_build" +# locally without Widevine certs, this will cause a build failure, which can +# be suppressed by manually setting `enable_widevine_cdm_host_verification` to +# false. enable_widevine_cdm_host_verification = enable_library_widevine_cdm && enable_cdm_host_verification + && is_official_build +} template("widevine_sign_file") { # For official builds, generate a signature file for |file| which will
diff --git a/tools/gritsettings/resource_ids.spec b/tools/gritsettings/resource_ids.spec index 902db6a2..32c6f27 100644 --- a/tools/gritsettings/resource_ids.spec +++ b/tools/gritsettings/resource_ids.spec
@@ -328,6 +328,9 @@ "chromeos/components/diagnostics_ui/resources/diagnostics_app_resources.grd": { "includes": [2517], }, + "chromeos/components/file_manager/resources/file_manager_resources.grd": { + "includes": [2518], + }, "chromeos/components/help_app_ui/resources/help_app_resources.grd": { "includes": [2520], },
diff --git a/tools/json_schema_compiler/cc_generator.py b/tools/json_schema_compiler/cc_generator.py index fd1a77dd..72057fc4 100644 --- a/tools/json_schema_compiler/cc_generator.py +++ b/tools/json_schema_compiler/cc_generator.py
@@ -161,8 +161,8 @@ if type_.origin.from_manifest_keys: c.Cblock( - self._GenerateParseFromDictionary(classname, classname_in_namespace, - type_)) + self._GenerateParseFromDictionary( + classname, classname_in_namespace, type_)) elif type_.property_type == PropertyType.ENUM: (c.Cblock(self._GenerateEnumToString(cpp_namespace, type_)) .Cblock(self._GenerateEnumFromString(cpp_namespace, type_)) @@ -490,8 +490,8 @@ assert self._namespace.manifest_keys.property_type == PropertyType.OBJECT return self._GenerateType(None, self._namespace.manifest_keys) - def _GenerateParseFromDictionary(self, classname, classname_in_namespace, - type_): + def _GenerateParseFromDictionary( + self, classname, classname_in_namespace, type_): # type: (str, str, Type) -> Code """Generates a function that deserializes the type from the passed dictionary. E.g. for type "Foo", generates Foo::ParseFromDictionary(). @@ -613,6 +613,7 @@ PropertyType.INTEGER, PropertyType.OBJECT, PropertyType.STRING, + PropertyType.ENUM } c = Code() @@ -621,14 +622,47 @@ assert (underlying_property_type in supported_property_types), ( 'Property type not implemented for %s, type: %s, namespace: %s' % (underlying_property_type, underlying_type.name, - underlying_type.namespace.name)) + underlying_type.namespace.name)) + + assert (underlying_property_type != PropertyType.ARRAY or + underlying_type.item_type.property_type != PropertyType.ENUM), ( + 'Enum types in arrays are not currently supported. Type: %s.' % + underlying_type.name) property_constant = cpp_util.UnixNameToConstantName(property.unix_name) out_expression = '&out->%s' % property.unix_name + + if underlying_property_type == PropertyType.ENUM: + enum_name = cpp_util.Classname( + schema_util.StripNamespace(underlying_type.name)) + cpp_type_namespace = '' if underlying_type.namespace == self._namespace \ + else '%s::' % underlying_type.namespace.unix_name + + params = [ + 'dict', + '%s' % property_constant, + '&%sParse%s' % (cpp_type_namespace, enum_name), + 'true' if property.optional else 'false', + '%s%s' % (cpp_type_namespace, + self._type_helper.GetEnumNoneValue(underlying_type)), + '%s' % out_expression, + 'error', + 'error_path_reversed' + ] + func_name = 'ParseEnumFromDictionary' + else: + params = [ + 'dict', + '%s' % property_constant, + '%s' % out_expression, + 'error', + 'error_path_reversed' + ] + func_name = 'ParseFromDictionary' + c.Sblock( - 'if (!::json_schema_compiler::manifest_parse_util::ParseFromDictionary' - '(dict, %s, %s, error, error_path_reversed)) {' % - (property_constant, out_expression) + 'if (!::json_schema_compiler::manifest_parse_util::%s(%s)) {' + % (func_name, self._GenerateParams(params, generate_error_messages=False)) ) if is_root_manifest_type: c.Append('::json_schema_compiler::manifest_parse_util::'
diff --git a/tools/json_schema_compiler/cpp_util.py b/tools/json_schema_compiler/cpp_util.py index e5159f1..d83f4f4 100644 --- a/tools/json_schema_compiler/cpp_util.py +++ b/tools/json_schema_compiler/cpp_util.py
@@ -138,8 +138,7 @@ # type (str) -> str """Converts unix_name to kUnixName. """ - return ('k' + ''.join(word[0].upper() + word[1:] - for word in unix_name.split('_'))) + return ('k' + ''.join(word.capitalize() for word in unix_name.split('_'))) def IsUnixName(s): # type (str) -> bool
diff --git a/tools/json_schema_compiler/manifest_parse_util.cc b/tools/json_schema_compiler/manifest_parse_util.cc index ae41bbc..98728c7 100644 --- a/tools/json_schema_compiler/manifest_parse_util.cc +++ b/tools/json_schema_compiler/manifest_parse_util.cc
@@ -54,6 +54,20 @@ "Parsing array failed: %s.", base::UTF16ToASCII(*error).c_str())); } +void PopulateInvalidEnumValueError( + base::StringPiece key, + const std::string& value, + base::string16* error, + std::vector<base::StringPiece>* error_path_reversed) { + DCHECK(error); + DCHECK(error_path_reversed); + DCHECK(error_path_reversed->empty()); + + error_path_reversed->push_back(key); + *error = base::ASCIIToUTF16( + base::StringPrintf("Specified value '%s' is invalid.", value.c_str())); +} + void PopulateFinalError(base::string16* error, std::vector<base::StringPiece>* error_path_reversed) { DCHECK(error); @@ -77,7 +91,6 @@ std::vector<base::StringPiece>* error_path_reversed) { DCHECK(error); DCHECK(error_path_reversed); - DCHECK(error->empty()); DCHECK(error_path_reversed->empty()); const base::Value* value = dict.FindKey(key);
diff --git a/tools/json_schema_compiler/manifest_parse_util.h b/tools/json_schema_compiler/manifest_parse_util.h index 31923cc..d6c108d 100644 --- a/tools/json_schema_compiler/manifest_parse_util.h +++ b/tools/json_schema_compiler/manifest_parse_util.h
@@ -25,6 +25,14 @@ base::string16* error, std::vector<base::StringPiece>* error_path_reversed); +// Populates |error| and |error_path_reversed| denoting the given invalid enum +// |value| at the given |key|. +void PopulateInvalidEnumValueError( + base::StringPiece key, + const std::string& value, + base::string16* error, + std::vector<base::StringPiece>* error_path_reversed); + // Populates manifest parse |error| for the given path in |error_path_reversed|. void PopulateFinalError(base::string16* error, std::vector<base::StringPiece>* error_path_reversed); @@ -129,6 +137,47 @@ return true; } +// Alias for pointer to a function which converts a string to an enum of type T. +template <typename T> +using StringToEnumConverter = T (*)(const std::string&); + +// Parses enum |out| from |dict| at the given |key|. On failure, returns false +// and populates |error| and |error_path_reversed|. +template <typename T> +bool ParseEnumFromDictionary( + const base::DictionaryValue& dict, + base::StringPiece key, + StringToEnumConverter<T> converter, + bool is_optional_property, + T none_value, + T* out, + base::string16* error, + std::vector<base::StringPiece>* error_path_reversed) { + DCHECK(out); + DCHECK_EQ(none_value, *out); + + // Ignore optional keys if they are not present without raising an error. + if (is_optional_property && !dict.FindKey(key)) + return true; + + // Parse errors for optional keys which are specified should still cause a + // failure. + const base::Value* value = FindKeyOfType(dict, key, base::Value::Type::STRING, + error, error_path_reversed); + if (!value) + return false; + + const std::string str = value->GetString(); + T enum_value = converter(str); + if (enum_value == none_value) { + PopulateInvalidEnumValueError(key, str, error, error_path_reversed); + return false; + } + + *out = enum_value; + return true; +} + } // namespace manifest_parse_util } // namespace json_schema_compiler
diff --git a/tools/json_schema_compiler/test/simple_api.json b/tools/json_schema_compiler/test/simple_api.json index 9ad8175..de2c8b3 100644 --- a/tools/json_schema_compiler/test/simple_api.json +++ b/tools/json_schema_compiler/test/simple_api.json
@@ -4,6 +4,11 @@ "description": "This is a simple API.", "types": [ { + "id": "TestEnum", + "type": "string", + "enum": ["one", "two", "three"] + }, + { "id": "TestType", "type": "object", "properties": { @@ -38,13 +43,12 @@ "items": { "type": "string" } + }, + "opt_external_enum": { + "optional": true, + "$ref": "enums.Enumeration" } } - }, - { - "id": "TestEnum", - "type": "string", - "enum": ["one", "two", "three"] } ], "manifest_keys": { @@ -67,6 +71,9 @@ "type": "boolean" } } + }, + "key_enum": { + "$ref": "TestEnum" } }, "functions": [
diff --git a/tools/json_schema_compiler/test/simple_api_unittest.cc b/tools/json_schema_compiler/test/simple_api_unittest.cc index 74613b3..d3adb399 100644 --- a/tools/json_schema_compiler/test/simple_api_unittest.cc +++ b/tools/json_schema_compiler/test/simple_api_unittest.cc
@@ -12,8 +12,10 @@ #include "base/values.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "tools/json_schema_compiler/test/enums.h" namespace simple_api = test::api::simple_api; +namespace enums = test::api::enums; namespace { @@ -49,7 +51,7 @@ bool result = simple_api::ManifestKeys::ParseFromDictionary( base::Value::AsDictionaryValue(*manifest), manifest_keys, &error_16); - ASSERT_TRUE(result); + ASSERT_TRUE(result) << error_16; ASSERT_TRUE(error_16.empty()) << error_16; } @@ -245,7 +247,8 @@ "integer": 32, "object": { "foo": "bar" - } + }, + "key_enum": "one" } })"; @@ -266,7 +269,8 @@ "number": 25.4, "integer": 32, "array": ["one", "two", 3] - } + }, + "key_enum": "one" })"; std::string error; @@ -277,6 +281,27 @@ error); } +TEST(JsonSchemaCompilerSimpleTest, ManifestKeyParsing_InvalidEnumValue) { + const char kPartialManifestJson[] = R"({ + "key_string": "abc", + "key_ref": { + "string": "ref_string", + "boolean": true, + "number": 25.4, + "integer": 32, + "opt_external_enum": "four" + }, + "key_enum": "one" + })"; + + std::string error; + ASSERT_NO_FATAL_FAILURE(GetManifestParseError(kPartialManifestJson, &error)); + EXPECT_EQ( + "Error at key 'key_ref.opt_external_enum'. Specified value 'four' is " + "invalid.", + error); +} + TEST(JsonSchemaCompilerSimpleTest, ManifestKeyParsing_Success_AllKeys) { const char kPartialManifestJson[] = R"({ "key_string": "abc", @@ -288,12 +313,14 @@ "object": { "foo": 42 }, - "array": ["one", "two"] + "array": ["one", "two"], + "opt_external_enum": "two" }, "key_obj": { "obj_string": "foo", "obj_bool": true - } + }, + "key_enum": "one" })"; simple_api::ManifestKeys manifest_keys; @@ -306,6 +333,8 @@ EXPECT_EQ("foo", manifest_keys.key_obj->obj_string); EXPECT_TRUE(manifest_keys.key_obj->obj_bool); + EXPECT_EQ(simple_api::TEST_ENUM_ONE, manifest_keys.key_enum); + EXPECT_EQ("ref_string", manifest_keys.key_ref.string); EXPECT_EQ(true, manifest_keys.key_ref.boolean); EXPECT_DOUBLE_EQ(25.4, manifest_keys.key_ref.number); @@ -315,6 +344,7 @@ ASSERT_TRUE(manifest_keys.key_ref.array); EXPECT_THAT(*manifest_keys.key_ref.array, ::testing::ElementsAre("one", "two")); + EXPECT_EQ(enums::ENUMERATION_TWO, manifest_keys.key_ref.opt_external_enum); } // Ensure leaving out optional keys is not a manifest parse error. @@ -327,7 +357,8 @@ "boolean": true, "number": 25.4, "integer": 32 - } + }, + "key_enum": "two" })"; simple_api::ManifestKeys manifest_keys; @@ -336,10 +367,12 @@ EXPECT_EQ("abc", manifest_keys.key_string); EXPECT_FALSE(manifest_keys.key_obj); + EXPECT_EQ(simple_api::TEST_ENUM_TWO, manifest_keys.key_enum); EXPECT_EQ("ref_string", manifest_keys.key_ref.string); EXPECT_EQ(true, manifest_keys.key_ref.boolean); EXPECT_DOUBLE_EQ(25.4, manifest_keys.key_ref.number); EXPECT_EQ(32, manifest_keys.key_ref.integer); EXPECT_FALSE(manifest_keys.key_ref.array); + EXPECT_EQ(enums::ENUMERATION_NONE, manifest_keys.key_ref.opt_external_enum); }
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 947830e..d6ab6830 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -27,6 +27,7 @@ 'linux-chrome-beta': 'official_goma', 'linux-chrome-stable': 'official_goma', 'linux-chromeos-chrome': 'official_goma_chromeos', + 'linux-chromeos-chrome-easwa': 'official_goma_chromeos', 'mac-chrome': 'official_goma', 'mac-chrome-beta': 'official_goma', 'mac-chrome-stable': 'official_goma', @@ -255,6 +256,7 @@ 'Linux remote_run Tester': 'release_bot', 'Linux Viz': 'release_trybot', 'linux-ash-chromium-builder-fyi-rel': 'chromeos_with_codecs_release_bot', + 'linux-inverse-fieldtrials-fyi-rel': 'gpu_tests_release_bot_minimal_symbols_invert_fieldtrials', 'linux-lacros-builder-fyi-rel': 'lacros_on_linux_release_bot', 'linux-lacros-tester-fyi-rel': 'lacros_on_linux_release_bot', 'Mac Builder Next': 'gpu_tests_release_bot_minimal_symbols', @@ -814,6 +816,7 @@ 'linux-chrome-beta': 'official_goma', 'linux-chrome-stable': 'official_goma', 'linux-chromeos-chrome': 'official_goma_chromeos_include_unwind_tables', + 'linux-chromeos-chrome-easwa': 'official_goma_chromeos_include_unwind_tables', 'mac-chrome': 'official_goma', 'mac-chrome-beta': 'official_goma', 'mac-chrome-stable': 'official_goma', @@ -902,6 +905,7 @@ 'linux-clang-tidy-dbg': 'debug_bot', 'linux-clang-tidy-rel': 'release_trybot', 'linux-dcheck-off-rel': 'release_trybot_dcheck_off', + 'linux-inverse-fieldtrials-fyi-rel': 'gpu_tests_release_trybot_no_symbols_use_dummy_lastchange_invert_fieldtrials', 'linux-gcc-rel': 'release_bot_x86_minimal_symbols_no_clang_cxx11', 'linux-lacros-fyi-rel': 'lacros_on_linux_release_trybot', 'linux-libfuzzer-asan-rel': 'libfuzzer_asan_release_trybot', @@ -1899,6 +1903,10 @@ 'gpu_tests', 'debug_bot', 'x86', 'no_symbols' ], + 'gpu_tests_release_bot': [ + 'gpu_tests', 'release_bot', + ], + 'gpu_tests_release_bot_minimal_symbols': [ 'gpu_tests', 'release_bot', 'minimal_symbols', ], @@ -1908,11 +1916,12 @@ 'partial_code_coverage_instrumentation', ], + 'gpu_tests_release_bot_minimal_symbols_invert_fieldtrials': [ + 'gpu_tests', 'release_bot', 'minimal_symbols', 'invert_fieldtrials', + ], + 'gpu_tests_release_bot_minimal_symbols_no_nacl': [ - 'gpu_tests', - 'release_bot', - 'minimal_symbols', - 'disable_nacl', + 'gpu_tests', 'release_bot', 'minimal_symbols', 'disable_nacl', ], 'gpu_tests_release_bot_x86_minimal_symbols': [ @@ -1961,8 +1970,9 @@ 'use_clang_coverage', 'partial_code_coverage_instrumentation', ], - 'gpu_tests_release_trybot': [ - 'gpu_tests', 'release_trybot', + 'gpu_tests_release_trybot_no_symbols_use_dummy_lastchange_invert_fieldtrials': [ + 'gpu_tests', 'release_trybot', 'no_symbols', 'use_dummy_lastchange', + 'invert_fieldtrials', ], 'gpu_tests_release_trybot_ptr_comp': [ @@ -1973,10 +1983,6 @@ 'gpu_tests', 'release_trybot', 'x86', 'resource_whitelisting', ], - 'gpu_tests_release_bot': [ - 'gpu_tests', 'release_bot', - ], - 'gpu_tests_sk_dawn_release_trybot': [ 'gpu_tests', 'sk_dawn', 'release_trybot', ], @@ -2765,6 +2771,10 @@ 'gn_args': 'internal_gles2_conform_tests=true build_angle_gles1_conform_tests=true', }, + 'invert_fieldtrials': { + 'gn_args': 'invert_fieldtrials=true', + }, + 'ios': { 'gn_args': 'target_os="ios"', },
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 796889b82..0cd38739 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -29157,6 +29157,7 @@ <int value="3467" label="CSSContainAllWithoutContentVisibility"/> <int value="3468" label="TimerInstallFromBeforeUnload"/> <int value="3469" label="TimerInstallFromUnload"/> + <int value="3470" label="ElementAttachInternalsBeforeConstructor"/> </enum> <enum name="FeaturePolicyAllowlistType"> @@ -40965,6 +40966,7 @@ <int value="-1645071473" label="ChromeColors:disabled"/> <int value="-1644721118" label="disable-experimental-accessibility-chromevox-search-menus"/> + <int value="-1643933608" label="SyncAutofillWalletOfferData:enabled"/> <int value="-1641832607" label="DragToPinTabs:enabled"/> <int value="-1638815914" label="enable-experimental-productivity-features"/> <int value="-1634878515" label="ChromeHomeModernLayout:enabled"/> @@ -41271,6 +41273,7 @@ <int value="-1357655121" label="enable-iframe-based-signin"/> <int value="-1357008397" label="ContextualSuggestionsCarousel:disabled"/> <int value="-1356379431" label="GlobalMediaControlsOverlayControls:enabled"/> + <int value="-1353865639" label="InteractiveWindowCycleList:disabled"/> <int value="-1353714232" label="FilesTransferDetails:enabled"/> <int value="-1353195918" label="UseSkiaRenderer:enabled"/> <int value="-1351968795" label="SingleProcessMash:enabled"/> @@ -41985,6 +41988,7 @@ <int value="-632030508" label="NativeWindowNavButtons:disabled"/> <int value="-631740127" label="inert-visual-viewport"/> <int value="-631614101" label="CameraSystemWebApp:enabled"/> + <int value="-630946893" label="TabSearchFixedEntrypoint:enabled"/> <int value="-626329144" label="SyncSupportTrustedVaultPassphrase:enabled"/> <int value="-626211146" label="DesktopMinimalUI:disabled"/> <int value="-625695291" label="AccessibilityExposeARIAAnnotations:enabled"/> @@ -42153,6 +42157,7 @@ <int value="-460313418" label="ProgressBarThrottle:enabled"/> <int value="-460081932" label="CustomFeedbackUi:disabled"/> <int value="-459318667" label="AccessiblePDFForm:enabled"/> + <int value="-457584339" label="TemporaryHoldingSpace:enabled"/> <int value="-457292000" label="HappinessTrackingSurveysForDesktop:enabled"/> <int value="-457174225" label="Av1Decoder:enabled"/> <int value="-456321929" label="ForceEnableSystemAec:disabled"/> @@ -42340,6 +42345,7 @@ label="AutofillSaveCreditCardUsesStrikeSystemV2:enabled"/> <int value="-268357961" label="enable-feature-policy"/> <int value="-265697837" label="PhoneHub:disabled"/> + <int value="-263645996" label="InteractiveWindowCycleList:enabled"/> <int value="-263150202" label="BundledConnectionHelp:disabled"/> <int value="-262122630" label="ArcEnableDocumentsProviderInFilesApp:enabled"/> <int value="-258081634" label="AutofillAssistantDirectActions:disabled"/> @@ -42603,6 +42609,7 @@ <int value="8891567" label="CaptionSettings:enabled"/> <int value="10458238" label="disable-print-preview-simplify"/> <int value="11698808" label="enable-dom-distiller-button-animation"/> + <int value="12016364" label="OmniboxBubbleUrlSuggestions:enabled"/> <int value="15614295" label="Portals:enabled"/> <int value="19629326" label="OmniboxExperimentalKeywordMode:enabled"/> <int value="19815558" label="EnableSettingsShortcutSearch:disabled"/> @@ -42804,6 +42811,7 @@ <int value="266702296" label="disable-plugin-power-saver"/> <int value="268535107" label="ash-new-touch-support-for-screen-magnification"/> + <int value="270118291" label="SyncAutofillWalletOfferData:disabled"/> <int value="270267831" label="enable-scripts-require-action"/> <int value="272108480" label="SmbFs:enabled"/> <int value="272631627" label="BookmarkAppsMac:enabled"/> @@ -43410,6 +43418,7 @@ <int value="879699575" label="disable-gesture-tap-highlight"/> <int value="879992337" label="disable-pull-to-refresh-effect"/> <int value="880510010" label="enable-permissions-bubbles"/> + <int value="880677998" label="TabSearchFixedEntrypoint:disabled"/> <int value="883190338" label="PrintWithReducedRasterization:disabled"/> <int value="884106779" label="supervised-user-safesites"/> <int value="885004540" label="ArcEnableApplicationZoomFeature:enabled"/> @@ -44008,6 +44017,7 @@ <int value="1496571153" label="enable-webapk"/> <int value="1497609106" label="ContextualNudges:enabled"/> <int value="1497924954" label="js-flags"/> + <int value="1498398756" label="TemporaryHoldingSpace:disabled"/> <int value="1499163193" label="PostScriptPrinting:disabled"/> <int value="1500390299" label="NtpCustomizationMenuV2:disabled"/> <int value="1505194447" label="disable-transition-compositing"/> @@ -44526,6 +44536,7 @@ <int value="2032558514" label="RemoveUsageOfDeprecatedGaiaSigninEndpoint:enabled"/> <int value="2034198538" label="TabHoverCards:enabled"/> + <int value="2037562553" label="OmniboxBubbleUrlSuggestions:disabled"/> <int value="2037756154" label="enable-impl-side-painting"/> <int value="2038036881" label="NewShortcutMapping:enabled"/> <int value="2039276757" label="EnableOverviewRoundedCorners:enabled"/> @@ -68581,6 +68592,7 @@ <int value="5" label="Voice"/> <int value="6" label="Calculator"/> <int value="7" label="Favicon"/> + <int value="8" label="Trends"/> </enum> <enum name="SuggestionPedalType"> @@ -75602,6 +75614,15 @@ <int value="2" label="Signature whitelist"/> </enum> +<enum name="WidgetClosedReason"> + <int value="0" label="Unspecified"/> + <int value="1" label="EscKeyPressed"/> + <int value="2" label="CloseButtonClicked"/> + <int value="3" label="LostFocus"/> + <int value="4" label="CancelButtonClicked"/> + <int value="5" label="AcceptButtonClicked"/> +</enum> + <enum name="WiFiAp80211kSupport"> <int value="0" label="Does not support 802.11k"/> <int value="1" label="Supports 802.11k neighbor lists"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 65de6fc..03a558e 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -28953,8 +28953,12 @@ <histogram name="Compositing.Browser.GPUMemoryForTilingsInKb" units="Kb" expires_after="M87"> + <obsolete> + Removed September, 2020. Memory.GPU.PeakMemoryUsage.PageLoad can be used to + track overall GPU memory usage. + </obsolete> <owner>pdr@chromium.org</owner> - <owner>ericrk@chromium.org</owner> + <owner>paint-dev@chromium.org</owner> <summary> The GPU memory allocated for tilings (in a browser process), summed over all picture layers. Emitted once per drawing. Nothing is recorded if there are @@ -28962,8 +28966,6 @@ Tilings are used for decomposition of the layer's entire contents at a picture screenspace resolution to do threaded rasterization. - - Team: paint-dev@chromium.org. </summary> </histogram> @@ -29655,6 +29657,9 @@ <histogram name="Compositing.Renderer.DirectlyCompositedImage.AvoidRasterAdjustmentWithTransformTrigger" units="boolean" expires_after="M87"> + <obsolete> + Removed September 2020 because the research it was used for is complete. + </obsolete> <owner>pdr@chromium.org</owner> <owner>dlibby@microsoft.com</owner> <owner>paint-dev@chromium.org</owner> @@ -29670,6 +29675,9 @@ <histogram name="Compositing.Renderer.DirectlyCompositedImage.RasterScaleDirectlyComposited" units="boolean" expires_after="M87"> + <obsolete> + Removed September 2020 because the research it was used for is complete. + </obsolete> <owner>pdr@chromium.org</owner> <owner>dlibby@microsoft.com</owner> <owner>paint-dev@chromium.org</owner> @@ -29682,6 +29690,9 @@ <histogram name="Compositing.Renderer.DirectlyCompositedImage.TileAreaAdded" units="pixels" expires_after="M87"> + <obsolete> + Removed September 2020 because the research it was used for is complete. + </obsolete> <owner>pdr@chromium.org</owner> <owner>dlibby@microsoft.com</owner> <owner>paint-dev@chromium.org</owner> @@ -29695,6 +29706,9 @@ <histogram name="Compositing.Renderer.DirectlyCompositedImage.TileAreaMatches" units="boolean" expires_after="M87"> + <obsolete> + Removed September 2020 because the research it was used for is complete. + </obsolete> <owner>pdr@chromium.org</owner> <owner>dlibby@microsoft.com</owner> <owner>paint-dev@chromium.org</owner> @@ -29709,6 +29723,9 @@ <histogram name="Compositing.Renderer.DirectlyCompositedImage.TileAreaSaved" units="pixels" expires_after="M87"> + <obsolete> + Removed September 2020 because the research it was used for is complete. + </obsolete> <owner>pdr@chromium.org</owner> <owner>dlibby@microsoft.com</owner> <owner>paint-dev@chromium.org</owner> @@ -29760,9 +29777,9 @@ </histogram> <histogram name="Compositing.Renderer.GPUMemoryForTilingsInKb" units="Kb" - expires_after="M87"> + expires_after="M90"> <owner>pdr@chromium.org</owner> - <owner>ericrk@chromium.org</owner> + <owner>paint-dev@chromium.org</owner> <summary> The GPU memory allocated for tilings (in a renderer process), summed over all picture layers. Emitted once per drawing. Nothing is recorded if there @@ -29770,8 +29787,6 @@ Tilings are used for decomposition of the layer's entire contents at a picture screenspace resolution to do threaded rasterization. - - Team: paint-dev@chromium.org. </summary> </histogram> @@ -100155,9 +100170,15 @@ </summary> </histogram> -<histogram name="Net.HttpProxy.ConnectLatency" units="ms" expires_after="M85"> +<histogram name="Net.HttpProxy.ConnectLatency" units="ms" + expires_after="2021-09-14"> + <owner>eroman@chromium.org</owner> <owner>tbansal@chromium.org</owner> - <summary>Time taken to establish the connection to the HTTP proxy.</summary> + <summary> + Time taken to establish the connection to the HTTP proxy. Note that the + histogram expired briefly for M-86 and M-87 non-stable versions. Exact + counts during that period may not be meaningful. + </summary> </histogram> <histogram name="Net.HttpProxySocketRequestTime" units="ms" @@ -104456,6 +104477,28 @@ </summary> </histogram> +<histogram name="Net.QuicSession.ZeroRttReasonGoogle" + enum="SSLHandshakeEarlyDataReason" expires_after="2021-05-11"> + <owner>renjietang@chromium.org</owner> + <owner>src/net/quic/OWNERS</owner> + <summary> + Indicates whether a QUIC handshake attempted or used 0-RTT on the + connection, and if 0-RTT was not used, it provides reasons why. Only records + connections with Google hosted servers. + </summary> +</histogram> + +<histogram name="Net.QuicSession.ZeroRttReasonNonGoogle" + enum="SSLHandshakeEarlyDataReason" expires_after="2021-05-11"> + <owner>renjietang@chromium.org</owner> + <owner>src/net/quic/OWNERS</owner> + <summary> + Indicates whether a QUIC handshake attempted or used 0-RTT on the + connection, and if 0-RTT was not used, it provides reasons why. Only records + connections with non-Google servers. + </summary> +</histogram> + <histogram name="Net.QuicSession.ZeroRttState" enum="ZeroRttState" expires_after="2021-05-11"> <owner>renjietang@chromium.org</owner> @@ -112720,6 +112763,17 @@ </summary> </histogram> +<histogram name="NewTabPage.Modules.ShownTime" units="ms" + expires_after="2021-01-01"> + <owner>tiborg@chromium.org</owner> + <owner>yyushkina@chromium.org</owner> + <owner>chrome-desktop-ntp@google.com</owner> + <summary> + Histogram of the time, in milliseconds since navigation start, it took until + the modules showed up on the NTP. + </summary> +</histogram> + <histogram name="NewTabPage.MostVisited" enum="MostVisitedTileIndex" expires_after="never"> <!-- expires-never: part of top-line metric (internal: go/chrome-browser-nsm) --> @@ -192210,6 +192264,18 @@ </summary> </histogram> +<histogram name="WebApp.InstallConfirmation.CloseReason" + enum="WidgetClosedReason" expires_after="M95"> + <owner>dmurph@chromium.org</owner> + <owner>desktop-pwa-team@google.com</owner> + <summary> + Records the reason that the WebApp install confirmation dialog is closed. + This dialog is shown when the user clicks on the 'install' icon in the + omnibox for websites that are installable. This metric is intended to give + data for an experiment to choose the best install icon. + </summary> +</histogram> + <histogram name="Webapp.InstallDuration.System" units="ms" expires_after="2021-03-07"> <owner>calamity@chromium.org</owner>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index 0c83629..0f30ecb 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -9,8 +9,8 @@ "remote_path": "perfetto_binaries/trace_processor_shell/mac/6b0afc48ae3d07d8cf6598be674562f9844333ec/trace_processor_shell" }, "linux": { - "hash": "2b1c2e7aeb587514deb69cce2d6223c3d2aad6f6", - "remote_path": "perfetto_binaries/trace_processor_shell/linux/9edd1a906f57a995531db1050629b608424ee202/trace_processor_shell" + "hash": "a4dde16c3a65a90950fbef9de7003dc503bfefa8", + "remote_path": "perfetto_binaries/trace_processor_shell/linux/bef393a5a340a4d6303b263cba7adee98372ab7f/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml index 1702583..71ff201 100644 --- a/tools/traffic_annotation/summary/annotations.xml +++ b/tools/traffic_annotation/summary/annotations.xml
@@ -162,6 +162,7 @@ <item id="isolated_prerender_canary_check" hash_code="60914954" type="0" content_hash_code="2991117" os_list="linux,windows" file_path="chrome/browser/prerender/isolated/isolated_prerender_origin_prober.cc"/> <item id="isolated_prerender_loader" hash_code="2181152" type="0" content_hash_code="113933667" os_list="linux,windows" file_path="chrome/browser/prerender/isolated/isolated_prerender_url_loader.cc"/> <item id="isolated_prerender_probe" hash_code="115160522" type="0" content_hash_code="75211055" os_list="linux,windows" file_path="chrome/browser/prerender/isolated/isolated_prerender_origin_prober.cc"/> + <item id="javascript_report_error" hash_code="109607776" type="0" content_hash_code="30837893" os_list="linux,windows" file_path="components/crash/content/browser/error_reporting/send_javascript_error_report.cc"/> <item id="kaleidoscope_service" hash_code="49759694" type="0" content_hash_code="14307563" os_list="linux,windows" file_path="chrome/browser/media/kaleidoscope/kaleidoscope_service.cc"/> <item id="kids_chrome_management_client_classify_url" hash_code="109987793" type="0" deprecated="2019-07-30" content_hash_code="112740597" file_path=""/> <item id="lib_address_input" hash_code="50816767" type="0" content_hash_code="57977576" os_list="linux,windows" file_path="third_party/libaddressinput/chromium/chrome_metadata_source.cc"/>
diff --git a/tools/traffic_annotation/summary/grouping.xml b/tools/traffic_annotation/summary/grouping.xml index 6637b65..588ea5e 100644 --- a/tools/traffic_annotation/summary/grouping.xml +++ b/tools/traffic_annotation/summary/grouping.xml
@@ -330,6 +330,9 @@ <traffic_annotation unique_id="cros_recovery_image_download"/> <traffic_annotation unique_id="download_recovery_component"/> </sender> + <sender name="Crash Reports"> + <traffic_annotation unique_id="javascript_report_error"/> + </sender> <sender name="Chrome Performance, Feedback, and Usage Statistics"> <traffic_annotation unique_id="background_performance_tracer"/> <traffic_annotation unique_id="chrome_feedback_report_app"/>
diff --git a/ui/gl/direct_composition_surface_win.cc b/ui/gl/direct_composition_surface_win.cc index aae4825f..1ec54927 100644 --- a/ui/gl/direct_composition_surface_win.cc +++ b/ui/gl/direct_composition_surface_win.cc
@@ -38,6 +38,8 @@ bool g_supports_overlays = false; // Whether the DecodeSwapChain is disabled or not. bool g_decode_swap_chain_disabled = false; +// Whether to force the nv12 overlay support. +bool g_force_nv12_overlay_support = false; // The lock to guard g_overlay_caps_valid and g_supports_overlays. base::Lock& GetOverlayLock() { @@ -295,6 +297,12 @@ &bgra8_overlay_support_flags, &rgb10a2_overlay_support_flags, &overlay_monitor_size); + if (g_force_nv12_overlay_support) { + supports_overlays = true; + nv12_overlay_support_flags = DXGI_OVERLAY_SUPPORT_FLAG_SCALING; + overlay_format_used = DXGI_FORMAT_NV12; + } + if (supports_overlays != SupportsOverlays() || overlay_format_used != g_overlay_format_used) { // Record the new histograms @@ -639,6 +647,13 @@ g_enable_bgra8_overlays_with_yuv_overlay_support = true; } +// static +void DirectCompositionSurfaceWin::ForceNV12OverlaySupport() { + // This has to be set before initializing overlay caps. + DCHECK(!OverlayCapsValid()); + g_force_nv12_overlay_support = true; +} + bool DirectCompositionSurfaceWin::Initialize(GLSurfaceFormat format) { d3d11_device_ = QueryD3D11DeviceObjectFromANGLE(); if (!d3d11_device_) {
diff --git a/ui/gl/direct_composition_surface_win.h b/ui/gl/direct_composition_surface_win.h index 799ffa8..0a608315 100644 --- a/ui/gl/direct_composition_surface_win.h +++ b/ui/gl/direct_composition_surface_win.h
@@ -100,6 +100,10 @@ // unsupported. So allow manually enabling BGRA8 overlay support. static void EnableBGRA8OverlaysWithYUVOverlaySupport(); + // Forces to enable NV12 overlay support regardless of the query results from + // IDXGIOutput3::CheckOverlaySupport(). + static void ForceNV12OverlaySupport(); + // GLSurfaceEGL implementation. bool Initialize(GLSurfaceFormat format) override; void Destroy() override;
diff --git a/ui/views/controls/link.cc b/ui/views/controls/link.cc index 0ed41be..7dc1a389 100644 --- a/ui/views/controls/link.cc +++ b/ui/views/controls/link.cc
@@ -85,7 +85,7 @@ if (GetEnabled() && (event.IsLeftMouseButton() || event.IsMiddleMouseButton()) && HitTestPoint(event.location())) - OnClick(event.flags()); + OnClick(event); } void Link::OnMouseCaptureLost() { @@ -101,7 +101,7 @@ return false; SetPressed(false); - OnClick(event.flags()); + OnClick(event); return true; } @@ -112,7 +112,7 @@ if (event->type() == ui::ET_GESTURE_TAP_DOWN) { SetPressed(true); } else if (event->type() == ui::ET_GESTURE_TAP) { - OnClick(event->flags()); + OnClick(*event); } else { SetPressed(false); return; @@ -182,10 +182,10 @@ } } -void Link::OnClick(int event_flags) { +void Link::OnClick(const ui::Event& event) { RequestFocus(); - if (!callback_.is_null()) - callback_.Run(event_flags); + if (callback_) + callback_.Run(event); } void Link::RecalculateFont() {
diff --git a/ui/views/controls/link.h b/ui/views/controls/link.h index b7ae40b..802ce73 100644 --- a/ui/views/controls/link.h +++ b/ui/views/controls/link.h
@@ -32,7 +32,7 @@ // A callback to be called when the link is clicked. Closures are also // accepted; see below. - using ClickedCallback = base::RepeatingCallback<void(int event_flags)>; + using ClickedCallback = base::RepeatingCallback<void(const ui::Event& event)>; explicit Link(const base::string16& title = base::string16(), int text_context = style::CONTEXT_LABEL, @@ -44,9 +44,10 @@ // way. void set_callback(base::RepeatingClosure callback) { // Adapt this closure to a ClickedCallback by discarding the extra arg. - callback_ = base::BindRepeating( - [](base::RepeatingClosure closure, int) { closure.Run(); }, - std::move(callback)); + callback_ = + base::BindRepeating([](base::RepeatingClosure closure, + const ui::Event& event) { closure.Run(); }, + std::move(callback)); } void set_callback(ClickedCallback callback) { callback_ = std::move(callback); @@ -76,7 +77,7 @@ private: void SetPressed(bool pressed); - void OnClick(int event_flags); + void OnClick(const ui::Event& event); void RecalculateFont();
diff --git a/ui/views/controls/link_unittest.cc b/ui/views/controls/link_unittest.cc index 4ae16fa0..490079e 100644 --- a/ui/views/controls/link_unittest.cc +++ b/ui/views/controls/link_unittest.cc
@@ -53,8 +53,7 @@ TEST_F(LinkTest, TestLinkClick) { bool link_clicked = false; link()->set_callback(base::BindRepeating( - [](bool* link_clicked, int event_flags) { *link_clicked = true; }, - &link_clicked)); + [](bool* link_clicked) { *link_clicked = true; }, &link_clicked)); link()->SizeToPreferredSize(); gfx::Point point = link()->bounds().CenterPoint(); ui::MouseEvent release(ui::ET_MOUSE_RELEASED, point, point, @@ -67,8 +66,7 @@ TEST_F(LinkTest, TestLinkTap) { bool link_clicked = false; link()->set_callback(base::BindRepeating( - [](bool* link_clicked, int event_flags) { *link_clicked = true; }, - &link_clicked)); + [](bool* link_clicked) { *link_clicked = true; }, &link_clicked)); link()->SizeToPreferredSize(); gfx::Point point = link()->bounds().CenterPoint(); ui::GestureEvent tap_event(point.x(), point.y(), 0, ui::EventTimeForNow(),
diff --git a/ui/views/controls/menu/menu_controller.cc b/ui/views/controls/menu/menu_controller.cc index 036d1b1..e6a9668 100644 --- a/ui/views/controls/menu/menu_controller.cc +++ b/ui/views/controls/menu/menu_controller.cc
@@ -2389,13 +2389,16 @@ // This is a top-level menu, position it relative to the anchor bounds. const gfx::Rect& anchor_bounds = state_.initial_bounds; + using MenuPosition = MenuItemView::MenuPosition; + // First the size gets reduced to the possible space. if (!monitor_bounds.IsEmpty()) { int max_width = monitor_bounds.width(); int max_height = monitor_bounds.height(); // In case of bubbles, the maximum width is limited by the space // between the display corner and the target area + the tip size. - if (state_.anchor == MenuAnchorPosition::kBubbleAbove) { + if (state_.anchor == MenuAnchorPosition::kBubbleAbove || + item->actual_menu_position() == MenuPosition::kAboveBounds) { // Don't consider |border_and_shadow_insets| because when the max size // is enforced, the scroll view is shown and the md shadows are not // applied. @@ -2432,6 +2435,7 @@ y = anchor_bounds.bottom() - border_and_shadow_insets.top() + menu_config.touchable_anchor_offset; } + item->set_actual_menu_position(MenuPosition::kAboveBounds); } else if (state_.anchor == MenuAnchorPosition::kBubbleLeft || state_.anchor == MenuAnchorPosition::kBubbleRight) { if (state_.anchor == MenuAnchorPosition::kBubbleLeft) { @@ -2461,18 +2465,35 @@ const int y_below = anchor_bounds.y() - border_and_shadow_insets.top(); const int y_above = anchor_bounds.bottom() - menu_size.height() + border_and_shadow_insets.bottom(); - if (y_below + menu_size.height() <= monitor_bounds.bottom()) { + + const bool able_to_show_below = + (y_below + menu_size.height() <= monitor_bounds.bottom()); + const bool able_to_show_above = (y_above >= monitor_bounds.y()); + + // Respect the actual menu position calculated earlier if possible, to + // prevent changing positions during menu size updates. + + if (item->actual_menu_position() == MenuPosition::kBelowBounds && + able_to_show_below) { + y = y_below; + } else if (item->actual_menu_position() == MenuPosition::kAboveBounds && + able_to_show_above) { + y = y_above; + } else if (able_to_show_below) { // Show below the anchor. Align the top of the menu with the top of the // anchor. y = y_below; - } else if (y_above >= monitor_bounds.y()) { + item->set_actual_menu_position(MenuPosition::kBelowBounds); + } else if (able_to_show_above) { // No room below, but there is room above. Show above the anchor. Align // the bottom of the menu with the bottom of the anchor. y = y_above; + item->set_actual_menu_position(MenuPosition::kAboveBounds); } else { // No room above or below. Show as low as possible. Align the bottom of // the menu with the bottom of the screen. y = monitor_bounds.bottom() - menu_size.height(); + item->set_actual_menu_position(MenuPosition::kBestFit); } } // The above adjustments may have shifted a large menu off the screen.
diff --git a/ui/views/controls/menu/menu_controller_unittest.cc b/ui/views/controls/menu/menu_controller_unittest.cc index 9a8ec213..4ac27d0 100644 --- a/ui/views/controls/menu/menu_controller_unittest.cc +++ b/ui/views/controls/menu/menu_controller_unittest.cc
@@ -988,6 +988,70 @@ ResetSelection(); } +// Verifies that the context menu bubble should prioritize its cached menu +// position (above or below the anchor) after its size updates +// (https://crbug.com/1126244). +TEST_F(MenuControllerTest, VerifyMenuBubblePositionAfterSizeChanges) { + constexpr gfx::Rect monitor_bounds(0, 0, 500, 500); + constexpr gfx::Size menu_size(100, 200); + const gfx::Insets border_and_shadow_insets = + BubbleBorder::GetBorderAndShadowInsets( + MenuConfig::instance().touchable_menu_shadow_elevation); + + // Calculate the suitable anchor point to ensure that if the menu shows below + // the anchor point, the bottom of the menu should be one pixel off the + // bottom of the display. It means that there is insufficient space for the + // menu below the anchor. + const gfx::Point anchor_point(monitor_bounds.width() / 2, + monitor_bounds.bottom() + 1 - + menu_size.height() + + border_and_shadow_insets.top()); + + MenuBoundsOptions options; + options.menu_anchor = MenuAnchorPosition::kBubbleRight; + options.monitor_bounds = monitor_bounds; + options.anchor_bounds = gfx::Rect(anchor_point, gfx::Size()); + + // Case 1: There is insufficient space for the menu below `anchor_point` and + // there is no cached menu position. The menu should show above the anchor. + { + options.menu_size = menu_size; + ASSERT_GT(options.anchor_bounds.y() - border_and_shadow_insets.top() + + menu_size.height(), + monitor_bounds.bottom()); + CalculateBubbleMenuBounds(options); + EXPECT_EQ(MenuItemView::MenuPosition::kAboveBounds, + menu_item()->ActualMenuPosition()); + } + + // Case 2: There is insufficient space for the menu below `anchor_point`. The + // cached position is below the anchor. The menu should show above the anchor. + { + options.menu_size = menu_size; + options.menu_position = MenuItemView::MenuPosition::kBelowBounds; + CalculateBubbleMenuBounds(options); + EXPECT_EQ(MenuItemView::MenuPosition::kAboveBounds, + menu_item()->ActualMenuPosition()); + } + + // Case 3: There is enough space for the menu below `anchor_point`. The cached + // menu position is above the anchor. The menu should show above the anchor. + { + // Shrink the menu size. Verify that there is enough space below the anchor + // point now. + constexpr gfx::Size updated_size(menu_size.width(), menu_size.height() / 2); + options.menu_size = updated_size; + EXPECT_LE(options.anchor_bounds.y() - border_and_shadow_insets.top() + + updated_size.height(), + monitor_bounds.bottom()); + + options.menu_position = MenuItemView::MenuPosition::kAboveBounds; + CalculateBubbleMenuBounds(options); + EXPECT_EQ(MenuItemView::MenuPosition::kAboveBounds, + menu_item()->ActualMenuPosition()); + } +} + // Tests that opening the menu and pressing 'Home' selects the first menu item. TEST_F(MenuControllerTest, FirstSelectedItem) { SetPendingStateItem(menu_item()->GetSubmenu()->GetMenuItemAt(0));
diff --git a/ui/views/controls/styled_label.cc b/ui/views/controls/styled_label.cc index fa2388f32..8429239f 100644 --- a/ui/views/controls/styled_label.cc +++ b/ui/views/controls/styled_label.cc
@@ -37,7 +37,7 @@ base::RepeatingClosure callback) { // Adapt this closure to a Link::ClickedCallback by discarding the extra arg. return CreateForLink(base::BindRepeating( - [](base::RepeatingClosure closure, int) { closure.Run(); }, + [](base::RepeatingClosure closure, const ui::Event&) { closure.Run(); }, std::move(callback))); }
diff --git a/ui/views/layout/flex_layout.cc b/ui/views/layout/flex_layout.cc index bd4e32e..045daa6 100644 --- a/ui/views/layout/flex_layout.cc +++ b/ui/views/layout/flex_layout.cc
@@ -507,6 +507,7 @@ const base::Optional<int> available_cross = GetAvailableCrossAxisSize(*data, view_index, bounds); + SetCrossAxis(&child_layout.available_size, orientation(), available_cross); flex_child.preferred_size = GetPreferredSizeForRule(flex_child.flex.rule(), child, available_cross); @@ -516,25 +517,19 @@ flex_child.current_size = GetCurrentSizeForRule(flex_child.flex.rule(), child, NormalizedSizeBounds(0, available_cross)); - SetCrossAxis(&child_layout.available_size, orientation(), - available_cross); - DCHECK_GE(flex_child.preferred_size.main(), flex_child.current_size.main()) << " in " << child->GetClassName(); - - // Keep track of non-hidden flex controls. - const bool can_flex = - flex_child.flex.weight() > 0 || - flex_child.current_size.main() < flex_child.preferred_size.main(); - if (can_flex) - (*flex_order_to_index)[flex_child.flex.order()].push_back(view_index); - } else { // All non-flex or unbounded controls get preferred size. flex_child.current_size = flex_child.preferred_size; } + // Keep track of non-hidden flex controls. + if (flex_child.flex.weight() > 0 || + flex_child.current_size.main() < flex_child.preferred_size.main()) + (*flex_order_to_index)[flex_child.flex.order()].push_back(view_index); + child_layout.visible = flex_child.current_size.main() > 0; } }
diff --git a/ui/views/widget/widget.h b/ui/views/widget/widget.h index 032f77d..bb19a2cc 100644 --- a/ui/views/widget/widget.h +++ b/ui/views/widget/widget.h
@@ -144,14 +144,16 @@ // reason for menu or for the main Chrome browser, as we have no reason to // specifically differentiate those yet. // - // Add additional values as needed. + // Add additional values as needed. Do not change any existing values, as this + // enum is logged to UMA. enum class ClosedReason { - kUnspecified = 0, // No reason was given for the widget closing. - kEscKeyPressed, // The ESC key was pressed to cancel the widget. - kCloseButtonClicked, // The [X] button was explicitly clicked. - kLostFocus, // The widget destroyed itself when it lost focus. - kCancelButtonClicked, // The widget's cancel button was clicked. - kAcceptButtonClicked // The widget's done/accept button was clicked. + kUnspecified = 0, // No reason was given for the widget closing. + kEscKeyPressed = 1, // The ESC key was pressed to cancel the widget. + kCloseButtonClicked = 2, // The [X] button was explicitly clicked. + kLostFocus = 3, // The widget destroyed itself when it lost focus. + kCancelButtonClicked = 4, // The widget's cancel button was clicked. + kAcceptButtonClicked = 5, // The widget's done/accept button was clicked. + kMaxValue = kAcceptButtonClicked }; struct VIEWS_EXPORT InitParams {
diff --git a/ui/webui/resources/cr_components/chromeos/BUILD.gn b/ui/webui/resources/cr_components/chromeos/BUILD.gn index 87fb0e39..12583695 100644 --- a/ui/webui/resources/cr_components/chromeos/BUILD.gn +++ b/ui/webui/resources/cr_components/chromeos/BUILD.gn
@@ -9,21 +9,17 @@ group("closure_compile") { deps = [ "bluetooth:closure_compile", + "bluetooth:closure_compile_module", "cellular_setup:closure_compile", + "cellular_setup:closure_compile_module", "multidevice_setup:closure_compile", "network:closure_compile", + "network:closure_compile_module", "network_health:closure_compile", - "quick_unlock:closure_compile", - "smb_shares:closure_compile", - - # Targets for auto-generated Polymer 3 JS Modules - # TODO: Uncomment as Polymer3 migration makes progress. - # "network:closure_compile_module", - - "quick_unlock:closure_compile_module", - "cellular_setup:closure_compile_module", - "bluetooth:closure_compile_module", "network_health:closure_compile_module", + "quick_unlock:closure_compile", + "quick_unlock:closure_compile_module", + "smb_shares:closure_compile", "smb_shares:closure_compile_module", ] }
diff --git a/ui/webui/resources/cr_components/chromeos/network/BUILD.gn b/ui/webui/resources/cr_components/chromeos/network/BUILD.gn index 5db23a0..3e1dec3 100644 --- a/ui/webui/resources/cr_components/chromeos/network/BUILD.gn +++ b/ui/webui/resources/cr_components/chromeos/network/BUILD.gn
@@ -274,7 +274,7 @@ ":network_property_list_mojo.m", # ":network_proxy.m", # ":network_proxy_exclusions.m", - # ":network_proxy_input.m", + ":network_proxy_input.m", ":network_select.m", ":network_shared_css.m", ":network_siminfo.m", @@ -527,7 +527,11 @@ js_library("network_proxy_input.m") { sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/network/network_proxy_input.m.js" ] deps = [ - # TODO: Fill those in. + ":network_shared_css.m", + ":onc_mojo.m", + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/cr_elements/cr_input:cr_input.m", + "//ui/webui/resources/js:i18n_behavior.m", ] extra_deps = [ ":network_proxy_input_module" ] } @@ -734,6 +738,8 @@ js_file = "network_proxy_input.js" html_file = "network_proxy_input.html" html_type = "dom-module" + auto_imports = cr_components_chromeos_auto_imports + namespace_rewrites = cr_components_chromeos_namespace_rewrites } polymer_modulizer("network_select") {
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_proxy_input.html b/ui/webui/resources/cr_components/chromeos/network/network_proxy_input.html index 6e4dcff..c4e3bb4 100644 --- a/ui/webui/resources/cr_components/chromeos/network/network_proxy_input.html +++ b/ui/webui/resources/cr_components/chromeos/network/network_proxy_input.html
@@ -3,6 +3,7 @@ <link rel="import" href="../../../cr_elements/cr_input/cr_input.html"> <link rel="import" href="../../../html/i18n_behavior.html"> <link rel="import" href="network_shared_css.html"> +<link rel="import" href="onc_mojo.html"> <dom-module id="network-proxy-input"> <template>
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_proxy_input.js b/ui/webui/resources/cr_components/chromeos/network/network_proxy_input.js index 7d649f9..40c3f6f4 100644 --- a/ui/webui/resources/cr_components/chromeos/network/network_proxy_input.js +++ b/ui/webui/resources/cr_components/chromeos/network/network_proxy_input.js
@@ -8,8 +8,6 @@ * event is fired with the combined url and port values passed as a single * string, url:port. */ -(function() { -'use strict'; Polymer({ is: 'network-proxy-input', @@ -66,4 +64,3 @@ this.fire('proxy-input-change', this.value); } }); -})();
diff --git a/ui/webui/resources/cr_components/chromeos/network/onc_mojo.js b/ui/webui/resources/cr_components/chromeos/network/onc_mojo.js index d9dd579..dc03da1 100644 --- a/ui/webui/resources/cr_components/chromeos/network/onc_mojo.js +++ b/ui/webui/resources/cr_components/chromeos/network/onc_mojo.js
@@ -2,8 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// clang-format off +// #import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js'; +// #import 'chrome://resources/mojo/services/network/public/mojom/ip_address.mojom-lite.js'; +// #import 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/network_types.mojom-lite.js'; +// #import 'chrome://resources/mojo/mojo/public/mojom/base/time.mojom-lite.js'; +// #import 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom-lite.js'; + // #import {assert, assertNotReached} from 'chrome://resources/js/assert.m.js'; -// #import {loadTimeData} from '../../../js/load_time_data.m.js'; +// #import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; +// cland-format on /** * @fileoverview Utilities supporting network_config.mojom types. The strings
diff --git a/ui/webui/resources/cr_components/cr_components_resources_v3.grdp b/ui/webui/resources/cr_components/cr_components_resources_v3.grdp index 3a5d9c4..5455dc06 100644 --- a/ui/webui/resources/cr_components/cr_components_resources_v3.grdp +++ b/ui/webui/resources/cr_components/cr_components_resources_v3.grdp
@@ -108,6 +108,10 @@ file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/network/network_property_list_mojo.m.js" use_base_dir="false" type="BINDATA" /> + <include name="IDR_WEBUI_CHROMEOS_NETWORK_PROXY_INPUT_M_JS" + file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/network/network_proxy_input.m.js" + use_base_dir="false" + type="BINDATA" /> <include name="IDR_WEBUI_CHROMEOS_NETWORK_SELECT_M_JS" file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/network/network_select.m.js" use_base_dir="false"
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IBrowser.aidl b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IBrowser.aidl index 40eb420..4759677 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IBrowser.aidl +++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IBrowser.aidl
@@ -38,5 +38,6 @@ ITab createTab() = 11; void setTopViewAndScrollingBehavior(in IObjectWrapper view, in int minHeight, - in boolean pinToContentTop, in boolean animate) = 12; + in boolean onlyExpandControlsAtPageTop, + in boolean animate) = 12; }
diff --git a/weblayer/public/java/org/chromium/weblayer/Browser.java b/weblayer/public/java/org/chromium/weblayer/Browser.java index 0d2e9d18..5265dd89 100644 --- a/weblayer/public/java/org/chromium/weblayer/Browser.java +++ b/weblayer/public/java/org/chromium/weblayer/Browser.java
@@ -224,23 +224,25 @@ * @param view The new top-view, or null to remove the view. * @param minHeight The minimum height in pixels that the top controls can scoll up to. A value * of 0 means the top-view should scroll entirely off screen. - * @param pinToContentTop Whether the top-view should only be expanded when the web + * @param onlyExpandControlsAtPageTop Whether the top-view should only be expanded when the web * content is scrolled to the top. A true value makes the top-view behave as though it - * were inserted into the top of the page content. + * were inserted into the top of the page content. If true, the top-view should NOT be + * used to display the URL, as this will prevent it from expanding in security-sensitive + * contexts where the URL should be visible to the user. * @param animate Whether or not any height/visibility changes that result from this call * should be animated. * * @since 86 */ - public void setTopView( - @Nullable View view, int minHeight, boolean pinToContentTop, boolean animate) { + public void setTopView(@Nullable View view, int minHeight, boolean onlyExpandControlsAtPageTop, + boolean animate) { ThreadCheck.ensureOnUiThread(); if (WebLayer.getSupportedMajorVersionInternal() < 86) { throw new UnsupportedOperationException(); } try { mImpl.setTopViewAndScrollingBehavior( - ObjectWrapper.wrap(view), minHeight, pinToContentTop, animate); + ObjectWrapper.wrap(view), minHeight, onlyExpandControlsAtPageTop, animate); } catch (RemoteException e) { throw new APICallException(e); }